组件架构

图片.png
ansible core : ansible 自身核心模块
host inventory: 主机库,定义可管控的主机列表
connection plugins: 连接插件,一般默认基于 ssh 协议连接
modules:core modules ( 自带模块 ) 、 custom modules ( 自定义模块 )
playbooks :剧本,按照所设定编排的顺序执行完成安排任务

Ansible与Saltstack和puppet的最大区别是Ansible无需在被控端部署任何客户端代理,默认直接通过SSH通道进行远程命令的执行或下发配置;相同点都是具备功能强大、灵活的的系统管理、状态配置,都使用YAML格式来描述配置,都具有丰富的模板及API。

Ansible提供了一个在线的Playbook分享平台,地址是:https://galaxy.ansible.com/,该平台汇聚了各类常用功能的角色,找到适合自己的Role(角色)后,只需要运行“ansible-galaxy install 作者id.角色包名称”就可以安装到本地。

  1. [root@xuegod63 ~]# ansible-galaxy install bennojoy.mysql
  2. - downloading role 'mysql', owned by bennojoy
  3. - downloading role from https://github.com/bennojoy/mysql/archive/master.tar.gz
  4. - extracting bennojoy.mysql to /etc/ansible/roles/bennojoy.mysql
  5. - bennojoy.mysql was installed successfully
  6. [root@xuegod63 ~]# ls /etc/ansible/roles/bennojoy.mysql/
  7. defaults/ handlers/ meta/ README.md tasks/ templates/ vars/


安装

  1. 建议使用yum方式安装
  2. 先安装在线yumepel
  3. [root@xuegod63 ~]# rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
  4. Retrieving http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
  5. warning: /var/tmp/rpm-tmp.tDsKed: Header V3 RSA/SHA256 Signature, key ID 0608b895: NOKEY
  6. Preparing... ########################################### [100%]
  7. 1:epel-release ########################################### [100%]
  8. 生成一下缓存
  9. [root@xuegod63 ~]# yum makecache
  10. [root@xuegod63 ~]# yum list | grep ansible
  11. ansible.noarch 2.1.1.0-1.el6 epel
  12. ansible-inventory-grapher.noarch 1.0.1-2.el6 epel
  13. ansible-lint.noarch 2.0.1-1.el6 epel
  14. ansible1.9.noarch 1.9.6-2.el6.1 epel
  15. 安装
  16. [root@xuegod63 ~]# yum install -y ansible1.9.noarch


入门操作

  1. 在这里我们用自己创建的目录/var/opt来存放ansible相应的文件
  2. [root@xuegod63 ~]# cd /var/opt
  3. 定义主机清单
  4. ansible基于ssh连接inventory中指定的远程主机时,将以此处的参数指定的属性进行
  5. ansible_ssh_port:指定 ssh 端口
  6. ansible_ssh_user:指定 ssh 用户
  7. ansible_ssh_pass:指定 ssh 用户登录是认证密码,明文密码不安全
  8. ansible_sudo_pass:指明 sudo 时候的密码
  9. 新建文件hosts
  10. [root@xuegod63 opt]# vim hosts
  11. #增加以下内容
  12. [tomcatserver] #主机组名
  13. 192.168.10.64 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=123456
  14. 192.168.10.65 #主机IP或主机名
  15. 简单测试下主机的连通性
  16. [root@xuegod63 opt]# ansible -i hosts tomcatserver -m ping -k
  17. SSH password:
  18. 192.168.10.65 | success >> {
  19. "changed": false,
  20. "ping": "pong"
  21. }
  22. 192.168.10.64 | success >> {
  23. "changed": false,
  24. "ping": "pong"
  25. }
  26. 一般来说,使用明文密码不安全,所以增加主机无密码访问
  27. 生成密钥对
  28. [root@xuegod63 opt]# ssh-keygen -t rsa -P ""
  29. Generating public/private rsa key pair.
  30. Enter file in which to save the key (/root/.ssh/id_rsa):
  31. Your identification has been saved in /root/.ssh/id_rsa.
  32. Your public key has been saved in /root/.ssh/id_rsa.pub.
  33. The key fingerprint is:
  34. 10:29:6f:38:e5:e3:da:52:3f:48:ed:7a:ae:ca:db:0a root@xuegod63.cn
  35. The key's randomart image is:
  36. +--[ RSA 2048]----+
  37. | .. |
  38. | . o. |
  39. | *. |
  40. | o =. |
  41. | + oS |
  42. | + . |
  43. | E = + |
  44. | oo.o = |
  45. | ==+=.. |
  46. +-----------------+
  47. 拷贝密钥到xuegod64和xuegod65
  48. [root@xuegod63 opt]# ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.10.64
  49. root@192.168.10.64's password:
  50. Now try logging into the machine, with "ssh '192.168.10.64'", and check in:
  51. .ssh/authorized_keys
  52. to make sure we haven't added extra keys that you weren't expecting.
  53. [root@xuegod63 opt]# ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.10.65
  54. root@192.168.10.65's password:
  55. Now try logging into the machine, with "ssh '192.168.10.65'", and check in:
  56. .ssh/authorized_keys
  57. to make sure we haven't added extra keys that you weren't expecting.
  58. anisble命令
  59. ansible [–i 主机文件] [-f 批次] [组名] [–m 模块名称] [–a 模块参数]
  60. 模块查询命令
  61. ansible-doc -l 列出所有的模块列表
  62. ansible-doc -s 查看指定模块的参数

常用模块

  1. 1.远程命令模块
  2. command:作为ansible的默认模块,可以运行远程权限范围内的所有shell命令;
  3. script:是在远程主机上执行主控端存储的shell脚本,相当于scp+shell组合;
  4. shell:是执行远程主机上的shell脚本
  5. # ansible -i hosts tomcatserver -m command -a "free -m"
  6. 2.copy模块
  7. copy:实现主控端向目标主机拷贝文件,类似scp功能
  8. # ansible -i hosts tomcatserver -m copy -a "src=./hosts dest=/tmp/ owner=root group=root mode=0755"
  9. 3.file模块
  10. file:设置文件属性。
  11. # ansible -i hosts tomcatserver -m file -a "path=/tmp/hosts mode=0777"
  12. 4.stat模块
  13. stat:获取远程文件信息
  14. # ansible -i hosts tomcatserver -m stat -a "path=/tmp/hosts"
  15. 5.get_url模块
  16. get_url:实现远程主机下载指定url到本地,支持sha256sum文件校验。
  17. # ansible -i hosts tomcatserver -m get_url -a "url=http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm dest=/tmp/ mode=0440 force=yes"
  18. 6.yum模块
  19. yumlinux平台软件包管理。
  20. 例子:安装php软件
  21. # ansible -i hosts tomcatserver -m yum -a "name=php state=latest"
  22. 7.cron模块
  23. cron:远程主机crontab配置。
  24. # ansible -i hosts tomcatserver -m cron -a "name='list dir' minute='*/30' job='ls /tmp'"
  25. 8. mount模块
  26. mount:远程主机分区挂载。
  27. # ansible -i hosts tomcatserver -m mount -a "name=/mnt src=/dev/sda1 fstype=ext4 opts=ro state=present"
  28. 9.service模块
  29. service:远程主机系统服务管理。
  30. [root@xuegod63 opt]# ansible -i hosts tomcatserver -m service -a "name=httpd state=restarted"
  31. 验证:查看服务启动时间
  32. [root@xuegod64 ~]# ps -eo cmd,pid,lstart,etime | grep httpd
  33. 10.sysctl模块
  34. sysctl:远程主机sysctl配置。
  35. # ansible -i hosts tomcatserver -m sysctl -a "name=net.ipv4.ip_forward value=1 reload=yes"
  36. 11.user模块
  37. user:远程主机用户管理
  38. # ansible -i hosts tomcatserver -m user -a "name=less state=present"


playbook

Playbook是一个不同于使用ansible命令行执行方式的模式,功能更强大灵活,简单地说,playbook是一个非常简单的配置管理和多主机部署系统。
playbook是由一个或多个”play”组成的列表。play的主要功能在于将事先归为一组的主机装扮成事先通过ansible中的task定义好的角色。
github上提供了大量的实例供大家参考 https://github.com/ansible/ansible-examples

核心元素

  • Hosts 执行的远程主机列表
  • Tasks 任务集
  • Variables 内置变量或自定义变量在playbook中调用
  • Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
  • Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
  • tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

playbooks 中 定义任务:

  1. ---
  2. - name task description 注释 描述信息
  3. module_name: module_args 声明模块:定义 ansible 模块参数

ansible-playbook 执行 命令:

  1. ansible-playbook <site.yml> ... [options]
  2. -C --check #只检测可能会发生的改变,但不真正执行操作
  3. --list-hosts #列出运行任务的主机
  4. --list-tags #列出tag
  5. --list-tasks #列出task
  6. --limit 主机列表 #只针对主机列表中的主机执行
  7. -v -vv -vvv #显示过程

Playbook 是一个由一个或多个 play 组成的文件;play 是针对特定主机或主机组执行的一组有序的任务;每个 playbook 必须包含两部分:
hosts: 运行 playbook 的一组主机
tasks: 需要在主机上运行的任务
除了这两个必须选项,还有一些可选项选项,也可能需要包含在 play 中,如:
name: play 的名称,在运行该 play 时,会在运行过程中显示。
become: 与配置文件中的 become 作用一样,用于提权,当配置文件中禁用提权时,你想要某个 play 使用提权的话,你可以在 play 中添加 become。
playbook 以 yaml 格式编写的,通常以 yml 扩展名保存。yaml 格式使用空格缩进,对于空格的数量没有特别要求,但需要注意:

  • 同一级别内的元素必须使用相同的缩进;
  • 对于子项目,缩进必须比父项目多

Playbook 以 —- 开头,用于标记文件开始;
第二行的 name 为该 play 的名称;
第三行的 hosts 表示将要运行该 play 的主机;
第四行的 tasks 表示该 play 将要执行的具体任务;
通过缩进,我们可以看出 tasks 一共分为三个部分,也就是三个模块,每个模块由一个 name 开表示该模块的 name,虽然 name 是可选选项,但建议写上,用来作为对该模块执行任务的解释说明,并且 name 的内容会在 playbook 执行此模块时,显示在执行过程中;
name 下面的是模块的名称,在该 play 的 tasks 中一共有三个模块:
apt: 用于安装软件
copy: 用于复制文件或内容
service: 用于操作 service,如启动服务,重启服务等

roles

学习资料:http://www.yunweipai.com/34669.html

角色是ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
运维复杂的场景:建议使用roles,代码复用度高
ansible - 图2

现生产案例

cnr_gateway.yml

  1. - hosts: cnr_gateway
  2. become: yes
  3. serial: 1
  4. become_method: sudo
  5. gather_facts: yes
  6. roles:
  7. - cnr_gateway

./roles/cnr_gateway/{defaults,handlers,PaxHeader,tasks,templates}
defaults/main.yml

  1. ---
  2. # Registry Settings
  3. cnr_gateway_docker_registry: 'registry.cn-hangzhou.aliyuncs.com'
  4. cnr_gateway_registry_user: ''
  5. cnr_gateway_registry_password: ''
  6. # Environment Specific Settings
  7. cnr_gateway_env: development
  8. cnr_gateway_image: cnr_gateway
  9. cnr_gateway_image_tag: latest
  10. # Host specific Settings
  11. cnr_gateway_confdir: '/srv/appvolumes/cnr_gateway'
  12. cnr_gateway_logdir: '/srv/logs'
  13. cnr_gateway_host_port: ''
  14. cnr_gateway_appport: ''
  15. cnr_gateway_network_mode: "bridge"
  16. cnr_gateway_syslog_url: ''
  17. # Eurka
  18. codemaster_codecamp_app_api_oos_enable: false
  19. # App Setting
  20. cnr_gateway_config_server_port: ""
  21. cnr_gateway_config_eureka_instance_hostname: ""
  22. cnr_gateway_config_apollo_meta: ""

./handlers/main.yml

  1. ---
  2. - name: Restart container
  3. command: /usr/bin/docker restart "{{ cnr_gateway_container_name }}"

./tasks/main.yml

  1. ---
  2. - name: Modify VServer Weight To Zero
  3. connection: local
  4. ali_slb:
  5. alicloud_access_key: '{{ alicloud_access_key }}'
  6. alicloud_secret_key: '{{ alicloud_secret_key }}'
  7. alicloud_region: '{{ cnr_gateway_alicloud_region }}'
  8. vserver_group_id: '{{ cnr_gateway_vserver_group_id }}'
  9. backend_servers:
  10. - ServerId: '{{ instance_id }}'
  11. Port: '{{ cnr_gateway_host_port }}'
  12. Weight: 0
  13. when: cnr_gateway_slb_enable
  14. - name: create log file
  15. file:
  16. path: '{{ cnr_gateway_logdir }}'
  17. owner: root
  18. group: root
  19. mode: 0755
  20. state: directory
  21. - name: Setup application data tree
  22. file:
  23. path: '{{ cnr_gateway_confdir }}'
  24. owner: root
  25. group: root
  26. mode: 0755
  27. state: directory
  28. - name: Setup application data tree
  29. file:
  30. path: '{{ cnr_gateway_confdir }}/log/'
  31. owner: root
  32. group: root
  33. mode: 0757
  34. recurse: yes
  35. state: directory
  36. - name: Setup application data tree
  37. file:
  38. path: '{{ cnr_gateway_confdir }}/log/common'
  39. owner: root
  40. group: root
  41. mode: 0757
  42. recurse: yes
  43. state: directory
  44. - name: Install application configuration
  45. template:
  46. src: 'config.yml.j2'
  47. dest: '{{ cnr_gateway_confdir }}/application-{{ cnr_gateway_env }}.yml'
  48. owner: root
  49. group: root
  50. mode: 0644
  51. notify: Restart container
  52. - name: Login to docker registry
  53. docker_login:
  54. registry: '{{ cnr_gateway_docker_registry }}'
  55. username: '{{ cnr_gateway_registry_user }}'
  56. password: '{{ cnr_gateway_registry_password }}'
  57. - name: Pull initial docker image from registry
  58. docker_image:
  59. name: '{{ cnr_gateway_docker_registry }}/codemaohub/{{ cnr_gateway_image }}:{{ cnr_gateway_image_tag }}'
  60. state: present
  61. - block:
  62. - name: Check if the port exists
  63. wait_for:
  64. port: "{{ cnr_gateway_host_port }}"
  65. state: stopped
  66. delay: 0
  67. timeout: 1
  68. rescue:
  69. - name: Change Application Out Of Service
  70. uri:
  71. url: 'http://127.0.0.1:{{ cnr_gateway_host_port }}/eureka/out_of_service'
  72. method: PUT
  73. register: response
  74. failed_when: "response.status != 200"
  75. - name: Waiting for cache clean
  76. pause:
  77. minutes: 2
  78. when: cnr_gateway_oos_enable
  79. - name: Install, update and start containers
  80. docker_container:
  81. name: '{{ cnr_gateway_container_name }}'
  82. image: '{{ cnr_gateway_docker_registry }}/codemaohub/{{ cnr_gateway_image }}:{{ cnr_gateway_image_tag }}'
  83. restart_policy: 'always'
  84. pull: yes
  85. recreate: yes
  86. state: started
  87. restart: yes
  88. command: "{{ cnr_gateway_start_command }} --spring.profiles.active={{ cnr_gateway_env }}"
  89. ports:
  90. - "{{ cnr_gateway_host_port }}:{{ cnr_gateway_app_port }}"
  91. volumes:
  92. - '{{ cnr_gateway_confdir }}:/usr/src/app/config'
  93. - '{{ cnr_gateway_logdir }}:/localdata'
  94. etc_hosts: "{{ all_etc_hosts }}"
  95. # Use the defaults bridge network
  96. # Mandatory for production!
  97. network_mode: "{{ cnr_gateway_network_mode }}"
  98. - name: Immediate Execution Handlers
  99. meta: flush_handlers
  100. - name: Wait for container to become available
  101. wait_for:
  102. port: '{{ cnr_gateway_host_port }}'
  103. delay: 5
  104. timeout: 45
  105. when: cnr_gateway_healthcheck_enabled
  106. - name: Validating application healthcheck
  107. uri:
  108. url: 'http://{{ cnr_gateway_healthcheck_host }}:{{ cnr_gateway_healthcheck_port }}{{ cnr_gateway_healthcheck_endpoint}}'
  109. method: GET
  110. return_content: true
  111. register: response
  112. retries: 5
  113. delay: 15
  114. until: response is succeeded
  115. failed_when: cnr_gateway_healthcheck_responsestring not in response.content
  116. when: cnr_gateway_healthcheck_enabled
  117. - name: Configure firewall to accept SLB health check
  118. ufw:
  119. rule: allow
  120. port: "{{ cnr_gateway_host_port }}"
  121. proto: tcp
  122. to_ip: "{{ ansible_eth0['ipv4']['address'] }}"
  123. - name: Modify VServer Weight To 100
  124. connection: local
  125. ali_slb:
  126. alicloud_access_key: '{{ alicloud_access_key }}'
  127. alicloud_secret_key: '{{ alicloud_secret_key }}'
  128. alicloud_region: '{{ cnr_gateway_alicloud_region }}'
  129. vserver_group_id: '{{ cnr_gateway_vserver_group_id }}'
  130. backend_servers:
  131. - ServerId: '{{ instance_id }}'
  132. Port: '{{ cnr_gateway_host_port }}'
  133. Weight: 100
  134. when: cnr_gateway_slb_enable

./templates/config.yml.j2

  1. server:
  2. port: {{ cnr_gateway_config_server_port }}
  3. eureka:
  4. client:
  5. service-url:
  6. defaultZone: {{ cnr_gateway_config_eureka_client_service_url }}
  7. instance:
  8. hostname: {{ cnr_gateway_config_eureka_instance_hostname }}
  9. apollo:
  10. meta: {{ cnr_gateway_config_apollo_meta }}