ansible 环境准备

ansible 架构

  • 控制节点:下发指令或文件到受控制节点。
  • 受控制节点:接受控制节点发过来的指令,并执行。

ansible 工作原理

ansible 控制节点通过ssh协议将python 模块推送到受控制节点受控制节点使用python执行python模块进行相应的配置。

ansible 环境准备

实验环境

10.1.8.10 controller.sjz.cloud controller
10.1.8.11 server1.sjz.cloud server1
10.1.8.12 server2.sjz.cloud server2
10.1.8.13 server3.sjz.cloud server3
10.1.8.14 server4.sjz.cloud server4

准备虚拟机模版

准备1台干净的centos 7 虚拟机。

注意:模版虚拟机的CPU和内存的配置,建议设置为1CPU和2G内存。

开发脚本sethost:

  • 不加参数执行sethost,则提示命令使用方法。
  • 加参数执行sethost,则第一个参数范围是10-14。超出范围也提示命令使用方法。
  • 正常执行示例:sethost 10,这设置正确的主机名和IP地址。
[root@centos ~ 13:34:31]# vim /usr/local/bin/sethost
#!/bin/bash

# test root user
(( UID!=0 )) && echo 'Please run as root.' && exit 1

usage="Usage: $0 10-14"

# test args number
(($# !=1 )) && echo $usage && exit 2

# 根据实际情况修改网卡名和域名
con_name=ens33
domain_name=sjz.cloud

host_id=$1

if ((host_id==10));then
  HOSTNAME=controller.${domain_name}
elif ((11<=host_id && host_id<=14)) ;then
  HOSTNAME=server$[host_id-10].${domain_name}
else
  echo $usage
  exit 3
fi

hostnamectl set-hostname $HOSTNAME
nmcli connection modify ${con_name} ipv4.addresses 10.1.8.${host_id}/24
nmcli connection up ${con_name}

hostname
ip -br address
[root@centos ~ 13:34:31]# chmod +x /usr/local/bin/sethost

关机打快照,快照名为ansible。

克隆虚拟机

基于模版虚拟机快照ansible,克隆出其他虚拟机,并使用sethost脚本设置主机名和IP地址。

以server1为例:

[root@centos ~ 13:34:31]# sethost 11

配置 ansible 基础环境

在模版虚拟机上配置/etc/hosts,添加ansible主机清单

[root@deploy ~ 14:51:11]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

################# ansible ####################
10.1.8.10 controller.sjz.cloud controller
10.1.8.11 server1.sjz.cloud server1
10.1.8.12 server2.sjz.cloud server2
10.1.8.13 server3.sjz.cloud server3
10.1.8.14 server4.sjz.cloud server4
################# ansible ####################

配置免密登录ansible节点:

[root@deploy ~ 14:52:58]# ssh-keygen -t rsa -N "" -f .ssh/id_rsa

[root@deploy ~ 14:54:39]# \
for host in controller server1 server2 server3 server4
do
  sshpass -p123 ssh-copy-id root@$host
done

[root@deploy ~ 14:56:02]# 
for host in controller server1 server2 server3 server4
do
  ssh root@$host 'hostname;ip -br a show ens33;echo'
done
# 输出内容如下:
controller.sjz.cloud
ens33            UP             10.1.8.10/24 fe80::20c:29ff:fe14:2f8b/64 

server1.sjz.cloud
ens33            UP             10.1.8.11/24 fe80::20c:29ff:fe6a:559b/64 

server2.sjz.cloud
ens33            UP             10.1.8.12/24 fe80::20c:29ff:feec:ac41/64 

server3.sjz.cloud
ens33            UP             10.1.8.13/24 fe80::20c:29ff:fe19:59c1/64 

server4.sjz.cloud
ens33            UP             10.1.8.14/24 fe80::20c:29ff:feaa:4763/64 

在模版虚拟机上开发脚本weihu,用来集中管理其他机器。

  • weihu cmd command,将会在ansible 5台设备上执行command。
  • weihu copy src dest,将模版虚拟机上的src文件复制到ansible 5台设备dest位置。
[root@deploy ~ 14:49:42]# vim /usr/local/bin/weihu
#!/bin/bash

function usage () {
  echo "Usage: weihu cmd COMMAND, 在集群中所有的机器上执行对应COMMAND命令"
  echo "Usage: weihu copy source target,将本地source文件,推送到集群中所有的机器上"
  exit
}

action=$1

HOSTLIST='controller server1 server2 server3 server4'

(( $#<=1 )) && usage

case "$action" in
  "cmd")
    # 删除参数1
    shift
    COMMAND="$*"
    for host in $HOSTLIST
    do 
      ssh root@$host "$COMMAND"
    done
    ;;
  "copy")
    # 删除参数1
    shift
    for host in $HOSTLIST
    do 
      num=$#
      case $num in
        2)
          scp -r $1 root@$host:$2
          ;;
        #[3-9]|[1-9][0-9])
        [3-9])
      last=$(echo $* | awk '{print $NF}')
          args_exclude_last=$(echo $* | sed "s#$last##")
          scp -r ${args_exclude_last} root@$host:${last}
          ;;
        *)
          usage
      esac
    done
    ;;
  *)
    usage
    ;;
esac
[root@deploy ~ 14:50:49]# chmod +x /usr/local/bin/weihu

测试维护脚本

root@deploy ~ 14:56:09]# weihu cmd hostname
controller.sjz.cloud
server1.sjz.cloud
server2.sjz.cloud
server3.sjz.cloud
server4.sjz.cloud

[root@deploy ~ 14:56:47]# weihu copy /etc/hosts /etc/hosts
hosts                                                    100%  449   222.1KB/s   00:00    
hosts                                                    100%  449   245.5KB/s   00:00    
hosts                                                    100%  449   275.8KB/s   00:00    
hosts                                                    100%  449   351.0KB/s   00:00    
hosts                                                    100%  449   317.4KB/s   00:00

[root@deploy ~ 14:57:33]# weihu cmd cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

################# ansible ####################
10.1.8.10 controller.sjz.cloud controller
10.1.8.11 server1.sjz.cloud server1
10.1.8.12 server2.sjz.cloud server2
10.1.8.13 server3.sjz.cloud server3
10.1.8.14 server4.sjz.cloud server4
......

准备一个专用的账户devops,用于控制节点远程登录其他节点。

[root@deploy ~ 15:21:59]# weihu cmd useradd devops
[root@deploy ~ 15:36:17]# weihu cmd id devops
uid=1001(devops) gid=1001(devops) groups=1001(devops)
uid=1001(devops) gid=1001(devops) groups=1001(devops)
uid=1001(devops) gid=1001(devops) groups=1001(devops)
uid=1001(devops) gid=1001(devops) groups=1001(devops)
uid=1001(devops) gid=1001(devops) groups=1001(devops)

[root@deploy ~ 15:36:22]# weihu cmd 'echo 123 | passwd --stdin devops'
[root@deploy ~ 15:37:41]# sshpass -p 123 ssh devops@server1 id
uid=1001(devops) gid=1001(devops) groups=1001(devops)

# 配置devops账户,免密提权为root
[root@deploy ~ 15:39:17]# weihu cmd "echo 'devops ALL=(ALL)NOPASSWD: ALL' > /etc/sudoers.d/devops"

配置控制节点使用devops账户免密登录所有ansible节点。

[root@deploy ~ 15:47:55]# sshpass -p123 ssh devops@controller 'ssh-keygen -t rsa -N "" -f .ssh/id_rsa'
[root@deploy ~ 15:48:30]# sshpass -p123 ssh devops@controller 'for host in controller server1 server2 server3 server4;do sshpass -p123 ssh-copy-id devops@$host;done'

# 验证控制节点免密登录其他节点
[devops@controller ~ 15:50:01]$ for host in controller server1 server2 server3 server4;do ssh devops@$host id;done
uid=1001(devops) gid=1001(devops) groups=1001(devops)
uid=1001(devops) gid=1001(devops) groups=1001(devops)
uid=1001(devops) gid=1001(devops) groups=1001(devops)
uid=1001(devops) gid=1001(devops) groups=1001(devops)
uid=1001(devops) gid=1001(devops) groups=1001(devops)

[devops@controller ~ 15:50:12]$ for host in controller server1 server2 server3 server4;do ssh devops@$host sudo id;done
uid=0(root) gid=0(root) groups=0(root)
uid=0(root) gid=0(root) groups=0(root)
uid=0(root) gid=0(root) groups=0(root)
uid=0(root) gid=0(root) groups=0(root)
uid=0(root) gid=0(root) groups=0(root)

ansible 配置

部署 ansible软件

控制节点

[devops@controller ~ 16:31:42]$ sudo yum install -y ansible

受管理节点

[root@deploy ~ 16:36:44]# weihu cmd yum install -y python

配置主机清单

ansible管理的主机信息要保存到一个文件中,这个文件称之为主机清单(inventory)。

[devops@controller ~ 16:33:11]$ mkdir ansible
[devops@controller ~ 16:38:45]$ cd ansible/
[devops@controller ansible 16:38:47]$ vim inventory
controller
server1
server2
server3
server4

[devops@controller ansible 16:43:15]$ ansible -i inventory -m command -a 'id' server1
server1 | CHANGED | rc=0 >>
uid=1001(devops) gid=1001(devops) groups=1001(devops)
# 参数说明:
# -i inventory,主机清单位置
# -m command,使用命令模块
# -a 'hostname',模块对应的具体参数
# server1,针对哪个机器操作

[devops@controller ansible 16:43:41]$ ansible -i inventory -m command -a 'id' -b server1
server1 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)
# -b 提权为root操作

# 使用user模块管理用户
[devops@controller ansible 16:43:00]$ ansible -i inventory -m user -a 'name=zhangsan state=present' -b server1
server1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 1002, 
    "home": "/home/zhangsan", 
    "name": "zhangsan", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 1002
}
[devops@controller ansible 16:43:46]$ ansible -i inventory -m command -a 'id zhangsan' server1
server1 | CHANGED | rc=0 >>
uid=1002(zhangsan) gid=1002(zhangsan) groups=1002(zhangsan)

# 删除用户
[devops@controller ansible 16:44:33]$ ansible -i inventory -m user -a 'name=zhangsan state=absent remove=yes' -b server1
server1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "zhangsan", 
    "remove": true, 
    "state": "absent"
}
[devops@controller ansible 16:45:49]$ ansible -i inventory -m command -a 'id zhangsan' server1
server1 | FAILED | rc=1 >>
id: zhangsan: no such usernon-zero return code

分组主机清单

[devops@controller ansible 16:45:53]$ vim inventory 
[controllers]
controller

[webs]
server1
server2

[dbs]
server3
server4

测试

# 针对webs主机组操作
[devops@controller ansible 16:48:55]$ ansible -i inventory -m command -a 'hostname' -o webs
server2 | CHANGED | rc=0 | (stdout) server2.sjz.cloud
server1 | CHANGED | rc=0 | (stdout) server1.sjz.cloud
# -o 输出内容合并为一行

# all代表所有机器
[devops@controller ansible 16:49:03]$ ansible -i inventory -m command -a 'hostname' -o all
server2 | CHANGED | rc=0 | (stdout) server2.sjz.cloud
server1 | CHANGED | rc=0 | (stdout) server1.sjz.cloud
controller | CHANGED | rc=0 | (stdout) controller.sjz.cloud
server3 | CHANGED | rc=0 | (stdout) server3.sjz.cloud
server4 | CHANGED | rc=0 | (stdout) server4.sjz.cloud

# web主机组安装nginx
[devops@controller ansible 16:51:41]$ ansible -i inventory -m yum -a 'name=nginx state=present' -b webs

# web主机组卸载nginx
[devops@controller ansible 16:51:41]$ ansible -i inventory -m yum -a 'name=nginx state=absent' -b webs

查看模块帮助

# 查看模块清单,并过滤出yum相关信息
[devops@controller ansible 16:53:41]$ ansible-doc -l | grep yum
yum                                                           Manages packages with the `yum' package manager  
yum_repository                                                Add or remove YUM repositories  
# 查看yum模块帮助信息
[devops@controller ansible 16:53:47]$ ansible-doc yum
# 直接搜索EXAMPLE
# 部分内容如下:
EXAMPLES:

- name: install the latest version of Apache
  yum:
    name: httpd
    state: latest

- name: ensure a list of packages installed
  yum:
    name: "{{ packages }}"
  vars:
    packages:
    - httpd
    - httpd-tools

- name: remove the Apache package
  yum:
    name: httpd
    state: absent

- name: install the latest version of Apache from the testing repo
  yum:
    name: httpd
    enablerepo: testing
    state: present
...

ansible最大的特点:

  1. 简单:只要能看懂English就行。
  2. 幂等性:多次执行,结果一致。假设第一次执行软件包未安装,则执行安装。第二次执行,则不需要做任何事情。

playbook 编写和执行

通过编写playbook,完成重复、复杂的任务。

  • ansible 命令类似于 shell 中单个命令。
  • playbook 类似于 shell 脚本。
[devops@controller ansible 16:55:36]$ vim deploy_web.yaml
# yaml格式起始行,一般不省略
---

# Playbook中第一个play
# play具有属性:name,hosts,become,tasks,缩进一致
# name属性,用于简要描述play
- name: debploy WebSite

  # hosts属性,用于定义要在哪个受管理节点执行
  hosts: webs

  # tasks属性,用于描述play中任务,属性是列表格式
  tasks:

    # 第一个任务
    # 任务具有属性:涵name和模块名等。
    # name属性,用于简要描述任务
    - name: latest version of httpd and firewalld installed
      # 指明模块名,也就是要执行的任务
      yum:
        # 指定要操作的rpm包名称
        name:
          # rpm包名称是-开头的列表格式,或者逗号分隔的列表格式
          - httpd
          - firewalld

        # 定义软件包的状态,lastet代表升级为最新版本
        state: latest

    # 第二个任务
    - name: prepare index.html
      # copy 模块,用于将content属性值写入到目标文件
      copy:
        content: "Welcome to {{ ansible_fqdn }} WebSite!\n"
        dest: /var/www/html/index.html

    # 第三个任务
    - name: enable and start httpd
      # service模块,用于启用并启动httpd服务
      service:
        name: httpd
        enabled: true
        state: started

    # 第四个任务
    - name: enable and start firewalld
      # service模块,用于启用并启动firewalld服务
      service:
        name: firewalld
        enabled: true
        state: started

    # 第五个任务
    - name: firewalld permits access to httpd service
      # firewalld,用于放行http服务
      firewalld:
        service: http
        permanent: true
        state: enabled
        immediate: yes

# Playbook中第二个play,-开头表示列表
- name: Test WebSite
  hosts: localhost
  become: no
  tasks:
    - name: connect to intranet web server
      # uri模块,用于测试网站是否可以访问
      uri:
        url: http://{{item}}
      loop:
        - server1
        - server2

# yaml格式结束行,一般省略
...
# 执行剧本
[devops@controller ansible 17:01:40]$ ansible-playbook -i inventory -b deploy_web.yaml
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐