Ansible企业应用实战
# Ansible企业应用实战
# 掌握要点
该实战案例为使用 Ansible 工具部署一个 3 节点的集群商城系统。
部署Mariadb高可用+Redis+Zookeeper+Kafka的集群。
# 节点规划
IP | 主机名 | 节点 |
---|---|---|
192.168.1.4 | ansible | Ansible 节点 |
192.168.1.7 | node1 | Node1 节点 |
192.168.1.26 | node2 | Node2 节点 |
192.168.1.3 | node3 | Node3 节点 |
# 目录结构
# ⚫项目目录
首先在/opt 目录下创建一个项目目录 gpmall_ansible,这个就是本次企业应用实战的项目目录.
[root@ansible ~]# mkdir /opt/gpmall_ansible
# ⚫创建角色
在创建 roles 角色目录之前,考虑将集群商城+监控案例拆分为多个 roles 执行,这样的话,PlayBook 易于编写和读懂。 安装集群商城+监控,使用 init(基础环境)、mariadb(数据库)、redis(数据库)、zookeeper(协调服务)、kafka(消息队列)、jar(运行 Jar 包)、nginx (前端服务)这些 roles 来完成。
在每个角色目录下面都有一样的目录,这些目录中的 task 目录一般是一定会用到的,其他的目录视情况而定来使用。
[root@ansible ~]# mkdir -p /opt/gpmall_ansible/roles/{init,mariadb,redis,zookeeper,kafka,jar,nginx,zabbix}/{tasks,files,templates,meta,handlers,vars}
[root@ansible ~]# tree /opt/gpmall_ansible/
/opt/gpmall_ansible/
└── roles
├── init
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── jar
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── kafka
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── mariadb
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── nginx
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── redis
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── zabbix
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
└── zookeeper
├── files
├── handlers
├── meta
├── tasks
├── templates
└── vars
# ⚫创建 group_vars 目录
在项目目录/opt/gpmall_ansible 下创建 group_vars 目录,并在该目录下创建all 文件,该目录用来存放变量声明文件 all。
[root@ansible ~]# cd /opt/gpmall_ansible/
[root@ansible gpmall_ansible]# mkdir group_vars
[root@ansible gpmall_ansible]# cd group_vars/
[root@ansible group_vars]# touch all
# ⚫创建安装入口文件
进入/opt/gpmall_ansible 目录,创建 install_gpmall_cluster.yaml 文件,该文件是安装动作的入口文件。
[root@ansible gpmall_ansible]# touch install_gpmall_cluster.yaml
[root@ansible gpmall_ansible]# ll
total 0
drwxr-xr-x. 2 root root 17 Aug 26 21:31 group_vars
-rw-r--r--. 1 root root 0 Aug 26 21:33 install_gpmall_cluster.yaml
drwxr-xr-x. 10 root root 114 Aug 26 21:18 roles
# 编写init角色
# 1.编写清单
⚫该角色执行的任务是用来部署 3 个 Node 节点的基础环境,包括关闭防火墙、 SELinux、配置 Yum 源、安装 Java JDK 环境。
⚫在 roles/init/tasks 目录下,创建 main.yaml 文件。
[root@ansible roles]# vim init/tasks/main.yaml
- name: disable selinux
shell: setenforce 0
- name: stop firewalld
shell: systemctl stop firewalld
- name: tar gpmall-repo
unarchive:
src: gpmall-repo.tar.gz
dest: /opt
- name: mv repo
shell: rm -rf /etc/yum.repos.d/*
- name: create local.repo
copy: src=local.repo dest=/etc/yum.repos.d/
- name: install jdk
yum: name={{item}} state=present
with_items:
- java-1.8.0-openjdk
- java-1.8.0-openjdk-devel
- name: copy hosts
template: src=hosts.j2 dest=/etc/hosts
# 2.files添加文件
⚫该剧本用到了 copy 和 template 以及unarchive模块,copy 模块使用的文件及镜像包,放入 tasks 同级目录的 files 目录下;
⚫template 模块使用的 Jinja2 文件,放入 tasks 同级目录的 templates 目录下。
⚫在该 init 角色剧本中,即把 gpmall-repo.tar.gz 镜像和 local.repo 文件拷贝至 init/files 目录下。
⚫把 hosts.j2 文件拷贝至 init/templates 目录下。
[root@ansible init]# ll files/
total 194544
-rw-r--r-- 1 root root 199206529 Feb 18 01:56 gpmall-repo.tar.gz
-rw-r--r-- 1 root root 148 Feb 18 01:57 local.repo
[root@ansible init]# ll templates/
total 4
-rw-r--r-- 1 root root 244 Feb 18 01:59 hosts.j2
[root@ansible init]# cat files/local.repo
[centos]
name=centos
baseurl=http://192.168.1.113/file/repo/centos/
gpgcheck=0
[gpmall]
name=gpmall
baseurl=file:///opt/gpmall-repo
gpgcheck=0
[root@ansible init]# cat templates/hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{{hostip1}} {{hostname1}}
{{hostip2}} {{hostname2}}
{{hostip3}} {{hostname3}}
# 3.在all添加变量
因为设置的变量,所以需要在**/opt/gpmall_ansible/group_vars/all** 中声明变量,all 文件内容如下。
[root@ansible gpmall_ansible]# cat group_vars/all
hostip1: 192.168.1.7
hostip2: 192.168.1.26
hostip3: 192.168.1.3
hostname1: node1
hostname2: node2
hostname3: node3
# 编写mariadb角色
# 1.编写清单
⚫该角色的作用是在 3 个节点上安装数据库服务并配置成数据库 MariaDBGalera Cluster 集群,在 roles/mariadb/tasks 目录下,创建 main.yaml 文件。
⚫主要内容是安装mariadb以及配置成高可用。
[root@ansible mariadb]# cat tasks/main.yaml
- name: install mariadb
yum:
name:
- mariadb-server
- mariadb
state: present
- name: start mariadb
service:
name: mariadb
state: started
- name: mysql_pass
shell: mysqladmin -uroot password {{DB_PASS}}
- name: config mariadb
template: src=server.cnf.j2 dest=/etc/my.cnf.d/server.cnf
- name: grant privileges
shell: mysql -uroot -p{{DB_PASS}} -e "grant all privileges on *.* to root@'%' identified by '{{DB_PASS}}';"
- name: stop db
shell: systemctl stop mariadb
- name: new cluster
shell: galera_new_cluster
when: ansible_fqdn == "node1"
- name: start maraidb
shell: systemctl start mariadb
when: ansible_fqdn == "{{ item }}"
with_items:
- node2
- node3
# 2.修改template模板
⚫在该 mariadb 角色剧本中,用到了 template 模块,需要把 server.cnf.j2 文件放入 tasks 同级别的 templates 目录下。
⚫需要修改成的内容将会用ansible的循环语句进行修改成j2的模板。
⚫server.cnf.j2 文件为数据库的配置文件,因需要确保各个节点的配置,需要使用变量。
[root@ansible mariadb]# cat templates/server.cnf.j2
[galera]
# Mandatory settings
wsrep_on=ON
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_cluster_address="gcomm://{{hostip1}},{{hostip2}},{{hostip3}}"
{% if ansible_fqdn == "node1" %}
wsrep_node_name={{hostname1}}
wsrep_node_address={{hostip1}}
{% elif ansible_fqdn == "node2" %}
wsrep_node_name={{hostname2}}
wsrep_node_address={{hostip2}}
{% else %}
wsrep_node_name={{hostname3}}
wsrep_node_address={{hostip3}}
{% endif %}
wsrep_sst_method=rsync
wsrep_causal_reads=ON
binlog_format=row
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
innodb_buffer_pool_size=120M
#
# Allow server to accept connections on all interfaces.
#
{% if ansible_fqdn == "node1" %}
bind-address={{hostip1}}
{% elif ansible_fqdn == "node2" %}
bind-address={{hostip2}}
{% else %}
bind-address={{hostip3}}
{% endif %}
#
# Optional setting
wsrep_slave_threads=1
innodb_flush_log_at_trx_commit=0
脚本中使用了 DB_PASS 变量,所以需要在 all 文件中声明,编辑**/opt/gpmall_ansible/group_vars/all** 文件,添加一条变量声明。
[root@ansible gpmall_ansible]# cat group_vars/all
hostip1: 192.168.1.7
hostip2: 192.168.1.26
hostip3: 192.168.1.3
hostname1: node1
hostname2: node2
hostname3: node3
DB_PASS: 123456 #添加一个DB_PASS
# 编写redis角色
# 1.编写清单
⚫该角色的作用是安装 redis 服务并配置启动。
⚫关闭bind 127.0.0.1 和关闭保护模式。
[root@ansible redis]# vim tasks/main.yaml
- name: install redis
yum:
name: redis
state: present
when: ansible_fqdn == "node1"
- name: config redis
copy: src=redis.conf dest=/etc/redis.conf
when: ansible_fqdn == "node1"
- name: start redis
shell: systemctl restart redis
when: ansible_fqdn == "node1"
# 2.修改配置文件
[root@ansible redis]# cp /etc/redis.conf files/
[root@ansible redis]# vim files/redis.conf
#bind 127.0.0.1 将bind 127.0.0.1注释掉
protected-mode no #将yes修改为no
# 编写zookeeper角色
# 1.编写清单
⚫该角色的作用是在 3 个节点上安装 Zookeeper 服务并配置为 Zookeeper 集群。
⚫在 roles/zookeeper/tasks 目录下,创建 main.yaml 文件。
[root@ansible zookeeper]# cat tasks/main.yaml
- name: unarchive tar
unarchive:
src: zookeeper-3.4.14.tar.gz
dest: /opt
- name: delete zoo.cfg
shell: rm -rf /opt/zookeeper-3.4.14/conf/zoo_sample.cfg
- name: config zoo.cfg
template:
src: zoo.cfg.j2
dest: /opt/zookeeper-3.4.14/conf/zoo.cfg
- name: mkdir file
shell: mkdir -p /tmp/zookeeper
- name: config myid
template:
src: myid.j2
dest: /tmp/zookeeper/myid
- name: start zookeeper
shell: sh /opt/zookeeper-3.4.14/bin/zkServer.sh start
# 2.添加文件
⚫该剧本使用了 copy 和 template 模块,故需要将 zookeeper-3.4.14.tar.gz 镜像 包拷贝至 tasks 目录同级别的 files 目录下。
⚫将 zoo.cfg.j2 文件和 myid.j2 文件拷贝 至 templates 下。
[root@ansible zookeeper]# ll files/
total 36796
-rw-r--r-- 1 root root 37676320 Nov 12 2020 zookeeper-3.4.14.tar.gz
[root@ansible zookeeper]# cat templates/myid.j2
{% if ansible_fqdn == "node1" %}
1
{% elif ansible_fqdn == "node2" %}
2
{% else %}
3
{%endif%}
[root@ansible zookeeper]# cat templates/zoo.cfg.j2
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1={{hostip1}}:2888:3888
server.2={{hostip2}}:2888:3888
server.3={{hostip3}}:2888:3888
# 编写kafka角色
# 1.编写清单
⚫该角色的作用是在 3 个节点上安装 Kafka 服务并配置为 Kafka 集群,在 roles/kafka/tasks 目录下。
⚫配置template将修改好的配置文件替换。
[root@ansible kafka]# cat tasks/main.yaml
- name: unarchive tar
unarchive:
src: kafka_2.11-1.1.1.tgz
dest: /opt
- name: config
template:
src: server.properties.j2
dest: /opt/kafka_2.11-1.1.1/config/server.properties
- name: start kafka
shell: sh /opt/kafka_2.11-1.1.1/bin/kafka-server-start.sh -daemon /opt/kafka_2.11-1.1.1/config/server.properties
# 2.添加文件
⚫该剧本使用了 copy 和 template 模块,故需要将 kafka_2.11-1.1.1.tgz 镜像包 拷贝至tasks目录同级别的files目录下。
⚫将server.properties.j2文件拷贝至templates 下。
[root@ansible kafka]# ll files/
total 56128
-rw-r--r-- 1 root root 57471165 Feb 21 00:50 kafka_2.11-1.1.1.tgz
[root@ansible kafka]# cat templates/server.properties.j2
#broker.id=0
#zookeeper.connect=localhost:2181
{% if ansible_fqdn == "node1" %}
broker.id=1
{% elif ansible_fqdn == "node2" %}
broker.id=2
{% else %}
broker.id=3
{% endif %}
zookeeper.connect={{hostip1}}:2181,{{hostip2}}:2181,{{hostip3}}:2181
{% if ansible_fqdn == "node1" %}
listeners = PLAINTEXT://{{hostip1}}:9092
{% elif ansible_fqdn == "node2" %}
listeners = PLAINTEXT://{{hostip2}}:9092
{% else %}
listeners = PLAINTEXT://{{hostip3}}:9092
{% endif %}
# 编写jar角色
# 1.编写清单
⚫该角色的作用是在 Node2 和 Node3 节点上启动应用商城的 Jar 包,在 roles/jar/tasks 目录下,创建 main.yaml 文件
⚫主要工作是负责传送jar包包括启动jar包。
[root@ansible jar]# cat tasks/main.yaml
- name: copy sql
copy: src=gpmall.sql dest=/opt/gpmall.sql
when: ansible_fqdn == "node1"
- name: config db
shell: mysql -uroot -p{{DB_PASS}} -e "create database gpmall;use gpmall;source /opt/gpmall.sql;"
when: ansible_fqdn == "node1"
- name: unarchive jar
unarchive:
src: jar.tar.gz
dest: /opt
when: ansible_fqdn == "{{item}}"
with_items:
- node2
- node3
- name: copy hostst
template: src=hosts.j2 dest=/etc/hosts
- name: start jar
shell: nohup java -jar /opt/user-provider-0.0.1-SNAPSHOT.jar &
when: ansible_fqdn == "{{item}}"
with_items:
- node2
- node3
- name: start jar
shell: nohup java -jar /opt/shopping-provider-0.0.1-SNAPSHOT.jar &
when: ansible_fqdn == "{{item}}"
with_items:
- node2
- node3
- name: start jar
shell: nohup java -jar /opt/gpmall-shopping-0.0.1-SNAPSHOT.jar &
when: ansible_fqdn == "{{item}}"
with_items:
- node2
- node3
- name: start jar
shell: nohup java -jar /opt/gpmall-user-0.0.1-SNAPSHOT.jar &
when: ansible_fqdn == "{{item}}"
with_items:
- node2
- node3
# 2.添加文件
⚫同样,该剧本使用了 copy 和 template 模块,需要将 gpmall.sql 和 4 个 gpmall 商城的 Jar 包拷贝至 tasks 目录同级别的 files 目录下。
⚫将 hosts.j2 文件拷贝至 templates 目录下。
[root@ansible jar]# ll files/
total 179696
-rw-r--r-- 1 root root 59239 Nov 12 2020 gpmall.sql
-rw-r--r-- 1 root root 183943654 Feb 21 01:24 jar.tar.gz
[root@ansible jar]# cat templates/hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{{hostip1}} redis.mall
{{hostip1}} mysql.mall
{{hostip1}} kafka1.mall
{{hostip2}} kafka2.mall
{{hostip3}} kafka3.mall
{{hostip1}} zk1.mall
{{hostip2}} zk2.mall
{{hostip3}} zk3.mal
# 编写nginx
# 1.编写清单
⚫该角色的作用是在 Node1 节点上安装 Nginx 服务,部署前端,并使用 IP 轮 询的方式配置负载均衡,在 roles/nginx/tasks 目录下,创建 main.yaml 文件。
⚫主要是修改配置文件然后重启服务。
[root@ansible nginx]# cat tasks/main.yaml
- name: install nginx
yum: name=nginx state=present
when: ansible_fqdn == "node1"
- name: delete html
shell: rm -rf /usr/share/nginx/html/*
when: ansible_fqdn == "node1"
- name: copy file
copy: src=dist dest=/opt
- name: cp file
shell: cp -rvf /opt/dist/* /usr/share/nginx/html/
when: ansible_fqdn == "node1"
- name: config default.config
template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf
when: ansible_fqdn == "node1"
- name: start nginx
service: name=nginx state=started
when: ansible_fqdn == "node1"
# 2.添加文件
⚫该剧本使用了 copy 和 template 模块,故需要将 dist 目录拷贝至 tasks 目录同 级别的 files 目录下。
⚫将 default.conf.j2 文件拷贝至 templates 下。下面代码展示了 default.conf.j2 文件的内容。
[root@ansible nginx]# ll files/
total 0
drwxr-xr-x 3 root root 38 Feb 21 02:13 dist
[root@ansible nginx]# cat templates/default.conf.j2
upstream myuser {
server {{hostip2}}:8082;
server {{hostip3}}:8082;
ip_hash;
}
upstream myshopping {
server {{hostip2}}:8081;
server {{hostip3}}:8081;
ip_hash;
}
upstream mycashier {
server {{hostip2}}:8083;
server {{hostip3}}:8083;
ip_hash;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /user {
proxy_pass http://myuser;
}
location /shopping {
proxy_pass http://myshopping;
}
location /cashier {
proxy_pass http://mycashier;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# 编写role角色
⚫执行角色剧本之后可以访问node1节点的IP
⚫过程中报错需要进行解决。
[root@ansible gpmall_ansible]# cat install_gpmall_cluster.yaml
---
- hosts: hosts
remote_user: root
roles:
- init
- mariadb
- redis
- zookeeper
- kafka
- jar
- nginx
[root@ansible gpmall_ansible]# ansible-playboox install_gpmall_cluster.yaml