Ansible相关

时间:2024-04-20 11:06:33

Ansible

环境准备

主机名 ip 分组
crontol 192.168.88.1
node1 192.168.88.11 test
node2 192.168.88.12 proxy
node3 192.168.88.13 webservers
node4 192.168.88.14 webservers
node5 192.168.88.15 database

所有操作只需在crontol上操作即可

  • 安装ansible
# 依赖一般也会跟着一起装好
yum install -y ansible
  • 配置域名解析
for i in {1..5}; do echo -e "192.168.88.1$i\tnode$i" >> /etc/hosts; done
  • 配置免密登录
ssh-keygen  # 回车即可
for i in node{1..5}; do ssh-copy-id $i ;done  # 按要求输入密码即可
  • 创建ansible工作目录
mkdir ansible && cd ansible
  • 创建配置文件(可参考:etc/ansible/ansible.cfg),以下操作都必须在工作目录下执行
vim ansible.cfg
# ansible.cfg内容
[defaults]
inventory = hosts  # 管理的主机,配置在当前目录的hosts文件中,hosts名是自定义的。=号两边空格可有可无

vim hosts
# hosts内容
[test]
node1

[proxy]
node2

[webservers]
node[3:4]

[database]
node5

[cluster:children]
webservers
database

# 测试是否成功
ansible all --list-hosts
# 输出下列结果表示成功
  hosts (5):
    node2
    node1
    node3
    node4
    node5

ansible管理分类

  • ansible远程管理
    • adhoc临时命令,也就是在命令行执行管理命令
    • playbook剧本,把管理任务用特定格式写到文件中

adhoc临时命令

  • 语法格式
ansible 主机或组列表 -m 模块 -a "参数"  # -a是可选的
  • 测试主机连通性
ansible all -m ping

ansible模块

  • 查看模块基本信息
# 查看所有模块
ansible-doc -l

# 查看指定模块
ansible-doc -l | grep file

# 查看模块使用文档,/EXAMPLE可以查看示例
ansible-doc file

command模块

  • ansible默认模块,用于在远程主机上执行任意命令
  • command不支持shell特性,如管道、重定向。
# 在所有被管主机上创建目录/tmp/demo
ansible all -a "mkdir /tmp/demo"

# 查看node1的ip地址
ansible node1 -a "ifconfig"  # ansible node1 -a "ifconfig | head -5"就会报错

shell模块

  • command模块类似,但是支持shell特性,如管道、重定向。
ansible node1 -m shell -a "ifconfig | grep inet"

script模块

  • 用于在远程主机上执行脚本
# 控制端先创建一个安装vsftpd服务的脚本
vim install.sh
# install.sh内容
#!/bin/bash

yum install -y vsftpd
systemctl start vsftpd

# 在test组执行这个脚本
ansible test -m script -a "install.sh"

注意:commandshellscript这三个模块一般不用,因为它们没有幂特性

file模块

  • 创建文件、目录、链接等,还可以修改权限,属主、属组等
  • 常用选项
    • path:指定文件路径
    • owner:设置文件所有者
    • group:设置文件所属组
    • state:状态,touch表示创建文件,directory表示创建目录,link表示创建超链接,absent表示删除
    • mode:设置权限
    • src:源文件,设置超链接的时候会用到
    • dest:目标文件,设置超链接的时候会用到
# 查看使用帮助
ansible-doc file

# 在test组的主机上创建/tmp/test.txt
ansible test -m file -a "path=/tmp/test.txt state=touch"

# 将test组的主机上的/tmp/test.txt属主和属组都修改为adm,权限修改为0777
ansible test -m file -a "path=/tmp/test.txt owner=adm group=adm mode='0777'"

# 在test组的主机上创建/tmp/demo,创建的同时设置该目录的属主和属组都修改为adm,权限修改为0777
ansible test -m file -a "path=/tmp/demo owner=adm group=adm mode='0777' state=directory"

# 在test组的主机上创建/etc/hosts的超链接,存放在/tmp/demo/hosts
ansible test -m file -a "src=/etc/hosts dest=/tmp/demo/hosts state=link"

# 删除test组的主机上的/tmp/test.txt和/tmp/demo
ansible test -m file -a "path=/tmp/demo state=absent"
ansible test -m file -a "path=/tmp/test.txt state=absent"

copy模块

  • 用于将文件从控制端拷贝到被控端
  • 常用选项
    • src:源文件路径
    • dest:目标路径
    • content:内容
    • owner:设置文件所有者
    • group:设置文件所属组
    • mode:设置文件权限
# 将本地的/etc/hostname拷贝到test组服务器的/root/下
ansible test -m copy -a "src=/etc/hostname dest=/root/"

# 在目标主机上创建/tmp/test.txt,内容是Hello bhlu
ansible test -m copy -a "content='Hello bhlu' dest=/tmp/test.txt"

fetch模块

  • 从被控端下载文件到控制端
  • 常用选项
    • src:源文件路径
    • dest:目标路径
    • flagyes代表直接下载文件,不会递归下载目录
# 将test组的主机上的/etc/hostname下载到本地的/root/下
ansible test -m fetch -a "src=/etc/hostname dest=/root/"

cat /root/node1/etc/hostname 
# node1

lineinfile模块

  • 操作目标服务器文件中的文件,可以添加,替换整行
  • 常用选项
    • path:待修改的文件路径
    • line:写入文件的一行内容
    • regexp:正则表达式,用于查找文件中内容
# 检测test组的主机的/tmp/test.txt文件中,是否有aaa,如果有,则不操作,没有就添加aaa到文件结尾
ansible test -m lineinfile -a "path=/tmp/test.txt line='aaa'"

# 将test组的主机的/tmp/test.txt文件中的包含aaa的行替换成bbb,从下往上,只替换一次
ansible test -m lineinfile -a "path=/tmp/test.txt line='bbb' regexp='aaa'"

replace模块

  • lineinfile会替换一行,replace替换关键词
  • 常用选项
    • path:待修改的文件路径
    • replace:替换成的内容
    • regexp:正则表达式,需要替换的内容
# 将test组的主机上的/tmp/test.txt中bb全部替换成haha
ansible test -m replace -a "path=/tmp/test.txt replace='haha' regexp='bbb'"

user模块

  • 实现linux用户管理
  • 常用选项
    • name:待创建的用户名
    • uid:用户ID
    • group:设置主组
    • groups:设置附加组
    • home:设置家目录
    • password:设置用户密码
    • state:状态,present表示创建,也是默认选项,absent表示删除
    • remove:删除家目录、邮箱等,yes或者true
# 在test组的主机上,创建一个bhlu的用户,uid为1020,设置主组为adm,附加组为root,密码是123456
ansible test -m user -a "name=bhlu uid=1020 group=adm groups=root password=123456"

# 修改test组的主机上的bhlu的密码为666666,使用加密算法
ansible test -m user -a "name=bhlu password={{'666666'|password_hash('sha512')}}"

# 删除test组的主机上的bhlu的用户,不删除家目录
ansible test -m user -a "name=bhlu state=absent"

# 删除test组的主机上的tools的用户,删除家目录
ansible test -m user -a "name=bhlu state=absent remove=yes"

group模块

  • 实现linux的组管理
  • 常用选项
    • name:待创建的组名
    • gid:GID
    • state:状态,present表示创建,也是默认选项,absent表示删除
# 在test组的主机上创建一个uid为1030的组,名称为project
ansible test -m group -a "name=project gid=1030"

# 将test组的主机上的名为project的组删除
ansible test -m group -a "name=project state=absent"

yum_repository模块

  • 用于配置yum
  • 常用选项
    • file:指定文件名
    • name:指定仓库名称
    • description:仓库描述
    • baseurl:仓库地址
    • gpgcheck:是否检查gpg,填yes|no,0和1都行
    • enabled:是否开启,填yes|no,0和1都行
# 在test组的主机上创建yum文件,文件为myrepo.repo,仓库名为myRepo,描述为My Repo,baseurl为ftp://yum-server/base/,开启状态,不检查gpg
ansible test -m yum_repository -a "file=myrepo name=myRepo description='My Repo' baseurl=ftp://yum-server/base/ enabled=yes gpgcheck=0"

# 被控主机
cat myrepo.repo 
[myRepo]
baseurl = ftp://yum-server/base/
enabled = 1
gpgcheck = 0
name = My Repo

yum模块

  • 用于rpm软件包管理,如安装、升级、卸载
  • 常用选项
    • name:包名
    • state:状态,present表示安装,如果安装则忽略;latest表示安装或者升级到最新版本;absent表示卸载
# 在test组的主机上安装tree
ansible test -m yum -a "name=tree"

# 在test组的主机上卸载tree
ansible test -m yum -a "name=tree state=absent"

service模块

  • 用于控制服务。启动、关闭、重启、设置开机自启
  • 常用选项
    • name:控制的服务名
    • state:状态,started表示启动;stopped表示关闭;restarted表示重启
    • enabledyes表示设置开机自启;no表示设置开机不自启
# 在test组的主机上开启vsftpd,并设置开机自启
ansible test -m service -a "name=vsftpd state=started enabled=yes"

# 在test组的主机上关闭vsftpd
ansible test -m service -a "name=vsftpd state=stopped"

逻辑卷相关模块

parted模块
  • 用于硬盘分区管理
  • 常用选项
    • device:待分区的设备
    • number:分区编号
    • state:状态,present表示创建;absent表示删除
    • part_start:分区起始位置,不写表示从开头
    • part_end:分区结束位置,不写表示结尾
# 在test组的主机上,对20G的/dev/nvme0n2进行操作,分两个分区,第一个5G,第二个15G
ansible test -m parted -a "device=/dev/nvme0n2 number=1 state=present part_end=5GiB"
ansible test -m parted -a "device=/dev/nvme0n2 number=2 state=present part_start=5GiB"
lvg模块
  • 创建、删除卷组,修改卷组大小
  • 常用选项
    • vg:定义卷组名。vg:volume group
    • pvs:物理卷,分号隔开。pvs:physical volumes
    • state:状态,present表示创建,默认状态;absent表示删除
# 在test组的主机上创建一个myvg的卷组,是有/dev/nvme0n2p1和/dev/nvme0n2p2组成
ansible test -m lvg -a "vg=myvg pvs=/dev/nvme0n2p1,/dev/nvme0n2p2 state=present"
lvol模块
  • 创建、删除逻辑卷,修改逻辑卷大小
  • 常用选项
    • vg:指定那个卷组
    • lv:逻辑卷名。lv:logical volume
    • size:逻辑卷大小,不写单位的情况下,默认以M为单位
    • state:状态,present表示创建,默认状态;absent表示删除
# 在test组的主机上创建一个逻辑卷,卷名mylv,大小为5G
ansible test -m lvol -a "vg=myvg lv=mylv size=5G"

# 修改mylv的大小为10G
ansible test -m lvol -a "vg=myvg lv=mylv size=10G"
filesystem模块
  • 用于格式化,创建文件系统
  • 常用选项
    • fstype:指定文件系统类型
    • dev:指定要格式化的设备,可以是分区,也可以是逻辑卷
    • forceyes,强制的意思,当格式化或者删除dev的时候,如果dev上有数据,需要添加这个
# 将test组的主机上的mylv格式化成xfs格式
ansible test -m filesystem -a "fstype=xfs dev=/dev/myvg/mylv"
mount模块
  • 用于挂载系统
  • 常用选项
    • path:挂载点
    • src:待挂载的设备
    • fstype:文件系统类型
    • state:状态,mounted表示永久挂载;absent表示卸载
# 将test组的主机上的/dev/myvg/mylv挂载到/data
ansible test -m mount -a "path=/data src=/dev/myvg/mylv fstype=xfs state=mounted"

# 将test组的主机上的/dev/myvg/mylv挂载到/data
ansible test -m mount -a "path=/data src=/dev/myvg/mylv fstype=xfs state=absent"

firewalld模块

  • 用于配置防火墙的模块
  • 常用选项
    • port:端口
    • permanent:是否永久生效,yes|no
    • immediate:立即生效,临时生效,默认为no
    • state:放行enabled,拒绝disabled
# 放行80端口,文件内容如下
---
- name: set firewalld
  hosts: test
  tasks:
    - name: allow 80/tcp
      firewalld:
        port: 80/tcp
        permanent: yes
        immediate: yes
        state: enabled

template模块

  • 上传文件,支持jinja2语法,跟copy模块不同
  • 常用选项
    • src:源文件路径
    • dest:目标文件路径
vim test.j2
# 文件内容如下
Hello {{name}},server is {{ansible_hostname}}

vim temp.yml
# 文件内容如下
---
- name: test template module
  hosts: test
  vars:
    name: "bhlu"
  tasks:
    - name: copy test.j2 to test
      template:
        src: test.j2
        dest: /var/www/html/index.html

# 执行,会有个警告,关于name变量,不用管
ansible-playbook temp.yml

# 测试
curl node1  # Hello bhlu,server is node1

综合测试

  • 所有操作均对test组中的主机生效

  • 在目标主机上创建/tmp/mydemo目录,属主和属组都是adm,权限为0777

  • 将控制端的/etc/hosts文件上传到目标主机的/tmp/mydemo目录中,属主和属组都是adm,权限为0600

  • 替换目标主机/tmp/mydemo/hosts文件中的node5为server5

  • 将目标主机/tmp/mydemo/hosts文件下载到控制端的当前目录

# 在目标主机上创建/tmp/mydemo目录,属主和属组都是adm,权限为0777
ansible test -m file -a "path=/tmp/mydemo owner=adm group=adm mode='0777' state=directory"

# 将控制端的/etc/hosts文件上传到目标主机的/tmp/mydemo目录中,属主和属组都是adm,权限为0600
ansible test -m copy -a "src=/etc/hosts dest=/tmp/mydemo owner=adm group=adm mode='0600'"

# 替换目标主机/tmp/mydemo/hosts文件中的node5为server5
ansible test -m replace -a "path=/tmp/mydemo/hosts replace='server5' regexp='node5'"

# 将目标主机/tmp/mydemo/hosts文件下载到控制端的当前目录
ansible test -m fetch -a "src=/tmp/mydemo/hosts dest=."

Playbook剧本

  • 常用于复杂任务的管理,以及管理经常要完成的任务
  • playbook也是通过模块和它的参数,在特定主机上执行任务
  • playbook是一个文件,该文件中需要通过yaml格式进行书写

YAML

  • YAML Ain’t a Markup Language:YAML不是一个标记语言

yaml语法规范

  1. yaml文件的文件名,一般以ymlyaml作为扩展名
  2. 文件一般以---作为第一行,不是必须的,但是常用
  3. 键值对使用冒号:表示,冒号后面必须有空格
  4. 数组使用-表示,-后面必须有空格
  5. 相同的层级必须有相同的缩进。如果缩进不对,则有语法错误。每一级缩进,建议2个空格
  6. 全文不能使用tab,必须使用空格

配置vim适应yaml语法

vim ~/.vimrc
set ai  # 设置自动缩进
set ts=2  # 设置按tab键,缩进2个空格
set et  # 将tab转换成相应的空格

yaml文件格式

  • 一般不能出现中文,下面的中文只是帮助理解
---
- name: 简介
  hosts: 主机或组,用分号隔开
  tasks:
    - name: 任务1介绍
      file:
         path: ...
         state: ...
         mode: ...
         
    - name: 任务2介绍
      copy:
        src: ...
        copy: ...

示例

  1. test组和node2上创建/tmp/demo目录,权限是0600,将控制端/etc/hosts拷贝到被控主机的/tmp/demo
  • vim fileop.yml
---
- name: create directory and copy file
  hosts: test,node2
  tasks:
    - name: create directory
      file:
        path: /tmp/demo
        state: directory
        mode: '0600'

    - name:
      copy:
        src: /etc/hosts
        dest: /tmp/demo/hosts
  • 运行:ansible-playbook fileop.yml
  1. 在test组中的主机上,创建用户bob,附加组是adm;在node2主机上,创建/tmp/test.txt,其内容为Hello bhlu
  • vim test.yml(文件中的content的|可以保留换行符,如果是>那就是将多行合并成一行)
---
- name: create user and touch file
  hosts: test
  tasks:
    - name: create user bob
      user:
        name: bob
        groups: adm

    - name: touch file
      copy:
        dest: /tmp/test.txt
        content: |
          Hello bhlu
  • 运行:ansible-playbook test.yml
  1. 在test组中的主机上创建bhlu用户,它的uid是1040,主组是daemon,密码为123
  • vim user.yml
---
- name: create user
  hosts: test
  tasks:
    - name: create user bhlu
      user:
        name: bhlu
        uid: 1040
        group: daemon
        password: "{{'123'|password_hash('sha512')}}"
  • 运行:ansible-playbook user.yml
  1. 磁盘管理

将test组的主机上/dev/nvme0n3,创建两个物理盘,第一个5G,第二个15G,/dev/nvme0n3一共是20G

将两个物理盘组成一个叫test-vg的卷组

在test-vg卷组上创建一个叫test-lv的逻辑卷,大小5G

将test-lv格式化成xfs

将test-lv永久挂载到/data

  • vim disk.yml
---
- name: disk manage
  hosts: test
  tasks:
  - name: create pv1
    parted: 
      device: /dev/nvme0n3
      number: 1
      state: present
      part_end: 5GiB
  
  - name: create pv2
    parted:
      device: /dev/nvme0n3
      number: 2
      state: present
      part_start: 5GiB

  - name: create vg
    lvg:
      vg: test-vg
      pvs: /dev/nvme0n3p1,/dev/nvme0n3p2

  - name: create lv
    lvol:
      vg: test-vg
      lv: test-lv
      size: 5G

  - name: create filesystem
    filesystem:
      dev: /dev/test-vg/test-lv
      fstype: xfs

  - name: mount
    mount:
      path: /data
      src: /dev/test-vg/test-lv
      fstype: xfs
      state: mounted
  • 运行:ansible-playbook disk.yml
  1. 安装多个软件包
---
- name: install pkg
  hosts: test
  tasks:
    - name: install httpd,tree,tar
      yum:
        name: [httpd,tree,tar]
        state: present
  1. 安装软件包组
# 查看软件包组
yum grouplist

# 如果显示是中文,可以加LANG=C yum grouplist
LANG=c yum grouplist

# 安装组
yum groupinstall "组名"
---
- name: install package groups
  hosts: test
  tasks:
    - name: install Development Tools
      yum:
        name: "@Development Tools"
        state: present
  1. 更新系统所有包,相当于yum update
---
- name: update packages
  hosts: test
  tasks:
    - name: update system
      yum:
        name: "*"
        state: latest

变量

facts变量
  • facts变量是ansible自带的预定义变量,用于描述被控端软硬件信息
  • 查看所有facts变量
ansible test -m setup
  • 可以通过filter来过滤想要查看的信息
# 查看所有ipv4地址信息
ansible test -m setup -a "filter=ansible_all_ipv4_addresses"

# 查看可用内存
ansible test -m setup -a "filter=ansible_memfree_mb"
  • 常用的facts变量

    • ansible_all_ipv4_addresses:所有的IPV4地址
    • ansible_bios_version:BIOS版本信息
    • ansible_memtotal_mb:总内存大小
    • ansible_hostname:主机名
  • 示例

---
- name: display host info
  hosts: test
  tasks:
    - name: display hostname and memory
      debug:
        msg: "hostname: {{ansible_hostname}}  mem: {{ansible_memtotal_mb}}MB"
自定义变量
  • 引入变量,可以方便Playbook重用。比如装包的playbook,包名使用变量。多次执行playbook,只要改变变量名即可,不用编写新的playbook。

  • ansible支持10种以上的变量定义方式。常用的变量来源如下:

    • inventory变量。变量来自于主机清单文件
    • facts变量。
    • playbook变量。变量在playbook中定义。
    • 变量文件。专门创建用于保存变量的文件。推荐变量写入单独的文件
  • 使用inventory变量示例,在node1主机上创建一个用户bhlu,在webservers组的主机上创建一个用户maomao

vim hosts
# hosts内容如下
[test]
node1 username="bhlu"  # 这里定义test组的

[proxy]
node2

[webservers]
node[3:4]

[database]
node5

[cluster:children]
webservers
database

[webservers:vars]  # 固定写法 :vars
username="maomao"

# 创建yml文件
vim var.yml
# var.yml内容如下
---
- name: create users
  hosts: test,webservers
  tasks:
    - name: create user
      user:
        name: "{{username}}"
        state: present
        
# 执行
ansible-playbook var.yml
  • 在playbook中定义变量
---
- name: create user
  hosts: test
  vars:  # 固定是vars
    username: "bhlu"
    passowrd: "123"
  tasks:
    - name: create bhlu
      user:
        name: "{{username}}"
        password: "{{passowrd|password_hash('sha512')}}"
        state: present
  • 将变量定义在文件里
vim user_vars.yml
# 文件内容
---
user: "maomao"
pwd: "123"

vim user.yml
# 文件内容
---
- name: create
  hosts: test
  vars_files: user_vars.yml
  tasks:
    - name: create maomao
      user:
        name: "{{user}}"
        password: "{{pwd|password_hash('sha512')}}"
        state: present
        
# 执行
ansible-playbook user.yml

错误处理

  • 解决当前面任务运行错误,后面任务就不执行的问题
# 默认是下面这样写的,但是当启动test服务失败时,会直接跳出,不会执行下面的任务了
---
- name: test error
  hosts: test
  tasks:
    - name: start test service
      service:
        name: test
        state: started
        enabled: yes

    - name: touch a file
      file:
        path: /tmp/test.txt
        state: touch
        
# 优化后
cat test.yml
---
- name: test error
  hosts: test
  tasks:
    - name: start test service
      ignore_errors: yes  # 忽略错误
      service:
        name: test
        state: started
        enabled: yes

    - name: touch a file
      file:
        path: /tmp/test.txt
        state: touch
        
# 全局优化
---
- name: test error
  hosts: test
  ignore_errors: yes  # 不管哪个任务发生错误,都会忽略
  tasks:
    - name: start test service
      service:
        name: test
        state: started
        enabled: yes

    - name: touch a file
      file:
        path: /tmp/test.txt
        state: touch

触发执行任务

  • 不管第一个任务是否执行,第二个任务都会执行,有些情况是不需要这样的
# 不管有没有修改配置文件,都会重启服务
---
- name: test trigger
  hosts: test
  vars:
    http_port: "80"
  tasks:
    - name: upload httpd.conf
      template:
        src: httpd.conf
        dest: /etc/httpd/conf/httpd.conf

    - name: restart httpd
      service:
        name: httpd
        state: restarted
        

# 优化后,只有第一个任务changed,才会执行第二个任务
---
- name: test trigger
  hosts: test
  vars:
    http_port: "8080"
  tasks:
    - name: upload httpd.conf
      template:
        src: httpd.conf
        dest: /etc/httpd/conf/httpd.conf
      notify: restart httpd  # 通知,后面的要对应上,空格也不能少

  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted

when条件

  • 只有满足条件时,才执行任务<