一, 安装
1,下载epel源
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
2, 安装ansible
yum install -y ansible
二, 初步认识ansible
1, ansible通过ssh来连接并控制被控节点 / salt控制节点需要安装salt-master,salt被控节点需要安装salt-minion
2, ssh的认证方式:
密码连接
密钥连接
3, ssh密钥登录
密钥需要生成密钥对(公钥和私钥)
ssh-keygen # 用来生成ssh的密钥对,一直回车
ssh-copy-id 192.168.107.131 # 复制秘钥到远程主机(ip地址为远程主机的ip)
执行完上面命令后,输入密码,然后会有提示,通过ssh+ip地址就可以登录远程主机了
4,ansible的命令格式
ansible <host-pattern> [options] -a MODULE_ARGS, --args=MODULE_ARGS #模块的参数 -C, --check # 检查 -f FORKS, --forks=FORKS #用来做高并发的 --list-hosts #列出主机列表 -m MODULE_NAME #模块名称 --syntax-check # 语法检查 -k 输入密码
5,查看ansible生成的文件
rpm -ql ansible| more /etc/ansible /etc/ansible/ansible.cfg /etc/ansible/hosts /etc/ansible/roles
6, ansible的 hosts 文件
1 # This is the default ansible 'hosts' file. 2 # 3 # It should live in /etc/ansible/hosts 4 # 5 # - Comments begin with the '#' character # 用#来表示注释 6 # - Blank lines are ignored # 空白行被忽略 7 # - Groups of hosts are delimited by [header] elements # 主机组 需要在【】下面 8 # - You can enter hostnames or ip addresses #可以写主机名或者ip地址 9 # - A hostname/ip can be a member of multiple groups # 一台主机可以在多个组里面 10 www[001:006].example.com #表示从www001到www006的机器
7,ansible为我们提供的ping
vi /etc/ansible/hosts # 将远程主机地址加到文件中
ansible 192.168.107.131 -m ping
# 这样就可以ping通了
以上的操作仅对已经做了密钥认证的主机有作用,没有密钥认证的还是ping不通,如果想要ping通的话,可以加上-k
ansible 192.168.107.131 -m ping -k #然后输入密码
但是每次都输入密码也是很麻烦啊,所以还是做上密钥认证比较好
8,有关ping的命令
系统自带的ping走的是ICMP协议
ansible 192.168.107.133 -m ping # ping一台主机 ansible all -m ping # ping所有主机 ansible 192.168.107.133,192.168.107.134 -m ping # ping其中某些主机
虽然通过这样的方式方便了不少,但是还是很麻烦啊,比如我们有100台主机,要测试其中的五十台,难道我们要用逗号写50个ip地址在这吗?
这个时候我们突然想到,配置文件中说到过分组的问题,对机器进行分组,这样不就方便多了吗
9,主机分组
vi /etc/ansible/hosts # 在文件中写入以下内容,分三个组 [web] 192.168.211.129 192.168.211.130 [db] 192.168.211.130 192.168.211.132 [cache] 192.168.211.129 192.168.211.132
ansible web -m ping #ping web组中的机器 ansible 'web:&db' -m ping # 交集 ansible 'web,db' -m ping #并集 ansible 'web:db' -m ping #并集 ansible 'web:!db' -m ping #差集
10,host-pattern的格式
- 单个的主机 直接写ip - 全部主机 all - 多个的主机 逗号分隔 - 单个组 - 多个组 - 交集 ‘web:&db’ - 并集 - web,db - ‘web:db’ - 差集 ‘web:!db’
11,ansible-doc 查看模块的帮助信息
ansible-doc -h # 查看ansible模块命令格式
ansible-doc [-l|-F|-s] [options] [-t <plugin type> ] [plugin] #命令格式 -j #以json的方式返回ansible的所有模块 -l, --list #列出所有的ansible的模块 -s #以片段式显示ansible的帮助信息
什么都不写是显示全部帮助信息
三,命令相关模块
1,command 不支持特殊字符 <> |!;$&
ansible web -a 'ls /' #查看web分组内机器的根信息 ansible web -a 'pwd' #查看当前工作目录 ansible-doc -s command #查看command的帮助信息 ansible web -a 'chdir=/tmp pwd' # 切换目录执行命令,使用场景是编译安装时使用 ansible web -a 'creates=/tmp pwd' # 用来判断/tmp目录是否存在,存在就不执行操作 ansible web -a 'creates=/data pwd' # 因为data不存在,所有才会执行pwd命令 ansible web -a 'removes=/tmp pwd' #用来判断tmp目录是否存在,存在就执行操作 ansible web -a 'removes=/data pwd' #因为data不存在,所有才不会执行
创建用户,查询用户是否创建成功
ansible web -a 'useradd liang' #创建用户 #查询用户是否创建成功: tail -1 /etc/passwd tail -1 /etc/shadow id liang echo '123' | passwd --stdin liang #设置密码
2,shell 模块
ansible web -m shell -a 'echo "123" | passwd --stdin liang' # 批量创建密码 ansible 192.168.107.131 -m shell -a 'bash a.sh' # 执行远程文件方式一 ansible 192.168.107.131 -m shell -a '/root/a.sh' #执行远程文件方式二,文件必须有执行权限 ansible 192.168.107.131 -m shell -a '/root/a.py' # 执行远端的Python脚本
3,script模块 在远程主机执行主控端的shell/python脚本
ansible web -m script -a '/root/m.sh' # 执行本地的文件,执行管控机上的文件 ansible web -m script -a 'removes=/root/m.sh /root/m.sh' # 用来判断被管控机上是不是存在文件,如果存在,存在就执行,不存在就不执行 ansible web -m script -a 'creates=/root/a.sh /root/m.sh' #用来判断被管控机上是不是存在文件,如果存在,就不执行
四,文件相关模块
1,copy
1 backup 备份,以时间戳结尾 2 dest 目的地址 3 group 文件的属组 4 mode 文件的权限 r 4 w 2 x 1 5 owner 文件的属主 6 src 源文件
ansible db -m copy -a 'src=/root/m.sh dest=/tmp/a.sh' #复制本地文件的到远程主机 ansible db -m copy -a 'src=/root/m.sh dest=/tmp/a.sh mode=755' #修改文件的权限 ansible web -m copy -a 'src=/root/m.sh dest=/tmp/a.sh mode=755 owner=alex' #修改文件的属主 ansible web -m copy -a 'src=/etc/init.d dest=/tmp/ mode=755 owner=alex' # 复制本地目录到远程主机,如果改变文件的属性,则文件夹内的文件也会被改变 ansible web -m copy -a 'src=/etc/init.d/ dest=/tmp/ mode=755 owner=alex' # 复制本地目录内的所有文件到远程主机 ansible web -m copy -a "content='大弦嘈嘈如急雨,小弦切切如私语\n' dest=/tmp/b.txt" # 直接将文本内容注入到远程主机的文件中
2,file 模块
1 path 2 src 3 link 4 hard 5 state 6 directory 7 touch 8 link 9 hard 10 absent
ansible db -m file -a 'path=/lzmly2 state=directory' #在远程机器上创建文件夹 ansible db -m file -a 'path=/root/q.txt state=touch' #用来在远程机器上创建文件 ansible db -m file -a 'path=/tmp/f src=/etc/fstab state=link' #创建软连接src是源地址,path是目标地址 ansible db -m file -a 'path=/tmp/f state=absent' #用来删除文件或者文件夹
补充:
inode # 硬盘的地址 id # 获取到的是内存的地址 ln -s a.py b.py # 创建软连接 ln a.py c.py # 创建硬链接 当 源文件变化时,软连接和硬链接文件都会跟着变化
3,fetch 模块 拉取被控节点上的文件,保留原来的目录结构,以id命名了一个文件夹
dest 目的地址 src 源地址 ansible web -m fetch -a 'src=/var/log/cron dest=/tmp' # 下载被控节点的文件,每台机器创建一个文件夹,并保留原来的目录结构
五, 软件相关模块
1, yum
rpm 和 yum的区别 :
rpm : redhat package mananger
yum : 可以解决依赖关系
yum源配置:
1 [epel] 2 name=Extra Packages for Enterprise Linux 7 - $basearch #名字 3 baseurl=http://mirrors.aliyun.com/epel/7/$basearch #rpm源的地址,可以写http,https,ftp,Samba,file: 4 failovermethod=priority 5 enabled=1 # 是否开启,1代表开启,0表示关闭 6 gpgcheck=0 #是否校验签名,1代表校验,0表示校验 7 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
yum安装包组 (存放功能相同的包) :
yum grouplist #查看包组信息 yum groupinstall #安装包组 disablerepo #禁用源 enablerepo #启用源 name #包名 state install (`present' or `installed', `latest'), or remove (`absent' or `removed')
ansible web -m yum -a 'name=wget' # 安装wget ansible web -m yum -a 'name=python2-pip' # 安装python2-pip ansible web -m yum -a 'name=wget state=absent' # 卸载软件包 ansible web -m yum -a 'name="@Development Tools"' # 安装包组(加@)
2, pip
name requirements 用来指定文件 pip install 安装包 pip freeze > a.txt 将python的环境打包到文件中 pip install -r a.txt 安装文件中的包 pip list 查看所有的以安装成功的包 ansible web -m pip -a 'name=flask' # 安装flask模块
3, service
name state started stopped restarted reloaded enabled 设置开机自启动 ps -ef|grep nginx #查看进程 ss -tnlp # 查看端口信息 systemctl start nginx # centos7 service nginx start # centos6 systemctl enabled nginx # centos7 开机自启动 chkconfig nginx on # centos6开机自启动 ansible web -m service -a 'name=nginx state=started' # 启动nginx ansible web -m service -a 'name=nginx state=stopped' # 关闭nginx
六, cron 计划任务
* * * * * job 分 时 日 月 周 任务 0 */2 * * * job 每隔两个小时 0 12,13 * * * job 12点和13点 0 12-17 * * * job 12点到17点 0 12-17/2 * * 1,3,6,0 周1,周3,周6,周7 12点到17点每隔两个小时 crontab -e # 编辑计划任务 crontab -l # 查看计划任务 crontab -r # 删除计划任务
ansible计划任务参数
day 天 disabled 禁用 hour 小时 job 任务 minute 分钟 month 月 name 任务名字 weekday 周 state disabled=yes 表现形式为# 需要注意的是不能都是*
计划任务常用操作
ansible db -m cron -a 'minute=26 job="touch /tmp/xzmly.txt" name=touchfile' # 新建一个计划任务 ansible db -m cron -a 'name=touchfile state=absent' # 删除一个计划任务 ansible db -m cron -a 'minute=26 job="touch /tmp/xzmly.txt" name=touchfile disabled=yes' # 禁用计划任务,以#表示禁用
七, 用户相关
1, user
用户: 管理员 root 0 普通用户 系统用户 不能登录 1-999 centos7 1-499 centos6 登录用户 可以登录 1000-65535 centos7 500-65535 centos6 用户组: 管理员组 root 0 系统用户组 1-999 centos7 1-499 centos6 登录用户组 1000-65535 centos7 500-65535 centos6 -d 指定用户的家目录 -g 指定用户的组 -G 执行用户的附加组 -s 指定登录后使用的shell -r 创建一个系统组 useradd -r ding 创建系统用户, 从999倒序 useradd -s /sbin/nologin liang 创建的是普通用户,从1000开始升序 useradd -d /opt/liang2 liang2 创建用户时指定用户的家目录 useradd -u 3000 liang3 # 创建用户并指定用户的uid userdel alex 删除用户 userdel -r liang2 删除用户并删除用户的家目录 groupadd yuchao 创建用户组 groupdel yuchao 删除用户组
ansible中用户组的参数
group 组 groups 附加组 home 家目录 name 用户名 password 密码 remove=yes shell 用户登录后使用的shell system 创建一个系统用户 uid 用来指定用户的id state 状态
常用操作
ansible db -m user -a 'name=liang uid=4000 home=/opt/liang groups=root shell=/sbin/nologin' #创建一个用户,并指定用户的id,用户的家目录,用户的附加组,用户的shell ansible db -m user -a 'name=liang state=absent' #删除用户但是不删除用户的家目录 ansible db -m user -a 'name=liang state=absent remove=yes' # 删除用户并删除用户的家目录
2, group 创建组
gid 组的id name 组名 system 系统组 state ansible db -m group -a 'name=wulaoshi system=yes' #创建系统组 ansible db -m group -a 'name=wulaoshi state=absent' # 删除组
小练习:
web 创建一个用户组liang ansible web -m group -a 'name=liang' 创建一个用户ding ansible web -m user -a 'name=ding' 把/etc/fstab文件复制到远程主机上/tmp/f ansible web -m copy -a 'src=/etc/fstab dest=/tmp/f' 安装nginx,并启动,设置开机自启动 ansible web -m yum -a 'name=nginx' ansible web -m service -a 'name=nginx enabled=yes' 小练习
八, ansible剧本---playbooks
yaml严格模式:
- 冒号后面必须有空格
- 等号后面不能有空格
- -后面也要有空格
- 严格对齐
--- - hosts: webservers vars: http_port: 80 max_clients: 200 remote_user: root tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=/srv/httpd.j2 dest=/etc/httpd.conf notify: - restart apache - name: ensure apache is running service: name=httpd state=started handlers: - name: restart apache service: name=httpd state=restarted 第一行中,文件开头为 ---;这是YAML将文件解释为正确的文档的要求。YAML允许多个“文档”存在于一个文件中,每个“文档”由 --- 符号分割,但Ansible只需要一个文件存在一个文档即可,因此这里需要存在于文件的开始行第一行。 YAML对空格非常敏感,并使用空格来将不同的信息分组在一起,在整个文件中应该只使用空格而不使用制表符,并且必须使用一致的间距,才能正确读取文件。相同缩进级别的项目被视为同级元素。 以 - 开头的项目被视为列表项目。作为散列或字典操作,它具有key:value格式的项。YAML文档基本上定义了一个分层的树结构,其中位于左侧是包含的元素。YAML文件扩展名通常为.yaml或者.yml。
语法校验 : ansible-playbook --syntax-check 文件名
playbook的核心元素:
Playbook本身由以下各部分组成: (1)Hosts:运行指定任务的目标主机; (2)Tasks:任务,即调用模块完成的操作; (3)Variables:变量; (4)Templates:模板; (5)Handles:处理器,当某条件满足时,触发执行的操作; (6)Roles:角色
1, 传参的方式
传参优先级 : -e > playbook vars > hosts文件
- hosts: web tasks: - name: create{{ user }} user: name={{ user}}
第一种方式:
ansible-playbook -e 'user=liang' p2.yml
第二种方式: 在主机组中添加
[db] 192.168.107.132 user=liang01 192.168.107.133 user=liang02
第三种方式 :
[db:vars] #表示组的参数 db组 vars:指定了变量 user=liang
第四种方式:
- hosts: db vars: - user: liang tasks: - name: create{{ user }} user: name={{ user}}
第五种方式 :
- hosts: db tasks: - name: sum shell: echo 7+8|bc register: user - name: createuser user: name={{user.stdout}}
2, setup
ansible_all_ipv4_addresses # ipv4的所有地址 ansible_all_ipv6_addresses # ipv6的所有地址 ansible_date_time # 获取到控制节点时间 ansible_default_ipv4 # 默认的ipv4地址 ansible_distribution # 系统 ansible_distribution_major_version # 系统的大版本 ansible_distribution_version # 系统的版本号 ansible_domain #系统所在的域 ansible_env #系统的环境变量 ansible_hostname #系统的主机名 ansible_fqdn #系统的全名 ansible_machine #系统的架构 ansible_memory_mb #系统的内存信息 ansible_os_family # 系统的家族 ansible_pkg_mgr # 系统的包管理工具 ansible_processor_cores #系统的cpu的核数(每颗) ansible_processor_count #系统cpu的颗数 ansible_processor_vcpus #系统cpu的总个数=cpu的颗数*CPU的核数 ansible_python # 系统上的python ansible cache -m setup -a 'filter=*processor*' # 用来搜索
3, 条件判断
(1),在yaml文件中写任务
(2),语法校验 ansible-playbook --syntax-check p6.yml
(3),执行 ansible-playbook -e 'a="3"' p6.yml
文件书写方式: when:
- hosts: db remote_user: root tasks: - name: createfile copy: content="大弦嘈嘈如急雨" dest=/tmp/a.txt when: a=="3" - name: cratefile copy: content="小弦切切如私语" dest=/tmp/a.txt when: a=="4"
应用场景:
不同的系统
不同的版本
不同的环境
不同的用户
4, 循环
(1),tags : 设置标签,运行指定的tasks
书写方式:
- hosts: web tasks: - name: installnginx yum: name=nginx - name: copyfile copy: src=/etc/nginx/nginx.conf dest=/etc/nginx/nginx.conf tags: copyfile - name: start service: name=nginx state=started
使用方式: -t 任务名
ansible-playbook -t copyfile p7.yml #只运行copyfile这个任务
(2), 循环
①,with_items
应用场景 : 需要一次性创建多个的时候
使用方式举例:
一次性创建三个不同的用户
- hosts: web tasks: - name: crateuser user: name={{item}} with_items: - liang01 - liang02 - liang03
一次性创建多个用户,并且创建多个组
- hosts: web tasks: - name: crateuser user: name={{item}} with_items: - liang01 - liang02 - liang03 - name: crategroup group: name={{item}} with_items: - ding01 - ding02 - ding03
②, 循环嵌套
使用举例 :
一次性创建多个组,并将每个组添加一个用户
- hosts: web tasks: - name: crategroup group: name={{item}} with_items: - wulaoshi30 - wulaoshi31 - wulaoshi32 - name: createuser user: name={{item.name}} group={{item.group}} #用点的方式获取字典中的值 with_items: #用字典的方式写 - {'name':alex40,'group':wulaoshi30} - {'name':alex41,'group':wulaoshi31} - {'name':alex42,'group':wulaoshi32}
5, template : 模板文件,以.j2后缀,
从被管控机的setup模块获取值
template类是jinja的另一个重要组件,可以看做是一个编译过的模板文件,用来产生目标文本,传递Python的变量给模板去替换模板中的标记
使用方法示例:
- hosts: web tasks: - name: installredis yum: name=redis - name: copyfile template: src=/etc/redis.conf dest=/etc/redis.conf #写的是绝对路径(如果
要写相对路径的话,要在目录下新建一个template的目录,然后把文件放进去) - name: start service: name=redis state=started 配置文件: bind {{ ansible_default_ipv4.address }}
-
copy模块不替代参数
-
template模块替代参数
6, Handlers
handlers用于当关注的资源发生变化时所采取的操作,当发生改变时,通过notify出发handlers的操作
- hosts: web tasks: - name: installredis yum: name=redis - name: copyfile template: src=redis.conf dest=/etc/redis.conf tags: copyfile notify: restart #写的是handlers里面任务的名字 - name: start service: name=redis state=started handlers: - name: restart service: name=redis state=restarted
九, roles
-
-
可以互相调用
roles内各目录含义解释:
1 files:用来存放由copy模块或script模块调用的文件。 2 templates:用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。 3 tasks:此目录应当包含一个main.yml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件。 4 handlers:此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。 5 vars:此目录应当包含一个main.yml文件,用于定义此角色用到的变量。 6 defaults:此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。 7 meta:此目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系。
创建roles步骤:
- 创建已roles命名的目录
- 在roles目录中分别创建已各角色名称命名的目录,如dbservers,webservers等。
- 在每个角色命名的目录中分别创建files、hadlers、meta、tasks、templates以及vars目录;用不到的目录可以创建为空目录,也可以不创建;
- 在playbook文件中,调用各角色;
[root@localhost ~]# mkdir -p ansible_playbooks/roles/{dbservers,webservers}/{tasks,files,templates,meta,handlers,vars} [root@localhost ~]# tree ansible_playbooks/ ansible_playbooks/ └── roles ├── dbservers │ ├── files │ ├── handlers │ ├── meta │ ├── tasks │ ├── templates │ └── vars └── webservers ├── files ├── handlers ├── meta ├── tasks ├── templates └── vars
浙公网安备 33010602011771号