ansible入门

1,205 阅读7分钟

Ansible入门.png

简介

是一种实现配置自动化的自动化运维工具,具有批量运行命令等功能。在集群环境中,可使用ansible命令对各节点进行批量操作,如对防火墙统一配置、集群间文件传输拷贝、集群各节点性能参数统计等操作。使用ansible可以实现多个对主机执行自动化任务操作,使用yaml配置文件。

简单一句话来介绍的话是无主无从架构,开箱即用,使用ssh协议

ansible配置自动化场景

可以帮助企业在大量服务器存在的情况下,快速实现应用部署、软件配置等一系列操作

ansible配置自动化优点

  • 提高配置效率
  • 提高配置的准确性
  • 降低人工参与度

ansible解决了什么问题

  • 自动化:避免运维工作中重复的工作
  • 模块化:手写shell,甚至手写python,要做到模块化和标准化,太困难了。ansible将大部分运维工作都抽象并标准化成一个个模块(module)。
  • 标准化:所有的模块的使用方式都是一样的,减少学习成本
  • 幂等的:采用声明式的描述方式,无论被执行了多少次结果都应该是我们所声明的

ansible可以用来做哪些事情

  • 上传文件到服务器
  • 给服务器安装,升级服务
  • 自动在远程服务器上执行脚本
  • 批量管理大规模主机
  • ...

ansible架构

工作原理如下图所示:

image.png

主要分为两大块:

  1. 主机
  2. ansible(模块;主机清单,即主机在主机清单里面才可进行操作;ssh;playbook)

ansible相关术语

  • 控制节点(Control node):指安装了ansible的主机,也叫ansible服务器端管理机。 ansible控制节点主要用于发布运行任务,执行控制命令。ansible的程序都安装在控制节点上,控制节点需要安装Python和ansible所需的各种依赖库。注意:目前ansible还不能安装在Windows下。

  • 受控节点(Managed nodes):也叫客户机,即想用ansible执行任务的客户服务器。

  • 清单(Inventory):受控节点的列表,即所有要管理的主机列表。

  • host文件:清单列表通常保存在一个名为host文件中。在host文件中,可以使用IP地址或者主机名来表示具体的管理主机和认证信息,并可以根据主机的用户进行分组。缺省文件:/etc/ansible/hosts,可以通过-i指定自定义的host文件。

  • 模块(Modules):模块是ansible执行特定任务的代码块。比如:添加用户,上传文件和对客户机执行ping操作等。ansible目前默认自带450多个模块。

  • 任务(Task):是ansible客户机上执行的操作。

  • 剧本(Playbook):是利用YAML标记语言编写的可重复执行的任务的列表,playbook实现任务的更便捷的读写和贡献。

  • 角色(roles):角色是ansible1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。

主机清单作用

ansible controller在对主机进行操作时,仅认主机清单中定义的主机列表,即从主机清单中读取到主机列表时,才可进行配置。

  • 用于ansible controller配置主机时读取主机列表
  • 实现主机分组

主机清单中如何写入

# 方法一:直接在主机清单文件中写入主机ip地址或主机名(需要能够解析)
192.168.216.28
或
web1

# 方法二:在主机清单文件中添加主机分组,然后把主机ip和主机名写入分组内即可
[webgroup]
192.168.216.28

或
[webgroup]
web1

ansible安装

安装步骤

首先登陆远程服务器

  1. 安装epel-release yum源
yum -y install epel-release
  1. 安装ansible
yum -y install ansible
  1. 验证是否安装成功
rpm -qa | grep ansible
或
ansible

ansible相关文件

配置文件

  • /etc/ansible/ansible.cfg: 主配置文件
  • /etc/ansible/hosts: 主机清单
  • /etc/ansible/roles/: 存放角色目录

程序

  • /usr/bin/ansible: 主程序

  • /usr/bin/ansible-doc: 查看配置文档,模块功能查看工具

  • /usr/bin/ansible-galaxy: 下载上传优秀代码或Roles模块官方平台

  • /usr/bin/ansible-playbook: 定制自动化任务

  • /usr/bin/ansible-vault: 文件加密工具

  • /usr/bin/ansible-console: 基于console界面与用户交互的执行工具

ansible中hosts常见参数

ansible_ssh_host  将要连接的远程主机名
ansible_ssh_port  ssh端口号
ansible_ssh_user  默认的ssh用户名
ansible_ssh_pass  ssh 密码(这种方式并不安全, 强烈建议使用 --ask-pass或ssh密钥)
ansible_sudo_pass udo 密码(这种方式并不安全, 强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe sudo命令路径(适用于1.8及以上版本)
ansible_connection 与主机的连接类型.比如:local, ssh 或者 paramiko. ansible 1.2以前默认使用paramiko.1.2 以后默认使用'smart', 'smart' 方式会根据是否支持ControlPersist, 来判断'ssh'方式是否可行.
ansible_ssh_private_key_file ssh使用的私钥文件.适用于有多个密钥
ansible_shell_type 目标系统的shell类型,默认情况下,命令的执行使用'sh' 语法, 可设置为 'csh''fish'

ansible任务执行模式

使用ansible有两种执行模式:ad-hocplaybook,即使用命令行执行简单的命令方式和通过配置文件批量执行多种命令的方式。即前者可以解决一些简单的任务, 后者解决较复杂的任务

下面详细说下这两种模式的区别:

  1. ad-hoc模式:使用单个模块,支持批量执行单条命令,相当于在bash中执行一句shell命令。
  2. playbook模式:ansible主要的管理方式,通过多个task的集合完成一类功能,可理解为多个ad-hoc的配置文件

ad-hoc模式使用场景

执行命令功能简单,一条命令即可完成;需要查看各节点数据

playbook模式使用场景

需执行多个功能,如需先打包文件,再同步到某一节点上,playbook通过多个task集合完成一类功能,如数据的批量备份等;可以把playbook理解为一个将多条ad-hoc操作集合在一起的配置文件

ad-hoc模式写法

ansible <host-pattern> [-f forks] [-m module_name] [-a args]

# host-pattern为需要远程执行的主机信息,通常可将需远程访问的host集合放在一个文件里,通过-i命令读取,具体我们看下面这个例子:-i指定读取hostlist中的host集合,all表示取全部

例子:
ansible -i /opt/xxx/hostlist all

ansible-playbook写法

核心元素包括下面几个

  1. Hosts :执行的远程主机列表
  2. Tasks :任务集,将需要执行的多个任务在此罗列,如shell模块、archive模块
  3. Varniables :自定义变量,playbook中进行调用
  4. Templates 模板:即使用模板语法的文件,比如配置文件等
  5. Handlers 和notity结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
  6. tags 标签,指定某条任务执行,用于选择运行playbook中的部分代码

语法

# 参数-e传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量
ansible-playbook ansible.yaml -e "HOST=${HOST}" -i ./hosts

playbook详细语法如下:

ansible-playbook [options] playbook.yml [playbook2 ...]

ansible常用的任务模块

命令模块command

-m默认模块,可执行基本的shell命令,不支持管道、通配符、脚本等

# hostname -i 显示主机的IP地址(组)
ansible -i /opt/xxx/hostlist all  -m command -a "hostname -i"

命令模块shell

相对于command的局限性,使用shell能够支持管道、通配符、脚本等,执行更多的命令

ansible -i /opt/xx/hostlist all -b -m shell  -a "sar -u 1 5|awk 'END{print}'"

文件模块copy

用于将当前主机上的信息传送到远程主机(当前同步到远程)

ansible -i /opt/xx/hostlist all  -m copy -a "src=/var/log/sa dest=/tmp/gly/sarinfo"

#参数说明
src 指定将本地管理主机的什么数据信息进行远程复制
backup #no|yes 默认数据复制到远程主机,会覆盖原有文件(yes将源文件进行备份)
content 在文件中添加信息
dest 将数据复制到远程节点的路径信息(必须)
group 文件数据复制到远程主机,设置文件属组用户信息
mode 文件数据复制到远程主机,设置数据的权限
owner 文件数据复制到远程主机,设置文件属主用户信息
remote_src no/yes,如果设置为yes,表示将远程主机上的数据进行移动操作如果设置为no,表示将管理主机上的数据进行分发操作

文件模块fetch

用于从远程主机获取文件(远程同步到当前)

ansible -i /opt/xxx/hostlist all -m fetch -a "src=/var/log/sa dest=/tmp/gly/sarinfo"

#参数说明
src  要获取的远程系统上的文件,必须是文件,而不是目录(必须)
dest 用于保存文件的目录

压缩/解压模块archive/unarchive

用于对指定目录的压缩/解压操作

ansible -i /opt/xx/hostlist all -m archive -a "path=/var/log/sa/sa* format=tar dest=/tmp/'hostname -i'.tar"

#参数说明
path 文件要压缩的远程绝对路径列表(必需)。
dest 目标路径与文件名
format 压缩包类型

file模块

设置文件夹的权限是非常常见的操作,所以就有了file任务,可以对远程服务器上的文件进行操作。创建删除文件,修改文件权限等。

  • path:执行文件、目录的路径
  • recurse:递归设置文件属性,只对目录有效
  • group:定义文件、目录的属组
  • mode:定义文件、目录的权限
  • owner:定义文件、目录的所有者
  • src:要被链接的源文件路径,只应用与state为link的情况
  • dest:被链接到的路径,只应用于state为link的情况
  • force:在两种情况下会强制创建软链接,一种是源文件不存在但之后会建立的情况;一种是目标软链接已经存在,需要先取消之前的软链接,然后创建新的软链接,默认值 no。
  tasks:
    - name: delete dir
      file:
        path: "{{ DEST_PATH }}"
        state: absent

state属性的值可以为:

  • absent:不存在。可以理解为删除该文件或文件夹。
  • directory:文件夹。如果该文件夹不存在,则创建。
  • file:文件。如果不存在,则创建。
  • touch:与linux的touch实现相同的效果

ansible常见的参数如下所示

参数含义
-b--become:特权方式运行命令
-m指定ansible命令执行的任务模块,默认使用command模块。常用的复制(copy)、解压/压缩文件(tar)等命令,ansible都有提供对应的模块去执行,使用时只需提供参数即可,不需要再在shell中使用copy、tar等命令
-a--args:制定模块所需的参数
-uREMOTE_USER, --user=REMOTE_USER #ssh连接的用户名
-h--help显示帮助内容
-v--verbose显示ansible-doc的版本号查看模块列表
-l--list列出可用的模块 library:即/usr/share/ansible,指向存放ansible模块的目录,支持多个目录方式,只要用冒号:隔开就可以
-s--sudo #sudo到root用户,相当于Linux系统下的sudo命令
-k--ask-pass ssh登录认证密码
-tTIMEOUT, --timeout=TIMEOUT ssh连接超时,默认10秒
-c--check 指定该参数后,执行playbook文件不会真正去执行,而是模拟执行一遍,然后输出本次执行会对远程主机造成的修改
-k--ask-pass ssh登录认证密码
-eEXTRA_VARS, --extra-vars=EXTRA_VARS 设置额外的变量如:key=value形式或者YAML or JSON,以空格分隔变量,或用多个-e -f FORKS, --forks=FORKS
-iinventory, --inventory-file=INVENTORY 指定hosts文件路径,默认 default=/etc/ansible/hosts
-fforks:并发连接数,默认为5
-llog_path:/var/log/ansible.log,指定一个存储ansible日志的文件(默认不记录日志)

示例:自动化部署

ansible配合gitlab-ci实现Node服务自动化部署,Node服务在docker镜像中运行

步骤

  1. Gitlab中配置CI变量

image.png

2..gitlab-ci.yml文件编写

stages:
  - dev_deploy
  - master_deploy

master_deploy:
  stage: master_deploy
  image: ansible镜像地址
  script:
    - echo \"${HOST}\" ansible_ssh_user=\"${USER}\" ansible_ssh_pass=\"${PASS}\" ansible_ssh_host=\"${HOST}\" > hosts
    - echo ansible-playbook ansible.yaml -e hosts=${HOST} -i ./hosts
    - ansible-playbook ansible.yaml -e "HOST=${HOST}  DEST_PATH=${ROOT_PATH}/${CI_PROJECT_NAME} -i ./hosts
    - git checkout master && yarn
    - rm -f hosts
  only:
    - master
  tags:
    - k8s

dev_deploy:
  stage: dev_deploy
  image: ansible镜像地址
  script:
    - echo \"${HOST}\" ansible_ssh_user=\"${USER}\" ansible_ssh_pass=\"${PASS}\" ansible_ssh_host=\"${HOST}\" > hosts
    - echo ansible-playbook ansible.yaml -e hosts=${HOST} -i ./hosts
    - ansible-playbook ansible.yaml -e "HOST=${HOST}  DEST_PATH=${ROOT_PATH}/${CI_PROJECT_NAME}" -i ./hosts
    - git checkout dev && yarn
    - rm -f hosts
  only:
    - dev
  tags:
    - k8s
  1. ansible.yaml文件编写
# cd到server目录,拉取最新代码,docker重启
- name: deploy
  hosts: "{{ HOST }}"
  become_user: root
  become: yes
  tasks: # 任务
    - name: git pull
      command: git pull
      args:
        chdir: 服务器对应的项目目录
      become_user: root
      become: yes
    - name: docker restart container
      command: docker restart docker容器(node服务的docker容器)
      args:
        chdir: 服务器对应的项目目录
      become_user: root
      become: yes

遇到的问题

问题1: CI执行时报yarn任务执行失败

排查: ansible文件中之前是如下形式写的,尝试在远程服务器上对应目录下执行yarn,发现报node版本不匹配

# cd到server目录,拉取最新代码,docker重启
- name: deploy
  hosts: "{{ HOST }}"
  become_user: root
  become: yes
  tasks: # 任务
    - name: yarn
      command: yarn
      args:
        chdir: 服务器对应的项目目录
    ...

解决:把ansible中yarn任务去掉,放到docker-compose.yml中执行,即在docker容器中执行yarn,而不是在服务器中执行

# 之前command是yarn,如今改为yarn && yarn start
version: '3.0'
services: # 服务列表
  node-server:  # node服务
    container_name: node-server-container # 容器名称
    image: node:14.15.0
    ports:  # 暴露的端口
      - "7007:5088"
    volumes:
      - .:/data
    working_dir: /data
    depends_on: # web服务依靠mysql要先等mysql启动
      - mysql
    restart: on-failure:5 # 自动重启,失败的话重启5次后停止
    command: yarn && yarn start # 覆盖容器启动后默认执行的命令

参考网址

getansible.com/begin/ansib…模块)

ansible-tran.readthedocs.io/en/latest/d…(中文文档)

docs.ansible.com/ (官方文档)