Ansible 学习笔记
几年前,还是大二的我在学习 TDD 的时候打算把 Fabric 和 Ansible 一起学了,结果看到 Fabric 不支持 Python3,Ansible 对 Python3.5 的支持有缺陷,处于某种洁癖就止步不前。现在想想自己当时高一用的不也是 Python 2,怎么现在对 Python 2 有了莫名的抵触。现在 Ansible 对 Python3 的支持非常好,Fabric3也有了,而我只有对自己的却步感到无尽的自责。
编译安装 Python
- 下载安装包到本地后进行配置
# ./configure --prefix=/usr/local \ --with-ensurepip=install \ --enable-shared \ DLFLAGS="-wl, -rpath /usr/local/lib"
- 进行编译安装并区分之前安装的版本
# make && make altinstall
- 设置软连接
# ln -sf /usr/local/bin/pip3.6 /usr/local/bin/pip
- Python37 安装时,还需要提供相应依赖
# Before make $ yum install libffi-devel -y # After Make $ cp libpython3.7m.so.1.0 /usr/lib64
安装 Ansible
Ansible 的安装有两种方法:Yum 和 Git。这里推荐使用 Git,有利于版本切换。
- 克隆 Ansible 仓库到本地
# git clone git://github.com/ansible/ansible.git
- 创建 Ansible 用户,使用 Virtualenv 创建对应的 Python 环境
# useradd deploy && su deploy
- 安装 Ansible 的相关依赖
$ pip install paramiko PyYAML Jinja2
- 切换 Ansible 版本为 2.5 (可选,Git安装的特性)
$ git checkout stable-2.5
- 启动 Ansible (重启系统后失效)
$ source ansible/hacking/env-setup -q
Ansible 密钥认证
其实就是使用 SSH 的密钥认证登录方式,方便 Ansible 操作目标主机。
# su deploy
# ssh-keygen -t rsa
# ssh-copy-id -i /home/deploy/.ssh/id_rsa.pub root@target.host.address
若
ssh-copy-id
命令不可用,还需安装相关软件:# yum -y install openssh-clients
Ansible 主机清单
Ansible 所有定义的主机与组规则可存放在当前目录下,也可以写在
/etc/Ansible/hosts
里。指定范例,供之后的 Playbooks 调用。- INI 格式范例:
[host_cluster_A] host1.alias ansible_port=22 ansible_host=192.0.2.50 host[02:50].example.com ansible_connection=ssh [host_cluster_B] ntp_server=ntp.atlanta.example.com proxy=proxy.atlanta.example.com
- YAML 格式范例:
all : hosts : mail.example.com : children : webservers : hosts : foo.example.com : bar.example.com : dbservers : hosts : one.example.com : two.example.com : three.example.com :
Ansible 配置文件
在下列表中,从上往下依次检查,检查到哪个可用就用哪个,后面直接忽视。(官方配置文件示例),Ansible 的其他配置文件同理。
ANSIBLE_CONFIG
环境变量,可定义配置文件的位置./ansible.cfg
存在于当前工作目录~/.ansible.cfg
存在于当前用户的 HOME 目录/etc/ansible/ansible.cfg
默认目录
Ansible Playbook 文件结构
Ansible Task
├─deploy.yml ( playbook 任务入口文件)
├─inventory ( Server 详细清单目录)
| └─taskenv ( 具体清单与变量声明文件 )
└─roles ( 任务列表 )
└─taskbox ( 详细目录 )
├─tasks
| └─main.yml ( 主任务文件 )
└─templates ( 用于传递参数的模板文件 )
Ansible Playbook 常用模块
- File 模块:在目标主机上创建文件或目录,并赋予其系统权限(属性:path, state, mode, owner, group)
- Copy 模块:实现服务器端到目标主机的文件传送(属性:remote_src, src, dest, mode, force)
- Stat 模块:获取远程文件的状态信息(属性:path; 方法:register)
- Debug 模块:调试并将结果在 Ansible 上输出 (方法:debug, when)
- Command / Shell 模块:执行命令,推荐使用后者(属性:Command, Shell)
- Template 模块:实现服务器端到目标主机 Jinja2 模板传送(属性:src, dest)
- Packaging 模块:调用目标主机包管理工具进行安装(方法:yum, apt; 属性:pkg, state)
- Service 模块:管理目标主机系统服务(属性:name, state)
taskenv 文件编写用例(NginX)
[NginX]
test.example.com
[NginX:vars]
server_name=test.example.com
user=root
output=/root/test.txt
server_name=test.example.com
port=80
user=deploy
worker_processes=4
max_open_file=65505
root=/www
Jinja2 模板文件编写用例(NginX)
user {{ user }};
worker_processes {{ worker_processes }};
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections {{ max_open_file }};
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
gzip on;
# Load config files from the /etc/nginx/conf.d directory
# The default server is in conf.d/default.conf
#include /etc/nginx/conf.d/*.conf;
server {
listen {{ port }} default_server;
server_name {{ server_name }};
charset utf-8;
#access_log logs/host.access.log main;
location / {
root {{ root }};
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/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;
}
}
}
Main.yml 编写用例
简单用法
- name: Print server name and user to remote testbox
shell: "echo 'Currently {{ user }} is logining {{ server_name }}' > {{ output }}"
- name: create a file
file: 'path=/root/foo.txt state=touch mode=0755 owner=foo group=foo'
- name: copy a file
copy: 'remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes'
- name: check if foo.sh exists
stat: 'path=/root/foo.sh'
register: script_stat
- debug: msg="foo.sh exists"
when: script_stat.stat.exists
- name: run the script
command: 'sh /root/foo.sh'
- name: write the nginx config file
template: src=roles/testbox/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: ensure nginx is at the latest version
yum: pkg=nginx state=latest
- name: start nginx service
service: name=nginx state=started
配置安装 NginX
- name: Disable system firewall
service: name=firewalld state=stopped
- name: Disable SELINUX
selinux: state=disabled
- name: setup nginx yum source
yum: pkg=epel-release state=latest
- name: write then nginx config file
template: src=roles/nginx/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: create nginx root folder
file: 'path={{ root }} state=directory owner={{ user }} group={{ user }} mode=0755'
- name: copy index.html to remote
copy: 'remote_src=no src=roles/nginx/files/index.html dest=/www/index.html mode=0755'
- name: restart nginx service
service: name=nginx state=restarted
- name: run the health check locally
shell: "sh roles/nginx/files/health_check.sh {{ server_name }}"
delegate_to: localhost
register: health_status
- debug: msg="{{ health_status.stdout }}"
部署 WordPress
- name: Update yum dependency
shell: 'yum update -y warn=False'
- name: Disable system firewall
service: name=firewalld state=stopped
- name: Disable SELINX
selinux: state=disabled
- name: Setup epel yum source for nginx and mariadb(mysql)
yum: pkg=epel-release state=latest
- name: Setup webtatic yum source for php-fpm
yum: name=https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
- name: Ensure nginx is at the latest version
yum: pkg=nginx state=latest
- name: Write the nginx config file
template: src=roles/wordpress/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: Create nginx root folder
file: 'path={{ root }} state=directory owner={{ user }} group={{ user }} mode=0755'
- name: Copy info.php to remote
copy: 'remote_src=no src=roles/wordpress/files/info.php dest=/data/www/info.php mode=0755'
- name: Restart nginx service
service: name=nginx state=restarted
- name: Setup php-fpm
command: 'yum install -y php70w php70w-fpm php70w-common php70w-mysql php70w-gd php70w-xml php70w-mbstring php70w-mcrypt warn=False'
- name: Restart php-fpm service
service: name=php-fpm state=restarted
- name: Copy php-fpm config file to remote
copy: 'remote_src=no src=roles/wordpress/files/www.conf dest=/etc/php-fpm.d/www.conf mode=0755 owner={{ user }} group={{ user }} force=yes'
- name: Restart php-fpm service
service: name=php-fpm state=restarted
- name: Run the health check locally
shell: "sh roles/wordpress/files/health_check.sh {{ server_name }} {{ port }}"
delegate_to: localhost
register: health_status
- debug: msg="{{ health_status.stdout }}"
- name: Setup mariadb(mysql)
command: "yum install -y mariadb mariadb-server warn=False"
- name: Backup current www folder
shell: 'mv {{ root }} {{ backup_to }}'
- name: Close git ssl verification
shell: 'git config --global http.sslVerify false'
- name: Clone WordPress repo to remote
git: "repo=https://{{ gitlab_user | urlencode }}:{{ gitlab_pass | urlencode }}@gitlab.example.com/root/Wordpress-project.git dest=/data/www version={{ branch }}"
when: project == 'wordpress'
- name: Change www folder permission
file: "path=/data/www mode=0755 owner={{ user }} group={{ user }}"
评论
发表评论