Ansible 安装部署及常用模块的使用

准备工作:

安装方式:这里我们选择使用yum直接安装

server端操作系统:Centos 7

修改镜像源为阿里云的源

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum clean all
yum makecache
yum install -y epel-release     # 需要epel源支持

安装

yum install -y ansible

检查是否安装成功:

[root@harbor ~]# ansible --version
ansible 2.9.3
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]

命令补全

https://github.com/dysosmus/ansible-completion

[root@harbor ansible]# wget https://github.com/dysosmus/ansible-completion/raw/master/ansible-completion.bash
[root@harbor ansible]# wget https://github.com/dysosmus/ansible-completion/raw/master/ansible-doc-completion.bash
[root@harbor ansible]# wget https://github.com/dysosmus/ansible-completion/raw/master/ansible-galaxy-completion.bash
[root@harbor ansible]# wget https://github.com/dysosmus/ansible-completion/raw/master/ansible-playbook-completion.bash
[root@harbor ansible]# wget https://github.com/dysosmus/ansible-completion/raw/master/ansible-pull-completion.bash
[root@harbor ansible]# wget https://github.com/dysosmus/ansible-completion/raw/master/ansible-vault-completion.bash
[root@harbor ansible]# cp * /etc/bash_completion.d/
[root@harbor ansible]# source /etc/profile.d/bash_completion.sh
# 如果没效果就执行 source /etc/bashrc

开启日志记录:

vim /etc/ansible/ansible.cfg        # 取消注释下面这行
log_path = /var/log/ansible.log

ansible 程序结构

安装目录如下(yum安装):
 配置文件目录:/etc/ansible/
 执行文件目录:/usr/bin/
 Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/
 Help文档目录:/usr/share/doc/ansible-X.X.X/
 Man文档目录:/usr/share/man/man1/

初始化

添加被管机IP

编辑(或创建)/etc/ansible/hosts 并在其中加入一个或多个远程系统.你的public SSH key必须在这些系统的authorized_keys中:

这里根据需求我添加了6台服务器:

[root@harbor harbor]# cat /etc/ansible/hosts |grep "^\s*[^# \t].*$"
[k8s_master]
k8s-master[01:03]
[k8s_node]
k8s-node[01:03]

收集被管机公钥或者关闭公钥认证(二选一即可)

收集被管服务器的公钥做公钥认证,它的目的是创建和验证“ssh_known_hosts”文件

ssh-keyscan k8s-master01 k8s-master02 k8s-master03 k8s-node01 k8s-node02 k8s-node03 >> /root/.ssh/known_hosts

如果不想启用公钥认证(推荐)

关闭公钥认证的方法有两种(推荐):

- 编辑ansible.cfg配置文件 (/etc/ansible/ansible.cfg)

[defaults]
host_key_checking = False
  • 直接设置环境变量
命令为:
export ANSIBLE_HOST_KEY_CHECKING=False

创建公钥

[root@harbor ansible]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:CobRTxn2/KOf4a3Q2Ks/0ReP50bVZtMnBiDzJ7euwNM root@harbor
The key's randomart image is:
+---[RSA 2048]----+
|      o o ..     |
|   . . = +  .    |
|  . . o o o o.  o|
|   o o   . + .+.B|
|  . o . S o... B+|
|   . . o *.o. o +|
|      . B E... + |
|         *.*    o|
|        .oOo.  . |
+----[SHA256]-----+

编写Playbook剧本文件

[root@harbor harbor]# cd /etc/ansible/
[root@harbor ansible]# ls
ansible.cfg  hosts  roles
[root@harbor ansible]# vim ssh.yml
[root@harbor ansible]# cat ssh.yml  # 这里的hosts参数可以改变为指定的host组
---
- hosts: all
  gather_facts: no

  tasks:

  - name: install ssh key
    authorized_key: user=root
                    key="{{ lookup('file', '/root/.ssh/id_rsa.pub') }}"
                    state=present

运行playbook文件做免密认证

[root@harbor ansible]# ansible-playbook -i hosts ssh.yml -k     # 如果需要使用其他用户添加-u xxx
SSH password:

PLAY [all] ********************************************************************************************************************************************************************************************************

TASK [install ssh key] ********************************************************************************************************************************************************************************************
changed: [k8s-master02]
changed: [k8s-master01]
changed: [k8s-master03]
changed: [k8s-node02]
changed: [k8s-node01]
changed: [k8s-node03]

PLAY RECAP ********************************************************************************************************************************************************************************************************
k8s-master01               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
k8s-master02               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
k8s-master03               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
k8s-node01                 : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
k8s-node02                 : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
k8s-node03                 : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

输入密码后应该都会被加入被管了,执行下命令测试一下

[root@harbor ansible]# ansible k8s_master -m ping
k8s-master02 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
k8s-master03 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
k8s-master01 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
[root@harbor ansible]# ansible k8s_node -m ping
k8s-node01 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
k8s-node02 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
k8s-node03 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
[root@harbor ansible]# cat ~/.ssh/known_hosts       # 可以看到都已经添加进去了
k8s-master01,192.168.1.50 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM221wY62j/3BRakXcMfnhNZtK68XmM3UpFskgtWT/kVknc44MuNsLuwP/zTTO9b7EhQbK70yHlRkHfHG3fHU4A=
k8s-master03,192.168.1.52 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM221wY62j/3BRakXcMfnhNZtK68XmM3UpFskgtWT/kVknc44MuNsLuwP/zTTO9b7EhQbK70yHlRkHfHG3fHU4A=
k8s-master02,192.168.1.51 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM221wY62j/3BRakXcMfnhNZtK68XmM3UpFskgtWT/kVknc44MuNsLuwP/zTTO9b7EhQbK70yHlRkHfHG3fHU4A=
k8s-node02,192.168.1.61 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM221wY62j/3BRakXcMfnhNZtK68XmM3UpFskgtWT/kVknc44MuNsLuwP/zTTO9b7EhQbK70yHlRkHfHG3fHU4A=
k8s-node01,192.168.1.60 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM221wY62j/3BRakXcMfnhNZtK68XmM3UpFskgtWT/kVknc44MuNsLuwP/zTTO9b7EhQbK70yHlRkHfHG3fHU4A=
k8s-node03,192.168.1.62 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM221wY62j/3BRakXcMfnhNZtK68XmM3UpFskgtWT/kVknc44MuNsLuwP/zTTO9b7EhQbK70yHlRkHfHG3fHU4A=
[root@harbor ansible]# ssh k8s-master03     # 尝试无密码登录
Last login: Fri Feb 14 12:44:40 2020 from hub.lixiang.com
[root@k8s-master03 ~]# exit
登出
Connection to k8s-master03 closed.
[root@harbor ~]# ansible k8s_master --list
  hosts (3):
    k8s-master01
    k8s-master02
    k8s-master03

可以看到返回都很正常

常用模块

ping模块

这个上面已经演示过了:

ansible <host-pattern> -m ping

以wang用户执行ping存活检测

ansible all -m ping -u wang -k

以wang sudo至root执行ping检测

ansible all -m ping -u wang -b -k

以wang sudo至mage用户执行ping存活检测

ansible all -m ping -u wang -b -k --become-user mage

command模块 (默认模块)

ansible <host-pattern> [-f forks] [-m module_name] [-a args]
[root@harbor ansible]# ansible lede -m command -a "ip a"    # 由于是默认模块,-m 后可不加command
192.168.1.111 | CHANGED | rc=0 >>
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c5:d6:44 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.111/24 brd 192.168.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fec5:d644/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:a8:f0:9f:f0 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

以wang sudo 至root用户执行ls

ansible all -m command -u wang --become-user=root -a 'ls /root' -b -k -K

shell模块

command模块无法处理代参数、管道或者环境变量的命令,这个时候就需要shell模块来执行

[root@harbor ansible]# ansible k8s-node03 -a 'echo $hostname'
k8s-node03 | CHANGED | rc=0 >>
$hostname

[root@harbor ansible]# ansible k8s-node03 -m shell -a 'echo $hostname'
k8s-node03 | CHANGED | rc=0 >>

[root@harbor ansible]# ansible k8s-node03 -a 'echo 123456|passwd --stdin test1' # command 模块实际不会执行
k8s-node03 | CHANGED | rc=0 >>
123456|passwd --stdin test1

[root@harbor ansible]# ansible k8s-node03 -m shell -a 'echo 123456|passwd --stdin test1'
k8s-node03 | CHANGED | rc=0 >>
更改用户 test1 的密码 。
passwd:所有的身份验证令牌已经成功更新。

script模块

在指定机器上执行ansible上指定的脚本

[root@harbor ansible]# vim host.sh
[root@harbor ansible]# cat host.sh
#!/bin/bash
hostname
[root@harbor ansible]# chmod +x host.sh
[root@harbor ansible]# ansible k8s-node03 -m script -a ~/ansible/host.sh
k8s-node03 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to k8s-node03 closed.\r\n",
    "stderr_lines": [
        "Shared connection to k8s-node03 closed."
    ],
    "stdout": "k8s-node03\r\n",
    "stdout_lines": [
        "k8s-node03"
    ]
}

copy模块

[root@harbor ~]# ansible k8s-node03 -m copy -a 'src=/root/111 dest=/root/ backup=yes'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/root/111.9184.2020-02-21@12:04:56~", 
    "changed": true, 
    "checksum": "f0fbe82ee70ca0dc32ea691eb8d9f2dc2be1aa57", 
    "dest": "/root/111", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "fdd30fbcc1024bebea93f6076076c15a", 
    "mode": "0644", 
    "owner": "root", 
    "size": 7, 
    "src": "/root/.ansible/tmp/ansible-tmp-1582257895.69-175368708621216/source", 
    "state": "file", 
    "uid": 0
}

如果需要修改文件权限,或者文件所属用户及组,可以参考一下:

[root@harbor ~]# ansible k8s-node03 -m copy -a 'src=/root/111 dest=/root/ backup=yes mode=000 owner=root group=root'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "f0fbe82ee70ca0dc32ea691eb8d9f2dc2be1aa57", 
    "dest": "/root/111", 
    "gid": 0, 
    "group": "root", 
    "mode": "0000", 
    "owner": "root", 
    "path": "/root/111", 
    "size": 7, 
    "state": "file", 
    "uid": 0
}

fetch模块

使用说明: 注意这个模块只能操作单个文件

[root@harbor ~]# ansible-doc -s fetch
- name: Fetch files from remote nodes
  fetch:
      dest:                  # (required) A directory to save the file into. For example, if the `dest' directory is `/backup' a `src' file named
                               `/etc/profile' on host `host.example.com', would be saved into
                               `/backup/host.example.com/etc/profile'. The host name is based on the inventory
                               name.
      fail_on_missing:       # When set to `yes', the task will fail if the remote file cannot be read for any reason. Prior to Ansible 2.5,
                               setting this would only fail if the source file was missing. The default was changed
                               to `yes' in Ansible 2.5.
      flat:                  # Allows you to override the default behavior of appending hostname/path/to/file to the destination. If `dest' ends
                               with '/', it will use the basename of the source file, similar to the copy module.
                               This can be useful if working with a single host, or if retrieving files that are
                               uniquely named per host. If using multiple hosts with the same filename, the file
                               will be overwritten for each host.
      src:                   # (required) The file on the remote system to fetch. This `must' be a file, not a directory. Recursive fetching may
                               be supported in a later release.
      validate_checksum:     # Verify that the source and destination checksums match after the files are fetched.

示例:

[root@harbor ~]# ansible k8s-node03 -m fetch -a 'src=/var/log/messages dest=~'
k8s-node03 | CHANGED => {
    "changed": true, 
    "checksum": "81c5a7255563bdd09fa4ec570be5d4822850e850", 
    "dest": "/root/k8s-node03/var/log/messages", 
    "md5sum": "7e889237d8978b68cfae2dd711b1a80c", 
    "remote_checksum": "81c5a7255563bdd09fa4ec570be5d4822850e850", 
    "remote_md5sum": null
}

archive模块(打包模块)

ansible-doc -s archive 
- name: Creates a compressed archive of one or more files or trees.
  action: archive
      dest         # 目标归档文件名。除非path指定要压缩的是单文件,否则需要dest选项
      format       # 指定压缩格式,默认为gz格式
      group        # 文件/目录的所属组
      owner        # 文件/目录的所有者
      mode         # 设置文件/目录的的权限,支持'0644'或'u+rwx'或'u=rw,g=r,o=r'等格式
      path=        # 要压缩的文件,可以是绝对路径,也可以是glob统配的路径,还可以是文件列表
      remove       # 压缩后删除源文件

示例

[root@harbor ~]# ansible k8s-node03 -m archive -a 'path=/root/anaconda-ks.cfg format=tar dest=/mnt/111.tar'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "archived": [
        "/root/anaconda-ks.cfg"
    ], 
    "arcroot": "/root/", 
    "changed": true, 
    "dest": "/mnt/111.tar", 
    "expanded_exclude_paths": [], 
    "expanded_paths": [
        "/root/anaconda-ks.cfg"
    ], 
    "gid": 0, 
    "group": "root", 
    "missing": [], 
    "mode": "0644", 
    "owner": "root", 
    "size": 10240, 
    "state": "file", 
    "uid": 0
}

file模块

创建文件夹:

[root@harbor ~]# ansible k8s-node03 -m file -a 'dest=/root/222 state=directory'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/root/222", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}

创建文件:

[root@harbor ~]# ansible k8s-node03 -m file -a 'dest=/root/333 state=touch'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/root/333", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}

创建软连接

[root@harbor ~]# ansible k8s-node03 -m file -a 'src=/root/333 dest=/root/333-link state=link'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/root/333-link", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 9, 
    "src": "/root/333", 
    "state": "link", 
    "uid": 0
}

删除文件或目录

[root@harbor ~]# ansible k8s-node03 -m file -a 'dest=/root/333-link state=absent'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/root/333-link", 
    "state": "absent"
}

设置文件属性

[root@harbor ~]# ansible k8s-node03 -m file -a 'path=/root/333 mode=755 owner=test'

cron模块(定时模块)

创建(这里建议每次创建都指定好name参数,否则会存在重复创建的情况)

[root@harbor ~]# ansible k8s-node03 -m cron -a 'minute=* weekday=1,3,5,6 job="/usr/bin/wall FBI warning" name=warningcron'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "warningcron"
    ]
}

停用指定定时任务

[root@harbor ~]# ansible k8s-node03 -m cron -a 'disabled=true job="/usr/bin/wall FBI warning" name=warningcron'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "warningcron"
    ]
}

启用指定定时任务

[root@harbor ~]# ansible k8s-node03 -m cron -a 'disabled=false job="/usr/bin/wall FBI warning" name=warningcron'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "warningcron"
    ]
}

删除指定定时任务

[root@harbor ~]# ansible k8s-node03 -m cron -a 'job="/usr/bin/wall FBI warning" name=warningcron state=absent'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": []
}

yum模块

安装

[root@harbor ~]# ansible k8s-node03 -m yum -a 'name=htop,nload state=latest'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "htop", 
            "nload"
        ], 
        "updated": []
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.aliyun.com\n * elrepo: mirrors.tuna.tsinghua.edu.cn\n * epel: mirrors.tuna.tsinghua.edu.cn\n * extras: mirrors.aliyun.com\n * updates: mirrors.ustc.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package htop.x86_64 0:2.2.0-3.el7 will be installed\n---> Package nload.x86_64 0:0.7.4-4.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package         Arch             Version                  Repository      Size\n================================================================================\nInstalling:\n htop            x86_64           2.2.0-3.el7              epel           103 k\n nload           x86_64           0.7.4-4.el7              epel            70 k\n\nTransaction Summary\n================================================================================\nInstall  2 Packages\n\nTotal download size: 174 k\nInstalled size: 393 k\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                              121 kB/s | 174 kB  00:01     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : htop-2.2.0-3.el7.x86_64                                      1/2 \n  Installing : nload-0.7.4-4.el7.x86_64                                     2/2 \n  Verifying  : nload-0.7.4-4.el7.x86_64                                     1/2 \n  Verifying  : htop-2.2.0-3.el7.x86_64                                      2/2 \n\nInstalled:\n  htop.x86_64 0:2.2.0-3.el7              nload.x86_64 0:0.7.4-4.el7             \n\nComplete!\n"
    ]
}

删除包:

[root@harbor ~]# ansible k8s-node03 -m yum -a 'name=htop,nload state=absent'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "removed": [
            "htop", 
            "nload"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nResolving Dependencies\n--> Running transaction check\n---> Package htop.x86_64 0:2.2.0-3.el7 will be erased\n---> Package nload.x86_64 0:0.7.4-4.el7 will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package         Arch             Version                 Repository       Size\n================================================================================\nRemoving:\n htop            x86_64           2.2.0-3.el7             @epel           218 k\n nload           x86_64           0.7.4-4.el7             @epel           176 k\n\nTransaction Summary\n================================================================================\nRemove  2 Packages\n\nInstalled size: 393 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Erasing    : htop-2.2.0-3.el7.x86_64                                      1/2 \n  Erasing    : nload-0.7.4-4.el7.x86_64                                     2/2 \n  Verifying  : nload-0.7.4-4.el7.x86_64                                     1/2 \n  Verifying  : htop-2.2.0-3.el7.x86_64                                      2/2 \n\nRemoved:\n  htop.x86_64 0:2.2.0-3.el7              nload.x86_64 0:0.7.4-4.el7             \n\nComplete!\n"
    ]
}

service模块

设置服务启动并开机自启

[root@harbor ~]# ansible k8s-node03 -m service -a 'name=ntpd state=started enabled=true'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "enabled": true, 
    "name": "ntpd", 
    "state": "started", 
    "status": {
        "ActiveEnterTimestampMonotonic": "0", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "inactive", 
    """
    """
    }
}

停止服务并关闭开机自启

[root@harbor ~]# ansible k8s-node03 -m service -a 'name=ntpd state=stopped enabled=false'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "enabled": false, 
    "name": "ntpd", 
    "state": "stopped", 
    "status": {
        "ActiveEnterTimestamp": "Sat 2020-02-22 19:05:16 CST", 
        "ActiveEnterTimestampMonotonic": "11389238933", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "active", 
        """
        """
    }
}

user 模块

创建用户,指定UID,指定home路径,指定nologin,指定groups

[root@harbor ~]# ansible k8s-node03 -m user -a 'name=testuser shell=/sbin/nologin system=yes home=/home/nginx groups=root,bin uid=666 comment="account for test"'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "account for test", 
    "create_home": true, 
    "group": 666, 
    "groups": "root,bin", 
    "home": "/home/nginx", 
    "name": "testuser", 
    "shell": "/sbin/nologin", 
    "state": "present", 
    "system": true, 
    "uid": 666
}
[root@harbor ~]# ansible k8s-node03 -a 'getent passwd testuser'     # 查看是否创建成功
k8s-node03 | CHANGED | rc=0 >>
testuser:x:666:666:account for test:/home/nginx:/sbin/nologin

删除指定用户

[root@harbor ~]# ansible k8s-node03 -m user -a 'name=testuser state=absent remove=yes'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "testuser", 
    "remove": true, 
    "state": "absent", 
    "stderr": "userdel: testuser mail spool (/var/spool/mail/testuser) not found\n", 
    "stderr_lines": [
        "userdel: testuser mail spool (/var/spool/mail/testuser) not found"
    ]
}
[root@harbor ~]# ansible k8s-node03 -a 'getent passwd testuser'     # 确认删除
k8s-node03 | FAILED | rc=2 >>
non-zero return code

group模块

创建组

[root@harbor ~]# ansible k8s-node03 -m group -a 'name=testgroup system=yes gid=666'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 666, 
    "name": "testgroup", 
    "state": "present", 
    "system": true
}
[root@harbor ~]# ansible k8s-node03 -a 'getent group testgroup'     #   验证
k8s-node03 | CHANGED | rc=0 >>
testgroup:x:666:

删除组


[root@harbor ~]# ansible k8s-node03 -m group -a 'name=testgroup state=absent'
k8s-node03 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "testgroup", 
    "state": "absent"
}
[root@harbor ~]# ansible k8s-node03 -a 'getent group testgroup'
k8s-node03 | FAILED | rc=2 >>
non-zero return code

选择执行对象

sudo执行

如果需要远程并sudo 至root用户执行相关命令:

[root@harbor ansible]# ansible lede -m command -a "ls -a /root" -b -K       # -b 默认参数是root -K 输入sudo的密码
BECOME password:
192.168.1.111 | CHANGED | rc=0 >>
.
..
.bash_history
.bashrc
docker_test
.profile
.ssh
.viminfo

多个组同时执行

[root@harbor ansible]# ansible '*master:lede' -m ping       #   组与组之间加冒号

同时满足几个组的交集执行:(a与b的交集)

[root@harbor ansible]# ansible '*master:&lede' -m ping      #   组与组之间加:&

满足a,但不在b组中的主机执行:

[root@harbor ansible]# ansible '*master:!lede' -m ping      #   需要注意顺序,组与组之间加:!
[root@harbor ansible]# ansible '*master:!lede' -m ping
k8s-master01 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host k8s-master01 port 22: No route to host",
    "unreachable": true
}
k8s-master02 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host k8s-master02 port 22: No route to host",
    "unreachable": true
}
k8s-master03 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host k8s-master03 port 22: No route to host",
    "unreachable": true
}
[root@harbor ansible]# ansible 'lede:!*master' -m ping
192.168.1.111 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

正则

按host环境条件执行

removes条件满足则执行
[root@harbor ansible]# ansible lede -a 'removes=/etc/fs cat /etc/fstab'
192.168.1.111 | SUCCESS | rc=0 >>
skipped, since /etc/fs does not exist

[root@harbor ansible]# ansible lede -a 'removes=/etc/fstab cat /etc/fstab'
192.168.1.111 | CHANGED | rc=0 >>
UUID=97a2ffb1-7a68-428d-8ef0-7c96b9b6989a / ext4 defaults 0 0
UUID=cc756777-a22d-4dee-afd8-0d2ebb677693 /boot ext4 defaults 0 0
/swap.img   none    swap    sw  0   0
creates条件满足则不执行
[root@harbor ansible]# ansible lede -a 'creates=/home/lixiang/lean-lede ip a'
192.168.1.111 | SUCCESS | rc=0 >>
skipped, since /home/lixiang/lean-lede exists

[root@harbor ansible]# ansible lede -a 'creates=/home/lixiang/lean ip a'
192.168.1.111 | CHANGED | rc=0 >>
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:c5:d6:44 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.111/24 brd 192.168.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fec5:d644/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:a8:f0:9f:f0 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

[root@harbor ansible]# ansible lede -a 'ls /home/lixiang'
192.168.1.111 | CHANGED | rc=0 >>
lean-lede
wget-log
切换到指定目录再执行

使用chdir参数指定需要切换的目录

[root@harbor ansible]# ansible lede -a 'chdir=/home/lixiang ls'
192.168.1.111 | CHANGED | rc=0 >>
lean-lede
wget-log

查看模块使用文档

usage: ansible-doc [-h] [--version] [-v] [-M MODULE_PATH]
                   [--playbook-dir BASEDIR]
                   [-t {become,cache,callback,cliconf,connection,httpapi,inventory,lookup,netconf,shell,module,strategy,vars}]
                   [-j] [-F | -l | -s | --metadata-dump]
                   [plugin [plugin ...]]
[root@harbor ansible]# ansible-doc command -s       # 添加 -s 简易模式
- name: Execute commands on targets
  command:
      argv:                  # Passes the command as a list rather than a string. Use `argv' to avoid quoting values that would otherwise be interpreted incorrectly (for example
                               "user name"). Only the string or the list form can be provided, not both.  One or the other must be provided.
      chdir:                 # Change into this directory before running the command.
      cmd:                   # The command to run.
      creates:               # A filename or (since 2.0) glob pattern. If it already exists, this step *won't* be run.
      free_form:             # The command module takes a free form command to run. There is no actual parameter named 'free form'.
      removes:               # A filename or (since 2.0) glob pattern. If it already exists, this step *will* be run.
      stdin:                 # Set the stdin of the command directly to the specified value.
      stdin_add_newline:     # If set to `yes', append a newline to stdin data.
      strip_empty_ends:      # Strip empty lines from the end of stdout/stderr in result.
      warn:                  # Enable or disable task warnings.

交互式工具

[root@harbor ansible]# ansible-console      # 多用于调试playbook
Welcome to the ansible console.
Type help or ? to list commands.
 
root@all (7)[f:5]$ cd 
192.168.1.111  k8s-master01   k8s-master03   k8s-node02     k8s_master     lede           
all            k8s-master02   k8s-node01     k8s-node03     k8s_node       ungrouped      
root@all (7)[f:5]$ cd k8s-node03
root@k8s-node03 (1)[f:5]$ command hostname
k8s-node03 | CHANGED | rc=0 >>
k8s-node03

root@k8s-node03 (1)[f:5]$ exit

PlayBook

基础写法

[root@harbor ansible]# vim playbook.yml
- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: hello
      command: hostname

执行playbook

[root@harbor ansible]# ansible-playbook playbook.yml 

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [hello] **************************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

playbook加密和解密

[root@harbor ansible]# ansible-vault encrypt playbook.yml   # 加密
New Vault password: 
Confirm New Vault password: 
Encryption successful
[root@harbor ansible]# cat playbook.yml 
$ANSIBLE_VAULT;1.1;AES256
38666630626439353938656236623532346466373735313261623261356334373661373538393234
6330613030373664373635643031396432373532353831330a626430396533646237656134383435
65636532393130636164353362356337633761643037633135346564373836643439636230306533
3437616661613831610a356631363064373130626239393133323062396566393962666639663962
61313665643064333466333961386330306335336465623035376433323435383336373064323635
64366634653538623861336662613962306164666163656636623462373539613436303830333839
37633965613638393133663165313930663830336531376162393031313864333036386638303130
36343534366537303264356534343466656365363732383630306131663963333432643230626337
3233
[root@harbor ansible]# ansible-playbook playbook.yml 
ERROR! Attempting to decrypt but no vault secrets found
[root@harbor ansible]# ansible-playbook playbook.yml --ask-vault-pass 
Vault password: 

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [hello] **************************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[root@harbor ansible]# ansible-vault view playbook.yml  # 通过view命令查看加密的内容
Vault password: 
- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: hello
      command: hostname
[root@harbor ansible]# ansible-vault edit playbook.yml  # 可以通过输入密码对playbook内容进行编辑
Vault password: 
[root@harbor ansible]# cat playbook.yml 
$ANSIBLE_VAULT;1.1;AES256
62366634303831363762303137626134353532326437336466373833376161396561316364333234
3265623562336365316333346337636164616462336432310a386235383130633132623538343562
38363339373566356165623638633239383334616131336164386539383135373539363439303036
3966393064366663620a363037393666303235376339653661636433653430326532613131346164
31656137353434313237633930336331643566383534633830363766366333636338316363316438
30353364323263646533666136373236396665623139646163356564396237656164353834653134
65633066356363326661616131663164343933323934656335636462636662346261663737343663
64366230356131353936383432363238346537343935633630393965613461326161363637643039
3766
[root@harbor ansible]# ansible-vault decrypt playbook.yml       # 解密
Vault password: 
Decryption successful
[root@harbor ansible]# cat playbook.yml 
- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: hello
      command: hostname

YAML语言写法

List

List: 列表,其所有元素均使用"-" 打头

示例:

# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango

Dictionary

Dictionary: 字典,通常由多个key与value构成

示例

# An employee record
name: Example Developer
job: Developer
skill: Elite

也可以将key:value放置于{}中进行表示, 用","分隔多个key:value

示例

# An employee record
{name: Example Developer, job: Developer, skill: Elite}

YAML陷阱

YAML语法要求如果值以{{ foo }}开头的话我们需要将整行用双引号包起来.这是为了确认你不是想声明一个YAML字典.该知识点在 YAML 语法 页面有所讲述.

这样是不行的:

- hosts: app_servers
  vars:
      app_path: {{ base_path }}/22

你应该这么做:

- hosts: app_servers
  vars:
       app_path: "{{ base_path }}/22"

一些样例

[root@harbor ansible]# cat test.yml 
---
- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: test createfile
      file: name=/root/newfile state=touch
    - name: test connection
      ping:
    - name: test createuser
      user: name=test1 shell=/sbin/nologin system=yes home=/home/test1 groups=root,bin uid=666 comment="account for test"
    - name: install yum htop
      yum: name=htop,nload
    - name: test copyfile
      copy: src=/root/111 dest=/root

模拟测试(dry run)

使用-C参数进行dry run

[root@harbor ansible]# ansible-playbook test.yml -C

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [test createfile] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [test connection] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [test createuser] ****************************************************************************************************************************
changed: [k8s-node03]

TASK [install yum htop] ***************************************************************************************************************************
changed: [k8s-node03]

TASK [test copyfile] ******************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=6    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

模拟测试通过后就实际运行一下

[root@harbor ansible]# ansible-playbook test.yml

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [test createfile] ****************************************************************************************************************************
changed: [k8s-node03]

TASK [test connection] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [test createuser] ****************************************************************************************************************************
changed: [k8s-node03]

TASK [install yum htop] ***************************************************************************************************************************
changed: [k8s-node03]

TASK [test copyfile] ******************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=6    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

检测是否执行成功

[root@k8s-node03 ~]# ls
111  111.9184.2020-02-21@12:04:56~  333  anaconda-ks.cfg  kubernetes.conf  newfile
[root@k8s-node03 ~]# getent passwd test1
test1:x:666:666:account for test:/home/test1:/sbin/nologin
[root@k8s-node03 ~]# htop --version
htop 2.2.0 - (C) 2004-2019 Hisham Muhammad
Released under the GNU GPL.

执行脚本时忽略错误的方法

1.如果命令或脚本的退出码不为0,可以使用如下方案替代

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || bin/true

2.或者使用ignore_errors来忽略错误信息:

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

查看待执行的主机列表

添加--list-hosts参数

[root@harbor ansible]# ansible-playbook test.yml  --list-hosts

playbook: test.yml

  play #1 (k8s-node03): k8s-node03      TAGS: []
    pattern: [u'k8s-node03']
    hosts (1):
      k8s-node03

查看playbook的任务列表

[root@harbor ansible]# ansible-playbook test.yml  --list-tasks 

playbook: test.yml

  play #1 (k8s-node03): k8s-node03      TAGS: []
    tasks:
      test createfile   TAGS: []
      test connection   TAGS: []
      test createuser   TAGS: []
      install yum htop  TAGS: []
      test copyfile     TAGS: []

针对特定主机执行

执行时添加--limit参数

[root@harbor ansible]# ansible-playbook test.yml --limit k8s-node03

Handlers: 在发生改变时执行的操作

由于module 具有”幂等”性,所以当远端系统被人改动时,可以重放 playbooks 达到恢复的目的. playbooks 本身可以识别这种改动,并且有一个基本的 event system(事件系统),可以响应这种改动.

(当发生改动时)’notify’ actions 会在 playbook 的每一个 task 结束时被触发,而且即使有多个不同的 task 通知改动的发生, ‘notify’ actions 只会被触发一次.

举例来说,比如多个 resources 指出因为一个配置文件被改动,所以 apache 需要重新启动,但是重新启动的操作只会被执行一次.

这里有一个例子,当一个文件的内容被改动时,重启两个 services:

- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
     - restart memcached
     - restart apache

‘notify’ 下列出的即是 handlers.

Handlers 也是一些 task 的列表,通过名字来引用,它们和一般的 task 并没有什么区别.Handlers 是由通知者进行 notify, 如果没有被 notify,handlers 不会执行.不管有多少个通知者进行了 notify,等到 play 中的所有 task 执行完成之后,handlers 也只会被执行一次.

这里是一个 handlers 的示例:

handlers:
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted

Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了.

tags

可以在创建task的时候为其指定标签,以方便在执行playbook的时候选择指定标签的任务去执行

执行方法:ansible-playbook -t yourtags1,yourtags2 yourplaybook.yml

[root@harbor ansible]# vim playbook.yml 
[root@harbor ansible]# cat playbook.yml 
- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: stop ntpd
      service: name=ntpd state=stopped
      tags: stop_ntpd
    - name: restart ntpd
      service: name=ntpd state=restarted
      tags: restart_ntpd 
[root@harbor ansible]# ansible-playbook --list-tags playbook.yml    # 查看标签

playbook: playbook.yml

  play #1 (k8s-node03): k8s-node03      TAGS: []
      TASK TAGS: [restart_ntpd, stop_ntpd]
[root@harbor ansible]# ansible-playbook -t stop_ntpd playbook.yml   # 这里我们只执行停止任务的标签

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [stop ntpd] **********************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[root@harbor ansible]# ansible k8s-node03 -a 'systemctl status ntpd'
k8s-node03 | FAILED | rc=3 >>
● ntpd.service - Network Time Service
   Loaded: loaded (/usr/lib/systemd/system/ntpd.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since Tue 2020-02-25 10:16:20 CST; 57s ago
  Process: 998 ExecStart=/usr/sbin/ntpd -u ntp:ntp $OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 1014 (code=exited, status=0/SUCCESS)

Feb 25 10:11:34 k8s-node03 ntpd[1014]: Listen and drop on 1 v6wildcard :: UDP 123
Feb 25 10:11:34 k8s-node03 ntpd[1014]: Listen normally on 2 lo 127.0.0.1 UDP 123
Feb 25 10:11:34 k8s-node03 ntpd[1014]: Listening on routing socket on fd #19 for interface updates
Feb 25 10:11:34 k8s-node03 ntpd[1014]: 0.0.0.0 c016 06 restart
Feb 25 10:11:34 k8s-node03 ntpd[1014]: 0.0.0.0 c012 02 freq_set kernel 6.765 PPM
Feb 25 10:11:37 k8s-node03 ntpd[1014]: Listen normally on 3 ens33 192.168.1.62 UDP 123
Feb 25 10:11:37 k8s-node03 ntpd[1014]: Listen normally on 4 docker0 172.17.0.1 UDP 123
Feb 25 10:11:37 k8s-node03 ntpd[1014]: new interface(s) found: waking up resolver
Feb 25 10:16:20 k8s-node03 systemd[1]: Stopping Network Time Service...     # 只执行了停止任务
Feb 25 10:16:20 k8s-node03 systemd[1]: Stopped Network Time Service.non-zero return code

Playbook使用变量

变量名:仅能由字母、数字和下划线组成,且只能以字母开头

变量来源:

​ ansible setup facts 远程主机的所有变量都可以直接调用

查看变量
[root@harbor ~]# ansible k8s-node03 -m setup -a 'filter=ansible_hostname'       # 这里的过滤条件支持通配符
k8s-node03 | SUCCESS => {
    "ansible_facts": {
        "ansible_hostname": "k8s-node03", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}

由于支持通配符,也可以写成

[root@harbor ~]# ansible k8s-node03 -m setup -a 'filter=*hostname*'
k8s-node03 | SUCCESS => {
    "ansible_facts": {
        "ansible_hostname": "k8s-node03", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
变量的优先级:

ansible-playbook -e "key=value"

Playbook 文件里面定义的变量

hosts文件里面定义的单个主机变量

hosts文件里面定义的group变量

调用系统默认变量

[root@harbor ~]# ansible k8s-node03 -m setup -a 'filter=ansible_ens33'  # 先查询要获取的变量
k8s-node03 | SUCCESS => {
    "ansible_facts": {
        "ansible_ens33": {
            "active": true, 
            "device": "ens33", 
            "features": {
                "busy_poll": "off [fixed]", 
                "fcoe_mtu": "off [fixed]", 
                "generic_receive_offload": "on", 
                "generic_segmentation_offload": "on", 
                "highdma": "off [fixed]", 
                "l2_fwd_offload": "off [fixed]", 
                "large_receive_offload": "off [fixed]", 
                "loopback": "off [fixed]", 
                "netns_local": "off [fixed]", 
                "ntuple_filters": "off [fixed]", 
                "receive_hashing": "off [fixed]", 
                "rx_all": "off", 
                "rx_checksumming": "off", 
                "rx_fcs": "off", 
                "rx_vlan_filter": "on [fixed]", 
                "rx_vlan_offload": "on", 
                "rx_vlan_stag_filter": "off [fixed]", 
                "rx_vlan_stag_hw_parse": "off [fixed]", 
                "scatter_gather": "on", 
                "tcp_segmentation_offload": "on", 
                "tx_checksum_fcoe_crc": "off [fixed]", 
                "tx_checksum_ip_generic": "on", 
                "tx_checksum_ipv4": "off [fixed]", 
                "tx_checksum_ipv6": "off [fixed]", 
                "tx_checksum_sctp": "off [fixed]", 
                "tx_checksumming": "on", 
                "tx_fcoe_segmentation": "off [fixed]", 
                "tx_gre_segmentation": "off [fixed]", 
                "tx_gso_robust": "off [fixed]", 
                "tx_ipip_segmentation": "off [fixed]", 
                "tx_lockless": "off [fixed]", 
                "tx_nocache_copy": "off", 
                "tx_scatter_gather": "on", 
                "tx_scatter_gather_fraglist": "off [fixed]", 
                "tx_sit_segmentation": "off [fixed]", 
                "tx_tcp6_segmentation": "off [fixed]", 
                "tx_tcp_ecn_segmentation": "off [fixed]", 
                "tx_tcp_segmentation": "on", 
                "tx_udp_tnl_segmentation": "off [fixed]", 
                "tx_vlan_offload": "on [fixed]", 
                "tx_vlan_stag_hw_insert": "off [fixed]", 
                "udp_fragmentation_offload": "off [fixed]", 
                "vlan_challenged": "off [fixed]"
            }, 
            "hw_timestamp_filters": [], 
            "ipv4": {
                "address": "192.168.1.62", 
                "broadcast": "192.168.1.255", 
                "netmask": "255.255.255.0", 
                "network": "192.168.1.0"
            }, 
            "macaddress": "00:0c:29:73:7f:5c", 
            "module": "e1000", 
            "mtu": 1500, 
            "pciid": "0000:02:01.0", 
            "promisc": false, 
            "speed": 1000, 
            "timestamping": [
                "tx_software", 
                "rx_software", 
                "software"
            ], 
            "type": "ether"
        }, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
[root@harbor ansible]# vim playbook2.yml 
[root@harbor ansible]# cat playbook2.yml 
- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: get ip
      shell: echo {{ ansible_ens33.ipv4.address }} > /root/321      # 使用变量
[root@harbor ansible]# ansible-playbook playbook2.yml 

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [get ip] *************************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@harbor ansible]# ansible k8s-node03 -a 'cat /root/321'
k8s-node03 | CHANGED | rc=0 >>
192.168.1.62

示例里面playbook里的变量可以有两种写法,效果都是一样的:

shell: echo {{ ansible_ens33.ipv4.address }} > /root/321
shell: echo {{ ansible_ens33["ipv4"]["address"] }} > /root/321

在hosts中定义变量

hosts文件路径默认为/etc/ansible/hosts

普通变量:

在主机组中主机单独定义,优先级高于公共变量

[root@harbor ansible]# vim /etc/ansible/hosts   # 对指定对象添加变量
[k8s_node]
k8s-node[01:03] package=ntpd

编写playbook并执行

[root@harbor ansible]# vim playbook3.yml 
[root@harbor ansible]# cat playbook3.yml 
- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: stop service
      service: name={{ package }} status=stopped
[root@harbor ansible]# ansible-playbook playbook3.yml 

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [stop service] *******************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
公共(组)变量:

针对主机组中所有主机定义统一变量

[root@harbor ansible]# vim /etc/ansible/hosts   # 对指定组添加变量
[k8s_node]
k8s-node[01:03] 

[k8s_node:vars]     # 添加[group:vars]来配置组变量
package=ntpd

执行

[root@harbor ansible]# vim playbook3.yml 
[root@harbor ansible]# cat playbook3.yml 
- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: stop service
      service: name={{ package }} state=stopped
[root@harbor ansible]# ansible-playbook playbook3.yml 

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [stop service] *******************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

通过命令行指定变量,优先级最高

Ansible-playbook -e varname=value

- hosts: k8s-node03
  remote_user: root

  tasks:
    - name: stop ntpd
      service: name={{package}} state=stopped
    - name: start ntpd
      service: name={{package}} state=started

执行:

[root@harbor ansible]# ansible-playbook -e 'package=ntpd' playbook.yml 

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [stop ntpd] **********************************************************************************************************************************
changed: [k8s-node03]

TASK [start ntpd] *********************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@harbor ansible]# ansible k8s-node03 -a 'systemctl status ntpd'
k8s-node03 | CHANGED | rc=0 >>
● ntpd.service - Network Time Service
   Loaded: loaded (/usr/lib/systemd/system/ntpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2020-02-25 11:04:30 CST; 7s ago
  Process: 68118 ExecStart=/usr/sbin/ntpd -u ntp:ntp $OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 68120 (ntpd)
    Tasks: 1
   Memory: 580.0K
   CGroup: /system.slice/ntpd.service
           └─68120 /usr/sbin/ntpd -u ntp:ntp -g

Feb 25 11:04:30 k8s-node03 ntpd[68120]: 0.0.0.0 c01d 0d kern kernel time sync enabled
Feb 25 11:04:30 k8s-node03 ntpd[68120]: ntp_io: estimated max descriptors: 1024, initial socket boundary: 16
Feb 25 11:04:30 k8s-node03 ntpd[68120]: Listen and drop on 0 v4wildcard 0.0.0.0 UDP 123
Feb 25 11:04:30 k8s-node03 ntpd[68120]: Listen and drop on 1 v6wildcard :: UDP 123
Feb 25 11:04:30 k8s-node03 ntpd[68120]: Listen normally on 2 lo 127.0.0.1 UDP 123
Feb 25 11:04:30 k8s-node03 ntpd[68120]: Listen normally on 3 ens33 192.168.1.62 UDP 123
Feb 25 11:04:30 k8s-node03 ntpd[68120]: Listen normally on 4 docker0 172.17.0.1 UDP 123
Feb 25 11:04:30 k8s-node03 ntpd[68120]: Listening on routing socket on fd #21 for interface updates
Feb 25 11:04:30 k8s-node03 ntpd[68120]: 0.0.0.0 c016 06 restart
Feb 25 11:04:30 k8s-node03 ntpd[68120]: 0.0.0.0 c012 02 freq_set kernel 6.765 PPM

如果有多个变量:

ansible-playbook -e 'key1=value1 key2=value2' yourplaybook.yml

在playbook中定义

- hosts: k8s-node03
  remote_user: root

  vars:
    - package: ntpd

  tasks:
    - name: stop ntpd
      service: name={{package}} state=stopped
    - name: start ntpd
      service: name={{package}} state=started

执行:

[root@harbor ansible]# ansible-playbook playbook.yml 

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [stop ntpd] **********************************************************************************************************************************
changed: [k8s-node03]

TASK [start ntpd] *********************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

自动写/etc/hosts:

需要先在/etc/ansible/hosts中定义对应的hostname变量

[fastdfs]
192.168.1.31 hostname=tracker_group1
192.168.1.32 hostname=tracker_group2
192.168.1.33 hostname=storage_group1_1
192.168.1.34 hostname=storage_group1_2
192.168.1.35 hostname=storage_group2_1
192.168.1.36 hostname=storage_group2_2
    - name: mod hosts
      tags:
        - test1 
      lineinfile:
        dest: /etc/hosts
        regexp: '.*{{ item }}$'
        line: "{{item}} {{ hostvars[item].hostname }}"
        state: present
      when: hostvars[item].hostname is defined
      with_items: "{{ groups.fastdfs }}"

YAML文件定义变量

区别于playbook中定义,我们可以将变量全部放到一个yml文件里来调用

[root@harbor ansible]# vim /etc/ansible/vars.yml
[root@harbor ansible]# cat /etc/ansible/vars.yml
package: ntpd
[root@harbor ansible]# vim playbook3.yml
[root@harbor ansible]# cat playbook3.yml 
- hosts: k8s-node03
  remote_user: root
  vars_files:       # 指定变量文件的路径
    - /etc/ansible/vars.yml

  tasks:
    - name: stop service
      service: name={{ package }} state=stopped

执行

[root@harbor ansible]# ansible-playbook playbook3.yml 

PLAY [k8s-node03] *********************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************
ok: [k8s-node03]

TASK [stop service] *******************************************************************************************************************************
changed: [k8s-node03]

PLAY RECAP ****************************************************************************************************************************************
k8s-node03                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

在role中定义

Template模板

文本文件,嵌套有脚本(使用模板变成语言编写)

jinja2语言,使用字面量,有下面形式:

​ 字符串:使用单引号或双引号

​ 数字:整数,浮点数

​ 列表:[item1, item2, ...]

​ 元祖:(item1, item2, ...)

​ 字典:{key1:vlaue1, key2:value2, ...}

​ 布尔型:true/false

算术运算:+, -, *, /, //, %, **

比较操作:==, !=, >, >=, <, <=

逻辑运算:and, or, not

流表达式:For If When

基础写法

修改文件nginx.com.j2下面的行

worker_processes {{ ansible_processor_vcpus }};

创建playbook文件:

cat temnginx2.yml

---
- hosts: websrvs
  remote_usr: root
  
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
ansible-playbook temnginx2.yml

when 判断

条件测试:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,通过when语句实现,在task中使用,jinja2的语法格式

when语句:

在task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法

示例:

tasks:
  - name: "shutdown RedHat flavored systems"
    command: /sbin/shutdown -h now
    when: ansible_os_family == "RedHat"

Playbook常用模块使用

更换centos7系统源为阿里源

这个剧本执行前需要准备两个repo文件

    - name: change repo
      template: src=CentOS-Base.repo dest=/etc/yum.repos.d/CentOS-Base.repo
      
    - name: install epel release
      yum: 
        name: epel-release

    - name: change repo
      template: src=epel-7.repo dest=/etc/yum.repos.d/epel-7.repo
      notify:
        - make cache

  handlers:
    - name: make cache
      shell:
        cmd: yum clean all && yum makecache

文件1:CentOS-Base.repo:

# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the 
# remarked out baseurl= line instead.
#
#
 
[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/os/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#released updates 
[updates]
name=CentOS-$releasever - Updates - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/updates/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/updates/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/extras/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/centosplus/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/centosplus/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/contrib/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/contrib/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

文件2:epel-7.repo

[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=http://mirrors.aliyun.com/epel/7/$basearch
failovermethod=priority
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
 
[epel-debuginfo]
name=Extra Packages for Enterprise Linux 7 - $basearch - Debug
baseurl=http://mirrors.aliyun.com/epel/7/$basearch/debug
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
gpgcheck=0
 
[epel-source]
name=Extra Packages for Enterprise Linux 7 - $basearch - Source
baseurl=http://mirrors.aliyun.com/epel/7/SRPMS
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
gpgcheck=0

Yum安装常用软件(yum)

    - name: install necessary tools
      tags:
        - yum
      yum: 
        name: unzip,conntrack,ntpdate,ntp,ipvsadm,ipset,jq,iptables,curl,sysstat,libseccomp,wget,vim,net-tools,git,nfs-utils,rpcbind,iptables-services,nload,htop,telnet,nmap,openssl

需要编译包的时候:

    - name: install necessary tools
      tags:
        - yum
      yum: 
        name: make,cmake,gcc,gcc-c++

更改时区(timezone)

    - name: Set timezone to Asia/Shanghai
      timezone:
        name: Asia/Shanghai

设置主机名(hostname)

需要在hosts文件里指定相应的hostname参数

    - name: set hostname
      hostname:
        name: "{{ hostname }}"

ansible的host文件指定参数示例:

[rocketmq]
192.168.1.81 hostname=rocketmq01
192.168.1.82 hostname=rocketmq02
192.168.1.83 hostname=rocketmq03
192.168.1.84 hostname=rocketmq04

主机组互相添加host信息(lineinfile)

同上一条,需要在ansible的host文件内指定hostname参数

    - name: mod hosts
      lineinfile:
        dest: /etc/hosts
        regexp: '.*{{ item }}$'
        line: "{{item}} {{ hostvars[item].hostname }}"
        state: present
      when: hostvars[item].hostname is defined
      with_items: "{{ groups.rocketmq }}"       # 注意修改组名

注意最后一行的变量里面需要修改为主机组名,在此时示例中组名为rocketmq

ansible的host文件指定参数示例:

[rocketmq]
192.168.1.81 hostname=rocketmq01
192.168.1.82 hostname=rocketmq02
192.168.1.83 hostname=rocketmq03
192.168.1.84 hostname=rocketmq04

获取本机ip变量

实际使用的时候需要测试一下是否正常获取

    mysqlip: "{{ansible_default_ipv4.address}}"

service相关操作(service)

指定相关进程的状态,以及是否开机自动启动

state可以指定的状态有reloaded, restarted, started, stopped

    - name: Disable unnecessary services
      service:
        name: "{{ item }}"
        state: stopped
        enabled: false
      with_items:
        - firewalld
        - postfix

关闭SELinux(selinux)

    - name: Disable SELinux tempoary
      selinux:
        state: disabled

关闭swap

    - name: disable swap
      lineinfile: 
        path: /etc/fstab
        regexp: swap
        state: absent

设置limits(lineinfile)

    - name: setting
      lineinfile:
        path: /etc/security/limits.conf
        line: "{{ item }}"
      with_items:
        - '* soft nofile 65535'
        - '* hard nofile 65535'
        - '* soft nproc 65535'
        - '* hard nproc 65535'
      notify:
        - ulimit
  handlers:
    - name: ulimit
      shell: ulimit -n

启用iptables并清理策略(service)

    - name: set iptables
      service:
        name: iptables
        state: started
        enabled: true
      notify:
        - clean iptables
  handlers:
    - name: clean iptables
      shell:
        cmd: iptables -F && service iptables save

ntp设置

需要指定一个ntp server变量,准备一个ntp.conf的template

- hosts: k8s
  vars:
    ntp_server: 192.168.1.1
  gather_facts: yes
  tasks:
    - name: set ntp
      tags:
        - ntp
      template: src=ntp.conf dest=/etc/ntp.conf

    - name: sync time
      tags:
        - ntp
      shell: ntpdate {{ ntp_server }} &&  hwclock -w 

    - name: start ntp
      tags:
        - ntp
      service:
        name: ntpd
        state: restarted
        enabled: true

ntp.conf

server {{ ntp_server }}

#在配置中增加以下配置:

#允许上层时间服务器主动修改本机时间
restrict {{ ntp_server }} nomodify notrap noquery


#外部时间服务器不可用时,以本地时间作为时间服务
server 127.0.0.1
fudge 127.0.0.1 stratum 10

创建group,user(group)(user)

    - name: create mysql group
      group:
        name: mysql
        state: present
          
    - name: create mysql user
      user:
        name: mysql
        group: mysql
        shell: /sbin/nologin
        home: /home/mysql
        state: present

创建文件夹(file)

Owner,group不写默认root

recurse:true允许递归创建

        
    - name: Create data directory 
      file:
        path: "{{ item }}"
        state: directory
        owner: mysql
        group: mysql
        recurse: true
      with_items:
        -  "{{data}}"
        -  "{{data}}/logs"
        -  "{{data}}/tmp"
        -  "{{data}}/undolog"
        -  /usr/local/mysql

拷贝文件(copy)

remote_src为yes的时候src和dest都在远程主机上

backup参数表示如果源文件存在将会备份源文件,可选参数

    - name: Copy the files
      copy:
        src: /etc/my.cnf
        dest: /etc/my.cnf.bak
        remote_src: yes
        backup: yes
      ignore_errors: yes

解压包(unarchive)

src这里没有特殊参数指定,会从ansible端的相关目录拉取压缩包

dest表示需要解压的目标目录

creates参数表示如果文件夹存在就不会重复进行解压操作

    - name: unarchive packages
      tags:
        - unzip
      unarchive:
        src: "{{ item.name }}"
        dest: /usr/local
        creates: /usr/local/{{ item.unarchived_name }}
      with_items:
        - { name: 'fastdfs.V6.06.tar.gz', unarchived_name: 'fastdfs-6.06' }
        - { name: 'libfastcommon.V1.0.43.tar.gz', unarchived_name: 'libfastcommon-1.0.43' }
        - { name: 'nginx-1.16.1.tar.gz', unarchived_name: 'nginx-1.16.1' }
        - { name: 'fastdfs-nginx-module.tar.gz', unarchived_name: 'fastdfs-nginx-module' }
        - { name: 'ngx_cache_purge-2.3.tar.gz', unarchived_name: 'ngx_cache_purge-2.3' }

执行shell命令(shell)

chdir: 表示切换到指定目录下再执行相应命令

cmd:命令主体

creates: 如果文件或文件夹存在,则不执行该命令

    - name: make libfastcommon
      tags:
        - make
      shell: 
        chdir: /usr/local/{{ libfastcommon }}   # 这个变量于演示无关
        cmd: ./make.sh && ./make.sh install
        creates: /usr/lib64/libfastcommon.so

做软链(file)

src: 源文件

dest: 软链地址

    - name: ln
      tags:
        - ln
      file:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
        state: link
      with_items:
        - { src: '/usr/lib64/libfastcommon.so', dest: '/usr/local/lib/libfastcommon.so' }
        - { src: '/usr/lib64/libfastcommon.so', dest: '/usr/lib/libfastcommon.so' }
        - { src: '/usr/lib64/libfdfsclient.so', dest: '/usr/local/lib/libfdfsclient.so' }

套用模板(template)

src: 模板文件,需要自己准备,同时模板内的变量需要自己定义好

dest:目标路径

notify,handlers:可选项,有时候需要在修改完配置文件后重启相关服务

    - name: config tracker
      tags:
        - install
      template:
        src: fdfs/tracker.conf.j2
        dest: /etc/fdfs/tracker.conf
      notify:
        - restart tracker
  handlers:        
    - name: restart tracker
      shell: /etc/init.d/fdfs_trackerd restart

another example

- hosts: mongo_config_servers
  gather_facts: yes
  vars:
    - based_dir: "/mongodb/sharded_cluster"
  tasks:
    - name: create config file for config_server and shard_server
      tags:
        - key
      template: src=mongod.conf.normal.j2 dest=/etc/mongod_{{ item.server_port }}.conf
      with_items:
        - { server_port: '20000', server_name: 'configs', cluster_role: 'configsvr' }
        - { server_port: '20001', server_name: 'shard1', cluster_role: 'shardsvr' }
        - { server_port: '20002', server_name: 'shard2', cluster_role: 'shardsvr' }
        - { server_port: '20003', server_name: 'shard3', cluster_role: 'shardsvr' }

角色条件判断(when)

when:

当待执行主机满足某个条件时才执行某些操作

    - name: set master
      tags:
        - master
      template:
        src: master.sh
        dest: /tmp/master.sh
        mode: u+x
      notify: apply master
      when: role == "master"

    - name: set slave
      tags:
        - slave
      template:
        src: slave.sh
        dest: /tmp/slave.sh
        mode: u+x
      notify: apply slave
      when: role == "slave"

这里贴上ansible的hosts文件:

[mysql]
192.168.0.71 hostname=master01 serverid=13306 role=master
192.168.0.72 hostname=slave01 serverid=23306 role=slave
192.168.0.73 hostname=slave02 serverid=33306 role=slave

在指定文件中加入一段文本(blockinfile)

create:如果没有就创建

    - name: create mongodb repo file
      tags:
        - test1
      blockinfile:
        path: /etc/yum.repos.d/mongodb-org-4.2.repo
        create: True
        block: |
          [mongodb-org-4.2]
          name=MongoDB Repository
          baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.2/x86_64/
          gpgcheck=1
          enabled=1
          gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc

修改文本(lineinfile)

示例中前两个是正则匹配替换,第三个表示确保文件中存在这一行

    - name: set ntp restrict
      tags:
        - ntp
      lineinfile:
        dest: /etc/ntp.conf
        regexp: '^restrict 192\.[0-9]{1,3}\.255\.1'
        line: restrict 192.168.1.1
      notify:
        - restart ntpd
    - name: set ntp server
      tags:
        - ntp
      lineinfile:
        dest: /etc/ntp.conf
        regexp: '^server 192\.[0-9]{1,3}\.255\.1 iburst minpoll 3 maxpoll 4 prefer'
        line: 'server 192.168.1.1 iburst minpoll 3 maxpoll 4 prefer'
      notify:
        - restart ntpd
             
    - name: disable auto update for mongodb
      lineinfile:
        path: /etc/yum.conf
        line: 'exclude=mongodb-org,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools'  

another example:

    - name: mod service
      tags:
        - test6 
      lineinfile: 
        path: /usr/lib/systemd/system/mongod_{{ server_port }}.service
        regexp: '^ExecStart=/usr/bin/m'
        line: 'ExecStart=/usr/bin/mongos $OPTIONS'
      with_items:
        - { server_port: '27017' }

替换文本(replace)

- name: change log dir
  tags:
    - log
  replace:
    path: "{{ item }}"
    regexp: '\${user.home}'     # 这里$需要打转义符
    replace: '/data/rocketmq'
  with_items:
    - /usr/local/rocketmq/conf/logback_broker.xml
    - /usr/local/rocketmq/conf/logback_namesrv.xml
    - /usr/local/rocketmq/conf/logback_tools.xml
    - /usr/local/rocketmq/conf/plain_acl.yml
    - /usr/local/rocketmq/conf/tools.yml

重启(reboot)

    - name: Reboot all nodes make sure all changes effected
      reboot:
        reboot_timeout: 3600
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,376评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,126评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,966评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,432评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,519评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,792评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,933评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,701评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,143评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,488评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,626评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,292评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,896评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,494评论 2 348