ansible批量管理

 


ansible批量管理

  • 使用ansible之前必须配置好密钥认证或者在hosts文件中指定目标主机的用户名和密码

  • 一键分发密钥脚本

#!/bin/bash
#author:supershy
#desc:
#	1.创建密钥对(判断是否存在密钥)
#	2.分发公钥(指定存放ip的文件)
#	3.检查

#1.vars
key=/root/.ssh/id_rsa
passwd=666666
ips=`cat /server/ips.txt`

#2.一键创建密钥对
if [ ! -f $key ];then
	ssh-keygen -f $key -P '' &>/dev/null
	if [ $? -eq 0 ];then
		echo "密钥对创建成功"
	else
		echo "密钥对创建失败"
		exit
	fi
fi


#3.一键分发公钥
for ip in $ips
do
	sshpass -p$passwd ssh-copy-id -o StrictHostKeyChecking=no $ip &>/dev/null
	if [ $? -ne 0 ];then
		echo "$ip公钥分发失败"
	fi
done



#4.一键检查
for ip in $ips
do
	ssh -p22 root@$ip hostname -I
done
  • hosts文件指定用户名密码
[web]
192.168.1.10 ansible_user=myuser ansible_password=mypassword
192.168.1.11 ansible_user=myuser ansible_password=mypassword

[db]
192.168.1.20 ansible_user=myuser ansible_password=mypassword

expect免密登录脚本

  • shell脚本 expect的常见用法
命 令 说 明
spawn 启动新的交互进程, 后面跟命令或者指定程序
expect 从进程中接收信息, 如果匹配成功, 就执行expect后的动作
send 向进程发送字符串
send exp_send 用于发送指定的字符串信息
exp_continue 在expect中多次匹配就需要用到
send_user 用来打印输出 相当于shell中的echo
interact 允许用户交互
exit 退出expect脚本
eof expect执行结束, 退出
set 定义变量
puts 输出变量
set timeout 设置超时时间
		# 配置批量免密钥登录脚本
cat > password_free_login.sh <<'EOF'
#!/bin/bash

# 创建密钥对
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa -q

# 声明你服务器密码,建议所有节点的密码均一致,否则该脚本需要再次进行优化
export mypasswd=666666

# 定义主机列表
k8s_host_list=(k8s-master01 k8s-master02 k8s-master03)

# 配置免密登录,利用expect工具免交互输入
for i in ${k8s_host_list[@]};do
expect -c "
spawn ssh-copy-id -i /root/.ssh/id_rsa.pub root@$i
  expect {
    \"*yes/no*\" {send \"yes\r\"; exp_continue}
    \"*password*\" {send \"$mypasswd\r\"; exp_continue}
  }"
done
EOF
sh password_free_login.sh

ansible配置文件

egrep -v '^$|#' /etc/ansible/ansible.cfg

[defaults]
host_key_checking = False	#类似于 ssh -o StrictHostKeyChecking=no
log_path = /var/log/ansible.log	#ansible的日志文件
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]

hosts被管理主机清单文件

/etc/ansible/hosts

#格式1
[web]
172.16.1.7
172.16.1.8
[backup]
172.16.1.41
[nfs]
172.16.1.31

#格式2,执行相同的操作时可以用这种方式,直接调用data等同于调用data的所有孩子
[data:children]
web
backup
nfs

#格式2的用法
ansible data -m commant -a 'hostname'

#格式3
[web]
192.168.1.10 ansible_user=myuser ansible_password=mypassword
192.168.1.11 ansible_user=myuser ansible_password=mypassword

[db]
192.168.1.20 ansible_user=myuser ansible_password=mypassword

ansible必会模块

  • 查看模块用法:ansible-doc -s copy
模块分类 模块
命令和脚本模块 command
shell shell和command区别:shell支持正则,通配符匹配
script
文件 file 创建文件,目录,软链接
copy 远程分发文件,修改权限,所有者,备份
fetch 全程拉取文件
template 和copy模块用法一样,区别:copy模块不会检测到传送文件中的变量,template会把文件中的变量解析出来
lineinfile 修改文件
replace 使用正则找到文件内容并替换
服务 systemd 服务管理
软件包 yum/apt
get_url 下载浏览器软件相当于wget
用户管理 user 管理用户
ground 管理用户组
其他系统管理 mount 挂载
cron 编写定时任务
用于调试的模块 ping 检查ansible与其他节点的连通性
debug 用户检查/显示 变量 msg:
其他 管理docker,k8s,zabbix,grafana……
rsync(synchronize),mysql(mysql_db,mysql_user)……
打包压缩 archive 打包压缩
unarchive 解压缩

命令和脚本模块选项参数

ansible 说明
-i 指定主机清单文件 默认主机清单文件/etc/ansible/hosts,修改了位置需要-i指定位置
-m 指定模块
-a 指定模块中的选项

file文件文件模块

file模块参数 说明 用法
path 路径(目录,文件),必须要写
src 指定源文件,一般用于创建软链接
state 状态,指定要做什么(创建,删除,操作文件/操作目录)
state=directory 创建目录
state=file(默认) 更新文件,如果文件不存在也不创建
state=link 创建软链接
state=touch 创建文件
ansible all -m file -a ‘path=/tmp/oldboy.txt state=touch’
ansible all -m file -a 'src=/tmp/oldboy.txt path=/tmp/oldboy.txt.link state=link'
state state=absent 删除(!!!如果是目录,递归删除目录,包括根!!!)
mode mode=755 修改权限
owner owner=root 修改所属者
group group=root 修改所属组

copy批量分发模块

copy模块参数 说明 用法
src 源文件,管理端某个文件
dest 目标,被管理端某个目录/文件
backup backup=yes 文件内容有变化,则会在覆盖前进行备份 ansible all -m copy -a ‘src=/etc/hosts dest=/tmp/hosts.txt backup=yes’
mode 修改权限
owner 修改所有者
group 修改所属组
  • 扩展:copy是推送,批量推送,fetch是拉取,批量拉取

template模块

  • #用法和copy模块一样,template会把文件中的变量解析出来,固定在templates目录下以.j2结尾的文件./templates/motd.j2
    cat templates/motd.j2
    "主机名:{{ansible_hostname}}"
    "内存大小(总计) 单位mb:{{ansible_memtotal_mb}}"
    "cpu数量:{{ansible_processor_vcpus}}"
    "默认的网卡ip eth0:{{ansible_default_ipv4.address}}"
    "系统发行版本名字:{{ansible_distribution}}"
    "系统的版本:{{ansible_distribution_version}}"
    "系统时间:{{ansible_date_time.date}}"
    
    #template模块剧本
    - hosts: all
      tasks:
        - name: 01 分发文件
          template:
            src: templates/motd.j2
            dest: /etc/motd
            backup: yes
    

lineinfile修改文件的多种策略:

  • sed修改替换功能
  • cat批量写入功能
  • echo写入功能
  • 管理机准备号配置文件copy分发
  • lineinfile模块
lineinfile模块参数 说明 用法
path 指定文件
regexp 指定正则,通过正则过滤出你要修改的行
line 这一行修改后的内容,向文件里写内容,如果添加的内容在文件中存在则不会添加 ansible all -m lineinfile -a ‘ path=/etc/ssh/sshd_config regexp=“^#Port” line=“Port 22” ’

replace替换模块

    - name: 03.修改ssh配置文件禁止root远程连接
      replace:
        path: "{{sshd_cfg}}"
        regexp: "^(#PermitRootLogin yes)|(PermitRootLogin yes)"
        replace: "PermitRootLogin no"

systemd服务管理

systemd模块参数 说明 用法
name 指定服务名字
enabled enabled=yes开机自启(yes/no)
state 指定服务开,关,重启…
state=started 开启
state=stopped 关
state=restarted 重启
state=reloaded 重读配置文件(个别服务支持)
ansible all -m systemd -a ‘name=crond enabled=yes state=started’
daemon-reload daemon-reload=yes 是否重新加载对应的服务管理配置文件

yum/get_url软件管理

yum/apt模块参数 说明 用法
name 指定软件包名字
state present 安装(也可以写为 installed)
absent 删除(也可以写为:removed)
lastest 安装或更新
update_cache 可以设置为update_cache=no加速,表示不更新本地缓存,实际应用中建议开启
get_url模块参数 说明 用法
url 指定下载地址
dest 下载到哪个目录 ansible all -m get_url -a ‘url=“https://mirrors.aliyun.com/zabbix/zabbix/6.0/rhel/7/x86_64/zabbix-agent-6.0.13-release1.el7.x86_64.rpm” desc=/tmp/’ #下载rpm包到本地,后续通过yum安装
ansible all -m yum -a ‘name=/tmp/zabbix* state=present’

user用户管理

user模块参数 说明 用法
name 指定用户名
uid 指定uid号
group 指定用户组
shell 指定命令解释器
create_home 是否创建家目录(yes/no)
state present 添加
absent 删除
password 加密的密码 #方法1,可以更新密码,密码为666666,密码经过管道传递给password_hash()插件,sha512加密算法,abcdefg是随机字符用于生成随机加密后的密码
ansible all -m user -a ‘ name=oldboy password={{“666666” |password_hash(“sha512”,”abcdefg”)}} state=present ’
#方法2
ansible all -m shell -a ‘ echo “1” |passwd - -stdin oldboy ’
group组模块 说明 用法
name 指定用户组名
gid 指定组gid号
state present 增加
absent 删除

cron定时任务管理

  • 用ansible定时任务cron模块写的定时任务只能通过ansible修改
cron模块参数 说明 用法
name 定时任务里的注释(一定要加上),对应下面注释内容
minute minute=“*/3”,minute=“00”
hour hour=“00”
day
month
week
job 指定命令或脚本(定向到空) ansible all -m cron -a ‘ name=“同步时间” minute=“”*/3” job=/sbin/ntpdate ntp1.aliyun.com &>/dev/null ’
state present 添加定时任务
absent 删除

mount挂载服务管理

mount模块参数 说明 用法
fstype 指定文件系统nfs,xfs,ext4,相当于mount -t
src 源地址(nfs服务端共享地址,src=172.16.1.31:/data)
path 挂载点,这里不是dest(哪个目录挂载到源地址目录)
state absent 卸载并修改fstab
unmounted 卸载但不修改fstab
present 仅修改fstab,但不挂载
mounted 挂载并修改fstab
remounted 重新挂载

debug调试模块

#剧本里应用,msg里写什么就输出什么也可以在里面调用变量
debug:
  msg: "gaojiaxing"

archive打包压缩模块

archive参数 说明
path 要打包压缩的目录名称
dest 生成压缩包的名字
format 指定打包格式

unarchive解压缩模块

unarchive参数 说明
src 要解压的文件名
dest 解压到哪个目录

mysql模块

  • ansible在调用mysql模块时需要插件:MySQL-python

剧本与变量

剧本调试

调试方法 说明 用法
-C - -check模拟运行,不做出改变,一些变量可能会报错,因为剧本没有真正运行 命令行中使用
- -syntax-check 只做语法检查,不运行 命令行中使用
- -start-at-task 从指定任务开始执行 ansible-playbook -i hosts - -start-at-task test.yml
高级:- -step 单步运行,y执行这个task,n忽略这个task,c自动全部运行 命令行中使用
tags: -t 指定运行标签,多个标签用‘ ,’分割 - -skip-tags 排除指定标签,多个标签用‘,’分割 ansible-playbook -i hosts test.yml -t 01_nfs_server_yum,03_nfs_server_conf 在剧本中添加标签,在命令行中指定标签
ignore_errors: ignore_errors: yes/no 忽略错误 在剧本中添加
- -list-tags 查看剧本中所有标签

剧本中符号说明

  • 特殊符号 说明
    | 在剧本表示下面内容是多行
    {{ }} 调用变量方式
    在剧本循环中使用,用来写变量

ansible定义变量方式

  • 常见变量和定义方式 应用场景
    在剧本中定义vars: 仅在一个play中使用
    变量文件存放group_vars/目录下l 自动读取 group_vars/all/vars.yml文件,适用于大多数场景,也可以根据主机清单不同服务设置变量 group_vars/web/vars.yml group_vars/nfs/vars.yml
    facts(ansible运行收集信息变量)
    register注册变量

ansible内置facts变量

  • ansible内置变量,在运行剧本时会有一个默认的task(Gathering Facts),这个在背后收集每个主机信息(eg:ip信息,主机名,磁盘,各种主机的信息)这些基本信息称为facts变量

  • facts默认执行剧本时自动执行,如果不使用facts可以在剧本中关闭 gather_facts: no

  • - hosts: all
      gather_facts: no
      tasks:
        -name: 
    
  • #获取方式facts变量所有内容
    ansible backup -i hosts -m setup
    
    #facts常用的变量
    
    "主机名:{{ansible_hostname}}"
    "内存大小(总计) 单位mb:{{ansible_memtotal_mb}}"
    "cpu数量:{{ansible_processor_vcpus}}"
    "默认的网卡ip eth0:{{ansible_default_ipv4.address}}"
    "系统发行版本名字:{{ansible_distribution}}"
    "系统的版本:{{ansible_distribution_version}}"
    "系统时间:{{ansible_date_time.date}}"
    
  • #剧本中使用facts变量
    - hosts: backup
      tasks:
        - name: 01 调试
          debug:
            msg: |
              "主机名:{{ ansible_hostname }}"
              "系统发行版本名:{{ ansible_distribution }}"
        - name: 02 保存到文件
          lineinfile:
            path: /tmp/info.txt
            create: yes
            line: |
              "主机名:{{ ansible_hostname }}"
              "系统发行版本名:{{ ansible_distribution }}"
    

register变量输出剧本中模块信息(用于输出脚本执行时输出的值的模块)

  • 结合debug调试,输出模块执行的结果
#register获取到的变量结果会输出很多内容,结果是以字典形式输出,可以用调用字典key的方式只显示出来命令的结果,reg.stdout
- hosts: all
  gather_facts: no
  tasks:
    - name: test register
      shell: date +%F
      register: reg
    - name: result
      debug:
        msg: |
          "{{ reg }}"  #输出很多内容
          "{{ reg.stdout }}"  #只调用出来命令的结果
  • shell + register
- name: Execute a shell script and capture the output
  ansible.builtin.shell: /path/to/script.sh
  register: script_output

- name: Display the script output
  ansible.builtin.debug:
    var: script_output.stdout
  • command + register
- name: Execute a command and capture the output
  ansible.builtin.command: ls -l /var/log
  register: log_files

- name: Display the command output
  ansible.builtin.debug:
    var: log_files.stdout_lines
  • script + register
- name: Execute a local script and capture the output
  ansible.builtin.script: /path/to/local_script.sh
  register: script_output

- name: Display the script output
  ansible.builtin.debug:
    var: script_output.stdout

with_items / loop循环

- hosts: all
  gather_facts: no
  tasks: 
    - name: 01 批量创建用户
      user: 
        name: "{{ item.name }}"
        uid: "{{ item.uid }}"
        state: present
      with_items:
        - {name: oldboy,uid: 2020}
        - {name: jiaxing,uid: 2021}

handlers触发器+notify

  • 需求:配置nfs服务,修改好配置文件后分发给nfs服务端机器,然后重启服务,如果nfs配置文件没有被修改则不需要重启服务
  • 实现方案:handlers+notify
#服务端配置
- hosts: nfs
  gather_facts: no
  tasks: 
    - name: 01 安装nfs服务
      yum:
        name: nfs-utils
        state: installed
    - name: 02 启动nfs服务
      systemd:
        name: "{{ item }}"
        enabled: yes
        state: started
      with_items:
        - rpcbind
        - nfs
    - name: 03 创建data共享目录
      file:
        path: "{{nfs_ser_dir}}"
        owner: nfsnobody
        group: nfsnobody
        state: directory
    - name: 04 分发exports
      template: 
        src: templates/exports.j2
        dest: /etc/exports
        backup: yes
      notify: 05 更改配置时重启nfs
  handlers:
    - name: 05 更改配置时重启nfs
      systemd:
        name: nfs
        state: reloaded

when判断

when中的符号 说明
is match(“正则”) match表示以什么开头,可以使用正则
is not match(“ ”) 取反
is regex(“ ”) 表示包括什么字符
== , != , > , >= , < , <=
- hosts: all
  tasks:
    - name: CentOS安装sl,cowsay
      yum:
        name: sl,cowsay
        state: present
      when: ansible_distribution == "CentOS"
    - name: Ubuntu安装cmatrix
      yum:
        name: cmatrix
        state: present
      when: ansible_distribution is match("Ubuntu")

jinja2文件中的判断

  • 使用template模块分发带有变量的.j2文件
cat templates/keepalived.conf.j2

{% if ansible_hostname == "web01" %}
	state 主节点
{% elif ansible_hostname == "backup" %}
	state 备节点
{% endif %}

jinja2文件中的循环

####jinja2循环参数调用变量时不需要加{{ }}
cat templates/keepalived.conf.j2

{% for ip in range(3,10) %}
	10.0.0.{{ip}}
{% endfor %}

{% for ip in [3,4,5,6] %}   
	10.0.0.{{ip}}
{% endfor %}

剧本进阶roles

roles基本格式(运行指定top.yml文件)

image-20240127190824878

include_tasks文件包含

  • 和python中模块调用方式一样,可以把一个服务中的每个功能单独写到一个文件中,然后在tasks/main.yml中调用这个模块就行

  • 调用方法(模块必须和main.yml在同一层目录下tasks/ )

    • include_tasks: install.yml
      include_tasks: config.yml
      

vault文件加密

#加密指定文件,ansible-vault
#加密hosts
ansible-vault encrypt hosts

#使用加密后的hosts
ansible或ansible-playbook --ask-vault-pass -i hosts test.yml
--ask-vault-pass 交互模式手动输入密码
--vault-password-file 指定密码文件

#解密文件
ansible-vault decrypt hosts

ansible优化

1)ansible安全优化—sudo

  • a)整体流程

    • 被管理端禁用root远程登录
    ######ansible安全优化--sudo######
    #被管理端
    #1.添加普通用户ans设置密码
    #2.配置sudo权限
    #3.修改ssh配置文件禁止root远程连接
    #4.重载sshd
    
    - hosts: all
      vars:
        username: "ans"
        passwd: "666666"
        sudo_cfg: /etc/sudoers
        sshd_cfg: /etc/ssh/sshd_config
      tasks:
        - name: 01.添加普通用户ans设置密码
          user:
            name: "{{username}}"
            shell: /bin/bash
            password: '{{passwd |password_hash("sha512","jiaxing")}}'
            state: present
          tags:
            - useradd ans
        - name: 02.配置sudo权限
          lineinfile:
            path: "{{sudo_cfg}}"
            line: "{{username}} ALL=(ALL) NOPASSWD: ALL"
            backup: yes
          tags:
            - update sudo config
        - name: 03.修改ssh配置文件禁止root远程连接
          replace:
            path: "{{sshd_cfg}}"
            regexp: "^(#PermitRootLogin yes)|(PermitRootLogin yes)"
            replace: "PermitRootLogin no"
    
    • ansible使用普通用户ans远程登录(具备sudo权限,不需要密码)
#管理端
#1.向被管理端分发密钥 执行脚本
#2.修改ansible管理端配置文件使用sudo登录
#3.调试测试 ansible all -i hosts -m ping


#ansible本地配置需要改的内容/etc/ansible/ansible.cfg
forks=5					#ansible最大并行操作几台机器,根据情况怎加数量
sudo_user=ans			#远端具有sudo权限的用户ans
remote_port=22			#远程连接的端口
host_key_checking=False	#运行ansible时是否检查key
remote_user=ans			#远端使用的用户ans
log_path=/var/log/ansible.log	#ansible日志文件
become=True				#开启sudo功能
become_method=sudo		#远端连接ans使用sudo命令
become_user=root		#普通用户切换为root

其他优化

  • 性能
    • ssh连接速度优化,关闭UseDNS,GSSAPIAuthcation ....
    • 不要让ansible运行交互式的命令,非要用使用命令的非交互模式.
    • 需要使用ans,yum安装软件,可以自建本地yum仓库,然后ans安装.(自建yum源,自己制作的rpm包)
    • 调整ansible并发数量( -f 调整并发数量 默认是5 ansible.cfg ,forks=5,实际调整根据负载情况.)
    • 给ansible配置缓存(redis),队列.缓存facts.
    • 给主机进行分组操作与管理.
    • 关闭gather_facts,如果不用facts变量可以关闭, 剧本中: gather_facts: false 配置文件:gathering = explicit
    • 关闭host,key,check 一般使用密码认证的时候需要关闭,如果不关闭 ansible配置文件 host_key_checking = False
  • 安全⭐
    • ⭐ 配置sudo用户 ans ALL=(ALL) NOPASSWD: ALL 密码是1,ssh端口是 22
    • 配合vpn,jms一起使用
    • 用户 ---->vpn---->jms(跳板机)---->ansible
    • 用户的密码,进行加密( hash, ansible-vault)

踩坑日记

 _________________________
< TASK [解压etcd软件包到etcd集群] >
 -------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

fatal: [10.0.0.242]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "Failed to find handler for \"/root/.ansible/tmp/ansible-tmp-1727671502.32-11899-50716666834698/source\". Make sure the required command to extract the file is installed. Command \"/usr/bin/unzip\" could not handle archive. Command \"/usr/bin/gtar\" could not handle archive."}
fatal: [10.0.0.241]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "Failed to find handler for \"/root/.ansible/tmp/ansible-tmp-1727671502.33-11898-259959298978359/source\". Make sure the required command to extract the file is installed. Command \"/usr/bin/unzip\" could not handle archive. Command \"/usr/bin/gtar\" could not handle archive."}
fatal: [10.0.0.243]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "Failed to find handler for \"/root/.ansible/tmp/ansible-tmp-1727671502.34-11900-22085878717261/source\". Make sure the required command to extract the file is installed. Command \"/usr/bin/unzip\" could not handle archive. Command \"/usr/bin/gtar\" could not handle archive."}


原因:压缩包损坏导致
解决:手动检查压缩包是否损坏,重新拉取软件包
[root@m01 /server/ansible/roles/ansible-kubernetes]# tar tf /download/etcd-v3.5.10-linux-amd64.tar.gz 
etcd-v3.5.10-linux-amd64/
etcd-v3.5.10-linux-amd64/README.md
etcd-v3.5.10-linux-amd64/READMEv2-etcdctl.md
etcd-v3.5.10-linux-amd64/etcdutl

gzip: stdin: unexpected end of file
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
posted @   逃离这世界~  阅读(34)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示

目录导航