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 }}"
评论
发表评论