Ansible-playbook 自动部署 zookeeper 集群



1.Ansible 基础知识预热;


(1).合法的变量名

在使用变量之前最好先知道什么是合法的变量名. 变量名可以为字母,数字以及下划线.变量始终应该以字母开头. “foo_port”是个合法的变量名.”foo5”也是. “foo-port”, “foo port”, “foo.port” 和 “12”则不是合法的变量名.1.Inventory中定义变量;


(2).Inventory文件描述;

Topics

  • Inventory文件

    • 主机与组

    • 主机变量

    • 组的变量

    • 把一个组作为另一个组的子成员

    • 分文件定义 Host 和 Group 变量

    • Inventory 参数的说明

Ansible 可同时操作属于一个组的多台主机,组和主机之间的关系通过 inventory 文件配置. 默认的文件路径为 /etc/ansible/hosts

除默认文件外,你还可以同时使用多个 inventory 文件(后面会讲到),也可以从动态源,或云上拉取 inventory 配置信息.详见 动态 Inventory.


主机与组

/etc/ansible/hosts 文件的格式与windows的ini配置文件类似:

mail.example.com[webservers]foo.example.combar.example.com[dbservers]one.example.comtwo.example.comthree.example.com

方括号[]中是组名,用于对系统进行分类,便于对不同系统进行个别的管理.

一个系统可以属于不同的组,比如一台服务器可以同时属于 webserver组 和 dbserver组.这时属于两个组的变量都可以为这台主机所用,至于变量的优先级关系将于以后的章节中讨论.

如果有主机的SSH端口不是标准的22端口,可在主机名之后加上端口号,用冒号分隔.SSH 配置文件中列出的端口号不会在 paramiko 连接中使用,会在 openssh 连接中使用.

端口号不是默认设置时,可明确的表示为:

badwolf.example.com:5309

假设你有一些静态IP地址,希望设置一些别名,但不是在系统的 host 文件中设置,又或者你是通过隧道在连接,那么可以设置如下:

jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50

在这个例子中,通过 “jumper” 别名,会连接 192.168.1.50:5555.记住,这是通过 inventory 文件的特×××设置的变量. 一般而言,这不是设置变量(描述你的系统策略的变量)的最好方式.后面会说到这个问题.

一组相似的 hostname , 可简写如下:

[webservers]www[01:50].example.com

数字的简写模式中,01:50 也可写为 1:50,意义相同.你还可以定义字母范围的简写模式:

[databases]
db-[a:f].example.com

对于每一个 host,你还可以选择连接类型和连接用户名:

[targets]

localhost              ansible_connection=local
other1.example.com     ansible_connection=ssh        ansible_ssh_user=mpdehaan
other2.example.com     ansible_connection=ssh        ansible_ssh_user=mdehaan

所有以上讨论的对于 inventory 文件的设置是一种速记法,后面我们会讨论如何将这些设置保存为 ‘host_vars’ 目录中的独立的文件.


主机变量

前面已经提到过,分配变量给主机很容易做到,这些变量定义后可在 playbooks 中使用:

[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909


组的变量

也可以定义属于整个组的变量:

[atlanta]
host1
host2

[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com


把一个组作为另一个组的子成员

可以把一个组作为另一个组的子成员,以及分配变量给整个组使用. 这些变量可以给 /usr/bin/ansible-playbook 使用,但不能给 /usr/bin/ansible 使用:

[atlanta]
host1
host2

[raleigh]
host2
host3

[southeast:children]
atlanta
raleigh

[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2

[usa:children]
southeast
northeast
southwest
northwest

如果你需要存储一个列表或hash值,或者更喜欢把 host 和 group 的变量分开配置,请看下一节的说明.


分文件定义 Host 和 Group 变量

在 inventory 主文件中保存所有的变量并不是最佳的方式.还可以保存在独立的文件中,这些独立文件与 inventory 文件保持关联. 不同于 inventory 文件(INI 格式),这些独立文件的格式为 YAML.详见 YAML 语法 .

假设 inventory 文件的路径为:

/etc/ansible/hosts

假设有一个主机名为 ‘foosball’, 主机同时属于两个组,一个是 ‘raleigh’, 另一个是 ‘webservers’. 那么以下配置文件(YAML 格式)中的变量可以为 ‘foosball’ 主机所用.依次为 ‘raleigh’ 的组变量,’webservers’ 的组变量,’foosball’ 的主机变量:

/etc/ansible/group_vars/raleigh
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball

举例来说,假设你有一些主机,属于不同的数据中心,并依次进行划分.每一个数据中心使用一些不同的服务器.比如 ntp 服务器, database 服务器等等. 那么 ‘raleigh’ 这个组的组变量定义在文件 ‘/etc/ansible/group_vars/raleigh’ 之中,可能类似这样:

---
ntp_server: acme.example.org
database_server: storage.example.org

这些定义变量的文件不是一定要存在,因为这是可选的特性.

还有更进一步的运用,你可以为一个主机,或一个组,创建一个目录,目录名就是主机名或组名.目录中的可以创建多个文件, 文件中的变量都会被读取为主机或组的变量.如下 ‘raleigh’ 组对应于 /etc/ansible/group_vars/raleigh/ 目录,其下有两个文件 db_settings 和 cluster_settings, 其中分别设置不同的变量:

/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings

‘raleigh’ 组下的所有主机,都可以使用 ‘raleigh’ 组的变量.当变量变得太多时,分文件定义变量更方便我们进行管理和组织. 还有一个方式也可参考,详见 Ansible Vault 关于组变量的部分. 注意,分文件定义变量的方式只适用于 Ansible 1.4 及以上版本.

Tip: Ansible 1.2 及以上的版本中,group_vars/ 和 host_vars/ 目录可放在 inventory 目录下,或是 playbook 目录下. 如果两个目录下都存在,那么 playbook 目录下的配置会覆盖 inventory 目录的配置.

Tip: 把你的 inventory 文件 和 变量 放入 git repo 中,以便跟踪他们的更新,这是一种非常推荐的方式.


Inventory 参数的说明

如同前面提到的,通过设置下面的参数,可以控制 ansible 与远程主机的交互方式,其中一些我们已经讲到过:

ansible_ssh_host
      将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.

ansible_ssh_port
      ssh端口号.如果不是默认的端口号,通过此变量设置.

ansible_ssh_user
      默认的 ssh 用户名

ansible_ssh_pass
      ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)

ansible_sudo_pass
      sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)

ansible_sudo_exe (new in version 1.8)
      sudo 命令路径(适用于1.8及以上版本)

ansible_connection
      与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.

ansible_ssh_private_key_file
      ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.

ansible_shell_type
      目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.

ansible_python_interpreter
      目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如  \*BSD, 或者 /usr/bin/python
      不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).

      与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....

一个主机文件的例子:

some_host         ansible_ssh_port=2222     ansible_ssh_user=manager
aws_host          ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
freebsd_host      ansible_python_interpreter=/usr/local/bin/python
ruby_module_host  ansible_ruby_interpreter=/usr/bin/ruby.1.9.3


2.ZK集群部署环境信息表;


        主机名称     IP地址系统版本软件版本 版本
  ansible-master
192.168.52.11CentOS Linux release 7.5ansible 2.7.2
     zookeeper01192.168.52.12CentOS Linux release 7.5zookeeper-3.4.8
     zookeeper02192.168.52.13CentOS Linux release 7.5zookeeper-3.4.8
     zookeeper03192.168.52.14CentOS Linux release 7.5zookeeper-3.4.8
     zk软件包获取地址:http://down.51cto.com/data/2460552





3.部署ansible 服务端配置免密码秘钥登录身份;


  1.升级系统为最新软件包版本,安装ansible软件包

   yum update && yum -y install ansible 

   2.配置ssh免秘钥登录;---ansible管理端秘钥的公钥传递到被控端机器上;

image.png

      [root@ansible-master ~]# ssh-copy-id 192.168.52.12 

      [root@ansible-master ~]# ssh-copy-id 192.168.52.13  

     [root@ansible-master ~]# ssh-copy-id 192.168.52.14

 

    

4.配置ansible inventory 文件配置

   inventory 文件配置. 默认的文件路径为 /etc/ansible/hosts

  image.png


5.在inventory  文件中定于变量;

  在执行ansible 命令时,ansible 默认会从 /etc/ansible/host_vars和group_vars 两个目录下读取变量定义,默认ansible安装不创建此目录,

   且可以在此目录下创建和host文件中主机名或者组名同名的文件来定义变量;

   image.png

image.png

6.定义变量内容如下;

[root@ansible-master ~]# cat /etc/ansible/group_vars/zookeeper-servers 

---

zk01server: 192.168.52.12

zk02server: 192.168.52.13

zk03server: 192.168.52.14

zookeeper_group: work

zookeeper_user:  work

zookeeper_dir: /chj/data/zookeeper

zookeeper_appdir: /chj/app/zookeeper

zk01myid: 12

zk02myid: 13

zk03myid: 14


7.编写playbooks部署zk; 

目录结构如下;

image.png

(1).查看playbook 内容

---

- hosts: "all"
  gather_facts: no
  tasks:
    - name: Create zookeeper group
      group:
        name: '{{ zookeeper_group }}'
        state: present
      tags:
        - zookeeper_user

    - name: Create zookeeper user
      user:
        name: '{{ zookeeper_user }}'
        group: '{{ zookeeper_group }}'
        state: present
        createhome: no
      tags:
        - zookeeper_group

    - name: 检测是否安过zk
      stat:
        path: /chj/app/zookeeper
      register: node_files
    - debug:
        msg: "{{ node_files.stat.exists }}"
    - name: 检查是否存在java环境
      shell: if [ ! -f "/usr/local/jdk/bin/java" ];then echo "创建目录"; curl -o /usr/local/jdk1.8.0_121.tar.gz  http://download.pkg.com/chj_jdk1.8.0_121.tar.gz; tar xf /usr/local/jdk1.8.0_121.tar.gz -C /usr/local/jdk1.8.0_121; cd /usr/local/; mv  /usr/local/jdk1.8.0_121 jdk; ln -s /usr/local/jdk/bin/java /sbin/java;  else echo "目录已存在\n" ;fi 

    - name: 下载解压 chj_zookeeper
      unarchive: src=http://download.pkg.com/zookeeper.tar.gz dest=/chj/app/ copy=no
      when: node_files.stat.exists == False
      register: unarchive_msg
    - debug:
        msg: "{{ unarchive_msg }}"
    - name: 创建zookeeper 数据目录和日志目录
      shell: if [ ! -d "/chj/data/zookeeper" ] && [ ! -d "/chj/data/zookeeperLog/" ];then echo "创建目录"; mkdir -p /chj/data/{zookeeper,zookeeperLog}  ; else echo "目录已存在\n" ;fi

    - name: 修改目录权限
      shell: chown work:work -R /chj/{data,app}
      when: node_files.stat.exists == False
    - name: 配置zk myid
      shell: "hostname -i| cut -d '.' -f 4|awk '{print $1}' > /chj/data/zookeeper/myid"
    - name: Config zookeeper service
      template:
        src:  zoo.cfg.j2
        dest: /chj/app/zookeeper/conf/zoo.cfg
        mode: 0755

    - name: auto service manager zookeeper
      template:
        src:  zookeeper.service.j2
        dest: /usr/lib/systemd/system/zookeeper.service
        mode: 0755

    - name: Reload systemd
      command: systemctl daemon-reload
    - name: Restart ZooKeeper service
      shell: sudo su - work -c "/chj/app/zookeeper/console start" 
 
    - name: Status ZooKeeper service 
      shell: "sudo su - work -c '/chj/app/zookeeper/console status'"
      register: zookeeper_status_result
      ignore_errors: True
    - debug:
        msg: "{{ zookeeper_status_result }}"

(2).查看jinja2 配置文件内容;

[root@ansible-master templates]# cat zoo.cfg.j2 
tickTime=2000
initLimit=500
dataDir={{ zookeeper_dir }}
dataLogDir=/chj/data/zookeeperLog/
# the port at which the clients will connect
clientPort=10311
maxClientCnxns=1000000
server.{{ zk01myid }}={{ zk01server }}:10301:10331
server.{{ zk02myid }}={{ zk02server }}:10302:10332
server.{{ zk03myid }}={{ zk03server }}:10303:10333


 


8.查看playbooks 执行结果;

检查playbook 语法;

ansible-playbook ZooKeeperinstall.yml --syntax-check

playbook: ZooKeeperinstall.yml


ansible-playbook ZooKeeperinstall.yml -b

ansible-playbook ZooKeeperinstall.yml -b

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

TASK [Create zookeeper group] *******************************************************************************************************************************************************
ok: [192.168.52.12 ]
ok: [192.168.52.13]
ok: [192.168.52.14]

TASK [Create zookeeper user] ********************************************************************************************************************************************************
ok: [192.168.52.12 ]
ok: [192.168.52.13]
ok: [192.168.52.14]

TASK [检测是否安过zk] *********************************************************************************************************************************************************************
ok: [192.168.52.12 ]
ok: [192.168.52.13]
ok: [192.168.52.14]

TASK [debug] ************************************************************************************************************************************************************************
ok: [192.168.52.14] => {
    "msg": false
}
ok: [192.168.52.13] => {
    "msg": false
}
ok: [192.168.52.12 ] => {
    "msg": false
}

TASK [检查是否存在java环境] *****************************************************************************************************************************************************************
changed: [192.168.52.12 ]
changed: [192.168.52.14]
changed: [192.168.52.13]

TASK [下载解压 chj_zookeeper] ***********************************************************************************************************************************************************
changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [debug] ************************************************************************************************************************************************************************
ok: [192.168.52.14] => {
    "msg": {
        "changed": true, 
        "dest": "/chj/app/", 
        "extract_results": {
            "cmd": [
                "/bin/gtar", 
                "--extract", 
                "-C", 
                "/chj/app/", 
                "-z", 
                "-f", 
                "/home/ops/.ansible/tmp/ansible-tmp-1555134665.42-104390716550153/zookeeper.tar.gz"
            ], 
            "err": "", 
            "out": "", 
            "rc": 0
        }, 
        "failed": false, 
        "gid": 1002, 
        "group": "work", 
        "handler": "TgzArchive", 
        "mode": "0755", 
        "owner": "work", 
        "size": 53, 
        "src": "/home/ops/.ansible/tmp/ansible-tmp-1555134665.42-104390716550153/zookeeper.tar.gz", 
        "state": "directory", 
        "uid": 1002
    }
}
ok: [192.168.52.13] => {
    "msg": {
        "changed": true, 
        "dest": "/chj/app/", 
        "extract_results": {
            "cmd": [
                "/bin/gtar", 
                "--extract", 
                "-C", 
                "/chj/app/", 
                "-z", 
                "-f", 
                "/home/ops/.ansible/tmp/ansible-tmp-1555134665.44-240377701606664/zookeeper.tar.gz"
            ], 
            "err": "", 
            "out": "", 
            "rc": 0
        }, 
        "failed": false, 
        "gid": 1002, 
        "group": "work", 
        "handler": "TgzArchive", 
        "mode": "0755", 
        "owner": "work", 
        "size": 53, 
        "src": "/home/ops/.ansible/tmp/ansible-tmp-1555134665.44-240377701606664/zookeeper.tar.gz", 
        "state": "directory", 
        "uid": 1002
    }
}
ok: [192.168.52.12 ] => {
    "msg": {
        "changed": true, 
        "dest": "/chj/app/", 
        "extract_results": {
            "cmd": [
                "/bin/gtar", 
                "--extract", 
                "-C", 
                "/chj/app/", 
                "-z", 
                "-f", 
                "/home/ops/.ansible/tmp/ansible-tmp-1555134665.45-222980892511143/zookeeper.tar.gz"
            ], 
            "err": "", 
            "out": "", 
            "rc": 0
        }, 
        "failed": false, 
        "gid": 1002, 
        "group": "work", 
        "handler": "TgzArchive", 
        "mode": "0755", 
        "owner": "work", 
        "size": 53, 
        "src": "/home/ops/.ansible/tmp/ansible-tmp-1555134665.45-222980892511143/zookeeper.tar.gz", 
        "state": "directory", 
        "uid": 1002
    }
}

TASK [创建zookeeper 数据目录和日志目录] ********************************************************************************************************************************************************
changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [修改目录权限] ***********************************************************************************************************************************************************************
 [WARNING]: Consider using the file module with owner rather than running chown.  If you need to use command because file is insufficient you can add warn=False to this command
task or set command_warnings=False in ansible.cfg to get rid of this message.

changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [配置zk myid] ********************************************************************************************************************************************************************
changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [Config zookeeper service] *****************************************************************************************************************************************************
changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [auto service manager zookeeper] ***********************************************************************************************************************************************
changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [Reload systemd] ***************************************************************************************************************************************************************
changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [Restart ZooKeeper service] ****************************************************************************************************************************************************
 [WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running sudo

changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [Status ZooKeeper service] *****************************************************************************************************************************************************
changed: [192.168.52.12 ]
changed: [192.168.52.13]
changed: [192.168.52.14]

TASK [debug] ************************************************************************************************************************************************************************
ok: [192.168.52.13] => {
    "msg": {
        "changed": true, 
        "cmd": "sudo su - work -c '/chj/app/zookeeper/console status'", 
        "delta": "0:00:02.411393", 
        "end": "2019-04-13 13:51:46.465955", 
        "failed": false, 
        "rc": 0, 
        "start": "2019-04-13 13:51:44.054562", 
        "stderr": "ZooKeeper JMX enabled by default\nUsing config: /chj/app/zookeeper/bin/../conf/zoo.cfg", 
        "stderr_lines": [
            "ZooKeeper JMX enabled by default", 
            "Using config: /chj/app/zookeeper/bin/../conf/zoo.cfg"
        ], 
        "stdout": "查看zookeeper服务状态", 
        "stdout_lines": [
            "查看zookeeper服务状态"
        ], 
        "warnings": [
            "Consider using 'become', 'become_method', and 'become_user' rather than running sudo"
        ]
    }
}
ok: [192.168.52.12 ] => {
    "msg": {
        "changed": true, 
        "cmd": "sudo su - work -c '/chj/app/zookeeper/console status'", 
        "delta": "0:00:01.887234", 
        "end": "2019-04-13 13:51:45.916725", 
        "failed": false, 
        "rc": 0, 
        "start": "2019-04-13 13:51:44.029491", 
        "stderr": "ZooKeeper JMX enabled by default\nUsing config: /chj/app/zookeeper/bin/../conf/zoo.cfg", 
        "stderr_lines": [
            "ZooKeeper JMX enabled by default", 
            "Using config: /chj/app/zookeeper/bin/../conf/zoo.cfg"
        ], 
        "stdout": "查看zookeeper服务状态", 
        "stdout_lines": [
            "查看zookeeper服务状态"
        ], 
        "warnings": [
            "Consider using 'become', 'become_method', and 'become_user' rather than running sudo"
        ]
    }
}
ok: [192.168.52.14] => {
    "msg": {
        "changed": true, 
        "cmd": "sudo su - work -c '/chj/app/zookeeper/console status'", 
        "delta": "0:00:02.401280", 
        "end": "2019-04-13 13:51:46.486860", 
        "failed": false, 
        "rc": 0, 
        "start": "2019-04-13 13:51:44.085580", 
        "stderr": "ZooKeeper JMX enabled by default\nUsing config: /chj/app/zookeeper/bin/../conf/zoo.cfg", 
        "stderr_lines": [
            "ZooKeeper JMX enabled by default", 
            "Using config: /chj/app/zookeeper/bin/../conf/zoo.cfg"
        ], 
        "stdout": "查看zookeeper服务状态", 
        "stdout_lines": [
            "查看zookeeper服务状态"
        ], 
        "warnings": [
            "Consider using 'become', 'become_method', and 'become_user' rather than running sudo"
        ]
    }
}

PLAY RECAP **************************************************************************************************************************************************************************
192.168.52.12                : ok=16   changed=10   unreachable=0    failed=0   
192.168.52.13           : ok=16   changed=10   unreachable=0    failed=0   
192.168.52.14               : ok=16   changed=10   unreachable=0    failed=0   、