ansible:———-2012年创建,最近被红帽1.5亿收购(兼有一些pupuet、fabric、agentless功能)
用于yum install ansible (前提yum源仓库为epel源)
1、特性:
模块化:调用特定的模块(插件)来完成特定任务核心组件所以小;
基于Python语言实现:由Paramiko, PyYAML和Jinja2三个关键模块实现;
部署简单:agentless
主从模式:
支持自定义模块:
支持playbook(剧本):
支持幂等性:运行一次或N次结果一样,如果有些不幂等性,要人工使其幂等
2、组成部分:
ansible core:主体核心(默认每次批量5个,可根据需要改变其值)
host inventory:管理范围的文件 (没在管理范围内的不管理)
connection plugins:连接插件(一般基于ssh来连接的)—用于与每一个被管理主机建立会话并发送管理指令
modules:要做的每一个操作都要靠模块来定义(连接插件等操作不能靠每次输入)
core modules 核心模块(自带)
custom modules 用户自定义模块
Plugins 扩展插件(如email、logging、other或者自己开发的插件)
Playbooks: 批量命令文件(事先编写好,让ansible完成的操作,ansible复用就靠它了)
3、配置文件:
主配置文件:/etc/ansible/ansible.cfg —————ansible core file
管理范围文件 :/etc/ansible/hosts —————Host Inventory file
4、ansible命令:
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
<host-pattern>: 要管理主机的匹配模式
-f forks:表示一次管理几个主机(默认一批是5个主机)
-m module_name:要使用的模块名字(默认模块command)
-a args:模块专用参数(key value ———-kv键值)
管理范围文件:/etc/ansible/hosts(文件名路径可以指定 -i PATH, –inventory=PATH:指明使用的host inventory文件路径;)
定义(INI风格):
中括号中的字符是组名 如:[webservers];
组号要放入[]号: 如:[webservers]
多主机名: 如:www[001:006].example.com———–表示从001到006主机
一个组也可以包括其他组:
同一个主机出现在多个组:
自定义:
[webserver]
172.16.38.3:2222 #这里加2222是因为此主机不是通过22号端口远程连接,而是2222。因为ansible是通过ssh连接管理的
172.16.38.4
[dbserver]
172.16.38.5
配置基于密钥认证:在控制端
1、生成密钥对:ssh-keygen -t rsa
.ssh目录下生成两个文件 ,我们要用的是id-rsa.pub
2、复制公钥给被控端:ssh-copy-id -i .ssh/id-rsa.pub root@host
[root@nfs .ssh]# ssh-copy-id -p 2222 -i id_rsa.pub root@172.16.38.3
[root@nfs .ssh]# ssh-copy-id -i id_rsa.pub root@172.16.38.4
5、ansible-doc命令:获取模块列表,及模块使用格式;
ansible-doc -l # 获取列表
ansible-doc -s module_name # 获取某个模块的具体使用参数
常用模块:
[-a args]:
args: key=value
注意:command模块的参数非为kv格式,而是直接给出要执行的命令即可;
command:默认模块
-a ‘COMMAND’
[root@nfs ~]# ansible all -a ifconfig
[root@nfs ~]# ansible all -a ‘crontab -l’ # 命令带选项时,要把整个命令段用单引号引起来
user:创建删除用户
-a ‘name= state={present|absent} force= system= uid= shell= home=’
[root@nfs ~]# ansible webserver -m user -a “name=test state=present” # 在webserver上面创建test用户
[root@nfs ~]# ansible webserver -m user -a “name=test state=absent remove=yes” # 删除test用户及其家目录
group:创建工作组
-a ‘name= state={present|absent} gid= system=’
[root@nfs ~]# ansible webserver -m group -a “name=mygrp state=present gid=300 system=true” #添加系统组mygrp,GID为300,system=true(是系统组)
[root@abc ~]# cat /etc/group
mygrp:x:300:
[root@nfs ~]# ansible webserver -m group -a “name=mygrp state=absent” # 删除mygrp组
cron:计划任务
-a ‘name= state= minute= hour= day= month= weekday= job=’
[root@nfs ~]# ansible all -m cron -a “minute=’*/1′ job=’cat /etc/passwd &>test.txt’ name=’showpasswd'” # 创建计划并输出到test.txt文件中,计划名为showpasswd
[root@nfs ~]# ansible all -m cron -a “name=’showpasswd’ state=absent” #删除计划
ping:查看主机状态—没有参数(下面是测试结果,主机都活着)
[root@nfs ~]# ansible webserver -m ping
172.16.38.3 | success >> {
“changed”: false,
“ping”: “pong”
}
172.16.38.4 | success >> {
“changed”: false,
“ping”: “pong”
}
[root@nfs .ssh]# ansible all -m ping # 不仅是webserver列表的,而是所有的
file:文件创建删除等管理
-a ‘path= mode= owner= group= state={file|directory|link|hard|touch|absent} src=’
[root@nfs ~]# ansible webserver -m file -a “path=/tmp/abc.txt owner=ftp mode=600 state=touch” # 创建文件abc.txt 所有者ftp,权限600
[root@abc tmp]# ll
-rw——- 1 ftp root 0 Jan 31 21:38 abc.txt
[root@nfs ~]# ansible webserver -m file -a “path=/tmp/abc.txt state=absent”
copy:文件复制
-a ‘dest= src= content= owner= group= mode=’
[root@nfs ~]# ansible webserver -m copy -a ‘src=/etc/fstab dest=/tmp/fstab.xyz mode=600 ‘ # 复制本机的fstab 文件到webserver组的tmp目录下
[root@nfs ~]# ansible webserver -a ‘rm /tmp/fstab.xyz’ # 删除文件
template
-a ‘dest= src= content= owner= group= mode=’
yum:yum安装
-a ‘name= conf_file= state={present|latest|absent} enablerepo= disablerepo=’
[root@nfs ~]# ansible webserver -m yum -a “name=zsh state=present” # 安装zsh在webserver上
[root@nfs ~]# ansible webserver -m yum -a “name=zsh state=absent”
service:管理服务的
-a ‘name= state={started|stopped|restarted} enabled= runlevel=’
[root@nfs ~]# ansible webserver -m service -a ‘name=httpd state=started’ # 开启webserver组的httpd服务
[root@nfs ~]# ansible webserver -m service -a ‘name=httpd state=stopped’ # 停止webserver组的httpd服务
shell:用shell程序打开
-a ‘COMMAND’
[root@nfs ~]# ansible webserver -a ‘echo “gayj.cn” | passwd –stdin root’ # 用shell改变root密码
172.16.38.3 | success | rc=0 >>
gayj.cn | passwd –stdin root
172.16.38.4 | success | rc=0 >>
gayj.cn | passwd –stdin root
script:指定本地主机上的脚本文件,在远程主机上运行一次
-a ‘/PATH/TO/SCRIPT’
[root@nfs ~]# ansible webserver -m script -a ‘test.sh’ # 让本地主机的test.sh在webserver主机上运行一次
setup:收集主机的变量状态
[root@nfs ~]# ansible 172.16.38.3 -m setup
获取指定主机的facts;
十、playbooks:
1、核心元素:
Tasks 任务
Variables 变量
Templates 模板
Handlers 处理器
Roles 角色
2、组织格式:YAML ——–可读性较高的,可以用来表达资料序列的格式
YAML Ain’t Markup Language; Yet Another Markup Language;
语法:(键值段用冒号间隔,列表用-隔开)
name: Jerry
age: 21
gender: Male
spouse: (嵌套)
name: Lily
age: 19
gender: Female
children:(嵌套)
– name: tom
age: 2
gender: male
– name: obama
age: 5
gender: male
列表:-
字典: k:v(键值)———–上面三种颜色区域即表示三个字典
{name: jerry, age: 21, genden: male}—–字典可以写在{}中
3、playbook:
– host: 172.16.100.68
vars:
var1: value
var2: value
tasks:(任务)
– name:
– name:
– name:
handlers:(处理器)
– name:
remote_user: (以什么用户身份)
– host: 172.16.100.69
vars:
tasks:
handlers:
remote_user:
– host: 172.16.100.6
vars:
tasks:
handlers:
remote_user:
如何定义任务:
– name: task description
module_name: module_args
4、ansible-playbook命令:
ansible-playbook <filename.yml> … [options]
5、playbook的元素:
变量:
变量命名:字母、数字和下划线组成,仅能以字母开头;
变量种类:
facts:由远程主机发回的主机属性信息,这些信息被保存在ansible变量中;无须定义,可直接调用;
自定义变量:
通过命令行传递: ansible-playbook test.yml –extra-vars “host=www user=mageedu”
通过roles传递
主机变量:定义在inventory中的主机之后的变量;
组变量:定义在inventory中的组上的变量
[group_name:vars]
var1=value
var2=value
[websrvs]
[websrvs:vars]
变量使用示例:
– hosts: websrvs
remote_user: root
vars:
username: student
password: mageedu
tasks:
– name: add user
user: name={{ username }} state=present
– name: set password
shell: /bin/echo {{ password }} | /usr/bin/passwd –stdin {{ username }}
# ansible-playbook /PATH/TO/SOME_YAML_FILE { -e VARS|–extra-vars=VARS} 前面{}中方式二选一, 从新定义vars值,命令行传送的优先于hosts中的vars值
– hosts: webserver
remote_user: root
vars:
username: student
password: 123456
tasks:
– name: add user
user: name={{ username }} state=present
– name: set password
shell: /bin/echo {{ password }} | /usr/bin/passwd –stdin {{ username }}
[root@nfs ~]# ansible-playbook test.yml
PLAY [webserver] **************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.4]
ok: [192.168.1.3]
TASK: [add user] **************************************************************
changed: [192.168.1.3]
changed: [192.168.1.4]
TASK: [set password] **********************************************************
changed: [192.168.1.4]
changed: [192.168.1.3]
PLAY RECAP ********************************************************************
192.168.1.3 : ok=3 changed=2 unreachable=0 failed=0
192.168.1.4 : ok=3 changed=2 unreachable=0 failed=0
删除刚才创建的用户:
– hosts: webserver
remote_user: root
vars:
username: student
tasks:
– name: del user
user: name={{ username }} state=absent remove=true
[root@nfs ~]# ansible-playbook test.yml
PLAY [webserver] **************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.4]
ok: [192.168.1.3]
TASK: [del user] **************************************************************
changed: [192.168.1.4]
changed: [192.168.1.3]
PLAY RECAP ********************************************************************
192.168.1.3 : ok=2 changed=1 unreachable=0 failed=0
192.168.1.4 : ok=2 changed=1 unreachable=0 failed=0
inventory参数:(在hosts文件对应的Ip主机后定义)
ansible基于ssh连接inventory中指定的远程主机时,将以此处的参数指定的属性进行;
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
如下:
[webserver]
172.16.38.3 ansible_ssh_user=root ansible_ssh_pass=12345 ansible_ssh_port=2222
条件测试:
在某task后面添加when子句即可实现条件测试功能;when语句支持Jinja2语法;
tasks:
– name: install web server package
yum: name=httpd state=present
when: ansible_os_family == “RedHat”
– hosts: webserver
remote_user: root
tasks:
– name: install web server package
yum: name=zsh state=present
when: ansible_os_family == “Debian” # 当为Debint系统时执行安装
– name: say hello
command: /bin/echo “hello” # 向所以webserver组的主机说hello
[root@nfs ~]#
[root@nfs ~]# ansible-playbook test.yml
PLAY [webserver] **************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.1.4]
ok: [192.168.1.3]
TASK: [install web server package] ********************************************
skipping: [192.168.1.3]
skipping: [192.168.1.4]
TASK: [say hello] *************************************************************
changed: [192.168.1.3]
changed: [192.168.1.4]
PLAY RECAP ********************************************************************
192.168.1.3 : ok=2 changed=1 unreachable=0 failed=0
192.168.1.4 : ok=2 changed=1 unreachable=0 failed=0
迭代:
在task中调用内置的item(元素)变量;在某task后面使用with_items语句来定义元素列表;
– name: add four users
user: name={{ item }} state=present
with_items:
– testuser1
– testuser2
– testuser3
– testuser4
注意:迭代中,列表中的每个元素可以为字典格式;
– name: add two users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
– { name: ‘testuser5’, groups: ‘wheel’ }
– { name: ‘testuser6’, groups: ‘root’ }
handlers:——–处理(触发)
也是task,但只有其关注的条件满足时,才会被触发执行;—-当复制一个命令到远程主机,主机不知道是否重载命令,这就要靠handlers
– hosts: websrvs
remote_user: root
tasks:
– name: install httpd
yum: name=httpd state=present
– name: install config file
copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd #notify是当然条件满足时,触发handlers。让服务重新启动
– name: start httpd service
service: name=httpd state=started
handlers:
– name: restart httpd
service: name=httpd state=restarted
templates:——模板
用于生成文本文件(配置文件);模板文件中可使用jinja2表达式,表达式要定义在{{ }},也可以简单地仅执行变量替换;
roles:——-角色
roles用于实现“代码复用”;
roles以特定的层次型格式组织起来的playbook元素(variables, tasks, templates, handlers);可被playbook以role的名字直接进行调用;
roles/
webserver/
files/:此角色中用到的所有文件均放置于此目录中;
templates/:Jinja2模板文件存放位置;
tasks/:任务列表文件;可以有多个,但至少有一个叫做main.yml的文件;
handlers/:处理器列表文件;可以有多个,但至少有一个叫做main.yml的文件;
vars/:变量字典文件;可以有多个,但至少有一个叫做main.yml的文件;
meta/:此角色的特殊设定及依赖关系;
6、tags:——标签
– name: install config file
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
tags: conf
-t, TAGS, –tags=TAGS
+++++++++++++++++++++++++++++++++++++++++++++++++++++故障状态:++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
进行了密钥认证后,还是不能使用基于密钥认证的ansible登陆
[root@lvs ~]# ansible all -m ping
172.16.38.3 | FAILED => SSH Error: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
while connecting to 172.16.38.3:2222
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.
172.16.38.4 | FAILED => SSH Error: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
while connecting to 172.16.38.4:22
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.
172.16.38.5 | FAILED => SSH Error: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
while connecting to 172.16.38.5:22
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.
导致原因:
ask-pass 原来是被注释的
[defaults]
# some basic default values…
inventory = /etc/ansible/hosts
#library = /usr/share/my_modules/
remote_tmp = $HOME/.ansible/tmp
pattern = *
forks = 5
poll_interval = 15
sudo_user = root
#ask_sudo_pass = True
ask_pass = True
解决方法:
将ask_pass 取消注释,在测试命令,差什么程序包按提示安装提示包就行了(注意:yum install sshpass –nogpgcheck,后面是取消gpgcheck检查)
这样有个问题,每次登陆要输入密码:
最终于原因 :————-目录权限给太大了,系统为了安全考虑反而没权限了
drwxrwxrwx. 6 root root 4096 Feb 17 20:20 root
[root@lvs ~]# ssh 172.16.38.4
root@172.16.38.4’s password: # 这样认证就不起作用
[root@lgq ~]# tail /var/log/secure # 被控端,显示错误 bad ownership or modes for directory /root 错误的属主权限
Feb 17 20:31:51 lgq sshd[4721]: Authentication refused: bad ownership or modes for directory /root
Feb 17 20:32:36 lgq sshd[4721]: Accepted password for root from 172.16.38.17 port 41620 ssh2
在于被控端登陆用户的家目录不能为777,只能为700
改掉被控端权限,不用开启ask_pass选项
[root@lgq ~]# chmod 700 /root/
drwx——. 6 root root 4096 Feb 17 20:20 root
+++++++++++++++++++++++++++++++目录权限给太大了,系统为了安全考虑反而没权限了+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 本文固定链接: https://www.gayj.cn/?p=494
- 转载请注明: https://www.gayj.cn/