ansible

Posted cjwnb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,报错不存在了 















































以上是关于ansible的主要内容,如果未能解决你的问题,请参考以下文章

从jenkinsfile启动包含vault文件引用的Ansible playbook

ansible代码分析第一篇--主文件—ansible分析

python代码调用ansible

Ansible

基于ansible的zabbix源代码安装

需要代码来使用 Ansible 检查服务器连接