zoukankan      html  css  js  c++  java
  • ansible

    自动化运维工具

    • shell脚本
    • ansible
    • saltstack

    服务器部署的流程

    服务器 ->安装操作系统 -> 环境部署 -> 软件部署 -> 配置部署 ->启动服务 -> 加入集群


    Ansible基础架构

    1. 连接插件(connection plugin)  连接客户端
    2. 主机清单(Host Inventory)   定义ansible需要操作的主机的范围
    3. 核心模块 (Core Modules) 依赖于ansilbe自带的模块执行ansible命令
    4. 自定义模块 (Custom Modules) 自定义模块执行ansible命令
    5. 任务剧本 (playbooks) ansible的配置文件, 将多个任务定义在剧本中, 由ansible自动执行
    6. 插件 (plugins) 邮件插件, 日志插件
    


    Ansible安装配置


    准备机器

    192.168.43.3 管控节点
    192.168.43.14 被管控节点
    192.168.43.15 被管控节点
    192.168.43.16 被管控节点
    192.168.43.17 被管控节点
    

    管控节点安装ansilbe

    $ curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    $ yum install -y ansible
    

    ssh部署公钥到被管控节点

    $ ssh-copy-id  -i ~/.ssh/id_rsa.pub  root@192.168.43.14
    $ ssh-copy-id  -i ~/.ssh/id_rsa.pub  root@192.168.43.15
    $ ssh-copy-id  -i ~/.ssh/id_rsa.pub  root@192.168.43.16
    $ ssh-copy-id  -i ~/.ssh/id_rsa.pub  root@192.168.43.17
    

    ansible 命令格式

    Usage: ansible <host-pattern> [options]
    -a MODULE_ARGS  模块参数
    -C, --check  检查语法
    -f FORKS 并发
    --list-hosts  列出主机列表
    -m MODULE_NAME  模块名字
    

    ssh 认证方式

    • 密码

    • 秘钥

      • ssh-keygen 生成密钥对

      • ssh-copy-id 复制公钥到远程主机

      • 私钥加密,公钥解密


    查看ansible生成的文件

    rpm -ql ansible
    /etc/ansible
    /etc/ansible/ansible.cfg  # ansible 配置文件
    /etc/ansible/hosts
    /etc/ansible/roles
    

    ansible第一条命令

    ansible 192.168.43.15 -m ping   ping一台机器
    ansible 192.168.43.15,192.168.43.16 -m ping   ping多台机器
    ansible all -m ping  ping所有机器
    ansible web -m ping  ping一个组
    ansible "web:&db" -m ping ping web组和db组的都有的机器(交集)
    ansible "web:db" -m ping  ping web组和db组的所有的机器(并集)
    ansible 'web:!db' -m ping  ping web组中有的但是db组中没有的机器
    ansible'!web:db' -m ping   ping web组中没有的但是db中有的机器
    

    hosts文件内容

    # It should live in /etc/ansible/hosts
    #
    #   - Comments begin with the '#' character   #是注释
    #   - Blank lines are ignored    空行被忽略
    #   - Groups of hosts are delimited by [header] elements   []表示主机组
    #   - You can enter hostnames or ip addresses    可以输入主机名或者ip地址
    #   - A hostname/ip can be a member of multiple groups   一台主机可以被分配多个组
    www[001:006].example.com  www001到www006.example.com 
    

    host-pattern格式

    • 单个机器
    • 多个机器, 逗号隔开
    • 全部机器,all
    • 可以写一个分组
    • 可以写多个分组
      • 并集
        • 逗号隔开
        • 冒号隔开
      • 交集: :& 隔开
      • 差集: 两台主机组之间用冒号隔开,在不包括差集机器的主机组前加上& (比如 web:!db,!web:db )

    查看模块帮助信息

    ansible-doc [-l|-F|-s] [options] [-t <plugin type> ] [plugin]
    -j 以json格式显示所有模块信息
    -l 列出所有模块
    -s 显示模块的摘要信息
    # 不加任何选项,则显示模块的所有帮助信息
    

    ansible 特性: 幂等性

    同样的数据不进行第二次相同的操作


    命令相关

    removes和creates 起到判断的作用 (判断的是被管控机上的文件是否存在

    • removes: 如果条件存在,则执行后面的命令
    • creates: 如果条件存在,则不执行后面的命令
    ansible web -a 'ls'  
    ansible web -a 'chdir=/tmp pwd'  #先切换目录, 再执行命令pwd 一般情况下在编译时候使用
    ansible web -a 'creates=/tmp pwd'   #如果creates的文件存在,则不执行后面的命令
    ansible web -a 'removes=/tmp pwd'   #如果creates的文件存在,则执行后面的命令
    ansible web -a 'removes=/tmp mkdir /data' #会执行后面的mkdir命令
    ansible web -a 'creates=/data2 mkdir /data2'  #会执行后面的mkdir 命令
    

    补充

    查看用户是否被创建成功
    tail -1 /etc/passwd
    tail -1 /etc/shadow
    id <用户名>
    echo '<密码>' |passwd --stdin <用户名>  非交互式设置密码
    

    shell

    < > | ; & $  这些特殊字符command不支持
    ansible web -a "useradd alex"   对web组的机器创建用户alex
    ansible web -m shell -a 'echo '1'|passwd --stdin alex'  设置alex的密码
    ansible 192.168.43.15 -m shell -a '/root/a.sh'  执行目标机器上的shell脚本,前提是脚本有可执行权限
    ansible 192.168.43.15 -m shell -a '/root/a.py'  执行目标机器上python脚本,前提是脚本有可执行权限
    

    script

    ansible db -m script -a '/root/m.sh' 执行管控机上的文件
    ansible web -m script -a 'creates=/root/a.sh /root/m.sh'  #查看的是被管控机上的文件是否存在
    

    文件相关的模块


    copy

    ansible db -m copy -a 'dest=/tmp/a.sh src=/root/m.sh'   复制文件到远程主机
    ansible db -m copy -a 'dest=/tmp/a.sh src=/root/m.sh backup=yes' 复制文件并备份远程文件
    #如果之前执行过一次 ansible db -m copy -a 'dest=/tmp/a.sh src=/root/m.sh‘, 并且m.sh里的数据没有任何改变, 此时再加上参数backup=yes, 根据ansible幂等性特性,执行不成功
    
    nsible web -m copy -a 'dest=/tmp/a.sh src=/root/m.sh owner=alex mode=700' 修改复制后的文件的属主和权限
    ansible web -m copy -a "src=/etc/init.d dest=/tmp"  复制目录到远程主机
    ansible web -m shell -a "ls  /tmp"  复制目录里面的文件到远程主机
    ansible web -m copy -a "src=/etc/ansible dest=/tmp owner=alex"  复制目录到远程主机,并修改目录的属主,并且里面文件的属主也被修改了(类似于 chmod -R )
    ansible web -m copy -a "content='大弦嘈嘈如急雨,小弦切切如私语' dest=/tmp/b.txt  直接将content里面的内容添加到dest的文件里面,如果dest文件里面有内容,则内容被替换
    

    file


    补充

    ln -s <源文件地址> <目标地址>  创建软链接
    ln <源文件地址> <目标地址> 创建应链接
    
    ansible cache -m file -a "path=/tmp/wupeiqi state=directory"   创建一个目录
    ansible cache -m file -a "path=/tmp/wupeiqi.txt state=touch"   创建一个文件
    ansible cache -m file -a "path=/tmp/t state=link src=/etc/init.d"   创建软链接 path是目标文件  src是源文件
    ansible cache -m file -a "path=/tmp/t state=absent"  删除文件(linux中一切皆文件,软链接也是文件的一种)
    

    fetch

    fetch 用来拉去被管控机的文件或者目录,每个被管控机创建一个文件夹,并且保留原来的目录结构

    ansible web -m fetch -a "dest=/tmp src=/var/log/cron"软件包相关
    

    软件包相关

    yum

    回顾

    • rpm与yum的区别
      • redhat package manage
    • yum 源配置方式
    [epel]  #组名
    name=Extra Packages for Enterprise Linux 7 - $basearch  #名字
    baseurl=http://mirrors.aliyun.com/epel/7/$basearch   #url,可以写http,https,ftp,file:
    failovermethod=priority
    enabled=1   #是否启用, 1表示启用,0表示不启用
    gpgcheck=0  #是否校验gpgkey这个文件, 0表示不校验,1表示校验
    gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
    

    为什么要校验: 一般情况下,用rpm的包,会用gpgkey去加密,然后拿到这个key对它进行解密,证明这个文件没有问题,才能去装, yum自动完成这一步操作


    • yum 安装包组
    yum grouplist
    yum groupinstsall -y 'Development Tools'
    rpm -qa python2-pip  查看软件包是否安装
    
    ansible web -m yum -a 'name=python2-pip'  安装python2-pip包
    ansible web -m yum -a 'name=@Development Tools' 安装包组
    ansible web -m yum -a 'name=redis state=absent' 卸载
    

    pip

    pip freeze > a.txt 给当前python环境的包打快照
    pip install -r a.txt  安装文件里面所有的包
    pip list  查询所有安装的包以及版本号
    
    ansible web -m pip -a 'name=flask'  安装pip包
    

    service

    service nginx start|stop|restart  #centos6
    chkconfig add nginx  
    chkconfig nginx on  设置开机启动
    chkconfig --list
    
    systemctl start|stop|restart nginx #centos7
    systemctl enable nginx #设置开机自启动
    ss -tnlp  查看启动的端口
    
    ansible web -m service -a 'name=nginx state=started'  #启动服务
    ansible web -m service -a 'name=nginx state=stopped'  #停止服务
    

    cron

    分 时 日 月 周 job
    1  0  * *  *    
    *  *  * *  * tar zcvf /tmp/etc.tar.gz /etc/ 这是一个错误的示范
    2 */3 * *  *  每隔3小时第2分钟做某件事
    0 15-17 * * 2,3  每周二,周三的15-17点的0分做某件事
    
    day: 天
    hour: 小时
    job: 执行的任务
    minute: 分钟
    month: 月
    name: 名字
    weekday: 周
    ansible web -m cron -a 'minute=09 job="touch /tmp/alex.txt" name=touchfile'   #新建计划任务
    ansible web -m cron -a 'minute=12 job="touch /tmp/alex.txt" name=touchfile disabled=yes' 
    #注释掉计划任务
    ansible web -m cron -a 'name=touchfile state=absent'  #删除计划任务
    

    用户相关

    用户:
    超级用户 root 0
    系统用户 不能登录 201-999 centos7  1-499 centos6 
    普通用户  可以登入系统 1000-60000 centos7 500-65535 centos6
    组: 
    超级组: root 0
    系统组: 201-999 centos7  1-499 centos6 
    普通组: 1000-60000 centos7 500-65535 centos6
    #在 /etc/login.defs 中定义
    
    useradd -d /opt/alex alex  指定用户的家目录
    useradd -M -d /opt/alex2 alex2  不创建用户的家目录
    userdel -r alex3  删除用户并删除用户的家目录
    

    用户和组的关系

    • 一对一 主组
    • 一对多 附加组
    • 多对多

    user

    ansible db -m user -a "name=mysql home=/opt/mysql groups=root uid=2000"  创建用户,并指定用户的家目录,并指定用户的附加组,指定用户的uid
    ansible db -m user -a "name=mysql state=absent" 删除用户,但是不删除用户的家目录
    ansible db -m user -a "name=mysql state=absent remove=yes"  删除用户并删除用户的家目录
    

    setup

    ansible_all_ipv4_addresses  所有ipv4地址
    ansible_all_ipv6_addresses  所有ipv6地址
    ansible_architecture   系统的架构
    ansible_date_time   系统的时间
    ansible_default_ipv4  默认的ipv4的值
    ansible_distribution  系统名称
    ansible_distribution_file_variety  系统的家族
    ansible_distribution_major_version  系统的版本
    ansible_domain  主机所在的域
    ansible_fqdn  系统的主机名
    ansible_hostname  系统的主机名,简写
    ansible_os_family  系统的家族信息
    ansible_processor_cores  cpu的核数(单核或者双核)
    ansible_processor_count  cpu的颗数(几个CPU,1个或者2个)
    ansible_processor_vcpus  cpu的核心总数
    

    group

    ansible db -m group -a "name=wusir"    创建一个普通组
    ansible db -m group -a "name=wusir state=absent"  删除组
    #/etc/group  存储组信息
    

    创建一个用户alex

    ansible web -m user -a ‘name=alex’

    创建一个用户wusir

    ansible web -m user -a ‘name=wusir’

    复制 /etc/fstab 文件到 /tmp目录下面

    ansible web -m copy -a ‘dest=/tmp src=/etc/fstab’

    安装nignx

    ansible web -m yum ‘name=nginx’

    安装redis

    ansible web -m yum -a ‘name=redis’

    并新建crontab 每天的晚上12点重启nginx

    ansible web -m cron -a ‘minute=0 hour=12 job=systemctl restart nginx name=restart nginx’


    playbook剧本

    yaml

    列表: -
    字典: key: value
    后缀名: yaml, yml
    

    ansible-playbook的命令格式

    ansible-playbook [options] playbook.yml [playbook2 ...]
    -C, --check  干跑
    -f FORKS  用来做并发
    --list-hosts 列出主机列表
    --syntax-check 语法检查
    

    一个yml文件里可以写多个列表,列表间用列表(-)隔开, 一般情况下,一个文件里就写一个剧本,易维护


    单个 playbook

    ---
    - hosts: cache
      remote_user: root
      tasks:
      - name: create user
        user: name=alex
      - name: create group
        group: name=wusir
      - name: install redis
        yum: name=redis
        执行过程: 所有机器都执行完第一个任务,再去执行第二个任务
    

    playbook的参数

    - hosts: web
      remote_user: root
      tasks: 
      - name: create {{ user }}
        user: name={{ user }}
    

    传参方式

    • 第一种传参方式: -e
    ansible-playbook v3.yml -e user=alexsb
    

    • 第二种传参方式: hosts文件里面主机后面写(/etc/ansible/hosts)
    [web]
    192.168.43.14 user=alexsb2
    192.168.43.15 user=alexsb3
    

    • 第三种传参方式: hosts文件里面写 [groupname:vars]
    [web]
    192.168.43.14 
    192.168.43.15
    [web:vars]
    user=alexsb4
    

    • 第四种传参方式:playbook文件中vars来指定
    - hosts: web
      remote_user: root
      vars:
      - user: alexsb5
      tasks:
      - name: create {{ user }}
        user: name={{ user }}
    

    • 第五种传参方式: 通过register注册,使用的时候要使用参数的stdout值
    - hosts: web
      remote_user: root
      tasks: 
      - name: sum
        shell: echo 3+4 |bc
        register: user
      - name: create{{ user }}
        user: name=alexsb{{ user.stdout }}
    

    优先级

    -e > playbook的vars > host文件
    

    条件判断(when)

    - hosts: web
      tasks: 
      - name: file
        copy: content="凿壁偷光" dest=/tmp/wg.txt
        when: num == "2"
      - name: file
        copy: content="耍流氓" dest=/tmp/wg.txt
        when: num == "3"
    
    - hosts: cache
      tasks: 
      - name: create file
        copy: content="小弦切切如私语" dest=/tmp/ppx.txt
        when: ansible_python.version.major==1  #取字典内的值
    

    修改redis 配置文件

    bind 0.0.0.0   修改绑定的ip
    requirepass s14  为redis设置密码s14
    
    #部署redis并启动服务
    - hosts: cache
      remote_user: root
      tasks: 
      - name: install
        yum: name=redis
      - name: copyfile
        copy: dest=/etc/redis.conf src=/root/yaml/redis.conf
      - name: start redis
        service: name=redis state=started
    

    标签

    - hosts: cache
      remote_user: root
      tasks: 
      - name: install
        yum: name=redis
        tags: install
      - name: copyfile
        copy: dest=/etc/redis.conf src=/root/yaml/redis.conf
        tags: copyfile
      - name: start redis
        service: name=redis state=started
        tags: start
    
    ansible-playbook -t copyfile v8.yml   #执行打上某个标签的任务
    

    模板

    #创建目录template, 并将redis.conf配置文件拷贝到此目录并改名redis.conf.j2
    mkdir templates
    mv redis.conf{,.j2}
    vim redis.conf
    bind {{ansible_default_ipv4.address}}   #根据不同的主机来定制不同的监听地址
    

    - hosts: cache
      remote_user: root
      tasks: 
      - name: install
        yum: name=redis
        tags: install
      - name: copyfile
        template: dest=/etc/redis.conf src=redis.conf.j2  #可以使用相对路径,在当前目录的templates目录里面
        tags: copyfile
      - name: start redis
        service: name=redis state=started
        tags: start
    

    循环with_item

    - hosts: db
      tasks: 
      - name: create user
        user: name={{ item }}
        with_items:
        - alex10
        - wusir10
        - taiba10
    

    循环嵌套

    - hosts: db
      tasks: 
      - name: create group
        group: name={{item}}
        with_items:
        - alex20
        - wusir20
        - taibai20
      - name: create user
        user: name={{ item.name }} group={{item.group}}
        with_items:
        - {name: alex30,group: alex20}
        - {name: wusir30,group: wusir20}
        - {name: taibai30,group: taibai20}
    

    handlers

    - hosts: cache
      remote_user: root
      tasks: 
      - name: install
        yum: name=redis
        tags: install
      - name: copyfile
        template: dest=/etc/redis.conf src=redis.conf.j2
        tags: copyfile
        notify: restart redis
      - name: start redis
        service: name=redis state=started
        tags: start
      handlers: 
      - name: restart redis
        service: name=redis, state=restarted
    

    roles

    特点

    • 目录结构清晰
    • 重复调用相同的任务

    目录结构

    首先新建roles文件, 然后再在roles文件中新建需要调用的文件的目录,将调用的文件放在目录中,使得结构更清晰

    mkdir roles
    mkdir -pv {web,db}/{tasks,vars,templates,handlers}
    vim web.yml #总执行文件, roles目录下是调用的文件
    - hosts: web
      remote_user: root
      roles: 
      - web  #直接写目录文件名
    
    web/
    - tasks
        - install.yml
            - name: install {{pkg}}
              yum: name={{pkg}}
        - copyfile.yml
              - name: copyfile
      		    template: src=nginx.conf.j2 dest=/etc/nginx/nignx.conf
                notify: restart
        - start.yml
              - name: start {{pkg}}
     		    service: name={{pkg}} state=started
        - main.yml  #导入所有要执行的文件
          	  - import_tasks: install.yml
    		  - import_tasks: copyfile.yml
              - import_tasks: start.yml
    - templates
         - nginx.conf.j2 # 由nginx的配置文件/etc/nginx/nginx.conf 拷贝而来
               worker_processes { ansible_processor_vcpus*2 }; #进程数是cpu个数的2倍
               worker_connections 65535;  #最大连接数
    - vars
        - main.yml  #定义变量
            pkg: nginx
    - files
    - handlers
        - main.yml
              - name: restart
                service: name=nginx state=restarted
    

    tasks目录里面的查找规则:

    • 先找main.yml, 通过import_tasks 导入task,
    • 如果有handlers目录,找到main.yml,通过notify去找handlers里面的里面的task
    • template模块去templates目录里面找需要复制的文件

    常见报错解决

    [WARNING]: sftp transfer mechanism failed

    ansible 执行命令时,部分主机出现[WARNING]: sftp transfer mechanism failed on [xx]. Use ANSIBLE_DEBUG=1 to see detailed information的报错

    一、修改sshd_config文件,取消注释Subsystem     sftp    /usr/lib/ssh/sftp-server
    
    Subsystem      sftp    /usr/lib/ssh/sftp-server
    
    当该行注释时,表示禁用sftp,需取消注释启用,修改配置后重启sshd服务
    
    二、当sftp已启用时,报错仍然存在,修改ansible配置文件,添加scp_if_ssh=True
    
    vi /etc/ansible/ansible.cfg
    
        [ssh_connection]
        scp_if_ssh=True
    
    重新执行ansible,报错不存在了 
    
  • 相关阅读:
    ASIHttpRequest封装
    算法6-6:哈希表应用之字典应用
    代码杂记(三)
    拥塞避免算法
    使用Unity制作的一个望远镜特效,在狙击手游戏中非经常见
    Ubuntu Linux下安装Oracle JDK
    Java输入输出流(2)
    软考之路--小桥流水人家
    [Java]LeetCode116. 填充同一层的兄弟节点 | Populating Next Right Pointers in Each Node
    [Swift]LeetCode115. 不同的子序列 | Distinct Subsequences
  • 原文地址:https://www.cnblogs.com/cjwnb/p/11986641.html
Copyright © 2011-2022 走看看