『Ansible 上手指南』

Ansible 上手指南

前言

最近在重构一款命令行工具,使用 golang 重新开发,但需要继续维持原有的命令,同时增加新命令。

在重构的过程中,需要对现命令行工具和原命令行工具的命令输出结果进行比对,确保完全一致(项目要求),命令行工具需要在部署完成系统之后进行使用,每个系统完成时的部署组件又稍微有点差异。所以其实需要在多套服务主机上进行测试。

需要做这些动作:

  • 拷贝一些配置文件到主机上:用户配置、IP和端口文件
  • 安装命令行工具,确保使其在服务主机上可以使用
  • 执行一堆测试命令

按理说,我不断把需要的配置和二进制文件拷贝到主机上进行测试也能完成。

但在使用的过程中存在下面几个问题:

  • 测试发现,结果不对时需要及时修改代码,再次拷贝二进制文件到主机上
  • 主机环境需要多次推倒,重新部署,验证版本更新问题
  • 需要手动一个一个命令的执行
  • 测试有几套主机

看上去手动的方法,有点费劲。

目前我从事的工作就是 PaaS 部署相关的,部署层面的脚本的运行、组件的安装、服务的启动等都是使用 Ansible 来操作。具体的脚本编写由其他同事,我只知道这个东西是干嘛的。没实质性的学习。于是想借这个机会主动学习下 Ansible.

学习之处,差点犯了老问题,即:从头开始看官方文档,而不注重当前需要解决的问题。

因为其实整个 Ansible 的内容体系很多。不注重当前需要解决的问题,会导致你抓不住重点。

意识到后专注在当前需要解决的问题上:

  • 拷贝配置文件和安装脚本到多个主机上
  • 在多个主机上测试命令行工具

Ansible

看了上面的事件背景,你大概知道这个 Ansible 到底是个什么东西。

Ansible 是一个配置管理和应用部署工具,即在管理主机上操作一些命令就能在节点主机上进行相应的动作。由 Python 编写,由模块化组成,即执行动作的实体,在 ansible 上都是靠着相应的模块执行动作,比如拷贝 copy 模块、执行 command 模块、shell 模块、文件 file 模块等。

Ansible 的目标有如下:

  • 自动化部署应用
  • 自动化管理配置
  • 自动化的持续交付
  • 自动化的(AWS)云服务管理。

原理

管理主机从 hosts 里读取主机清单,通过 playbook 按顺序同时对管理的主机进行相应的操作。

如图:

示意图.png
示意图.png

管理主机主要是对主机的定义和配置、编写 playbook(即节点主机的执行动作)。

运行:

1. 命令行

ansible all -m ping 

2. playbook


ansible-playbook example.yml

主机清单

编辑文件:/etc/ansible/hosts

即:定义主机名称,变量等

主机的变量包括什么: 主机的执行用户、连接端口、密码等

类似于 ini 格式的文件

[test-new-cli]
10.62.60.72

[test-old-cli]
10.62.62.88

上面的例子:将两个主机的分为两组:test-new-clitest-old-cli

主机的变量有这么些:

  • ansible_ssh_host
    将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.

  • ansible_ssh_port
    ssh端口号.如果不是默认的端口号,通过此变量设置.

  • ansible_ssh_user
    默认的 ssh 用户名

  • ansible_ssh_pass
    ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)

  • ansible_sudo_pass
    sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)

  • ansible_sudo_exe (new in version 1.8)
    sudo 命令路径(适用于1.8及以上版本)

  • ansible_connection
    与主机的连接类型.比如:local, ssh 或者 paramiko.

  • ansible_ssh_private_key_file
    ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.

  • ansible_shell_type
    目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.

  • ansible_python_interpreter
    目标主机的 python 路径.

看不懂怎么用:

举个例子,你想连接主机 192.168.100.100 , 切换到 root 用户下执行相应的操作。

如果你直接ssh username@192.168.100.100 会要求你输入用户名和密码。

假如我编辑主机清单使得自己不需要输入用户名密码,怎么操作?

[test-new-cli]
example ansible_ssh_host=192.168.100.100 ansible_ssh_user=username ansible_ssh_pass=root

即配置好192.168.100.100 的主机别名为example, 主机的用户名和密码为:username/root

Yaml

包含三种类型:

  • 键值对:key: value
  • 数组
  • 纯量:整型、字符串、布尔型

这个很好理解:如果你熟悉Python, 这三种类型就相当于:map, list, 变量

如果你熟悉golang, 这三种类型就相当于: map, 数组, 变量

示例:

---
- name: "execute command nodepool node list {{item.name}}"
  shell: "{{item.cli}} nodepool node list {{item.id}}"
  register: result
- name: show result
  debug:
    msg: "{{result.stdout_lines}}"
  with_items:
    - { name: "new-cli", cli: "new-cli", id: "1" }
    - { name: "old-cli", cli: "old-cli", id: "1" }

模块

Ad-doc

ansible 命令行式,适合执行单条命令。

# 操作 192.168.100.100 主机,看管理主机是否和192.168.100.100的主机连通

ansible example -m ping

# 操作 192.168.100.100 主机,拷贝管理主机下的/root/opcli/conf 文件至节点主机/etc/opcli/conf 下
ansible test-new-cli -m copy -a="src=/root/opcli/conf dest=/etc/opcli/conf"

  • m: 模块
  • a: 接参数

可以看出适合执行单条命令

Patterns

假如你的节点主机分组很多了,Ad-hoc 如何选择特定特征的节点主机分组呢?

使用类正则表达式。

比如触发所有节点主机进行动作:

ansible all -m ping
ansible * -m ping

两者等价,都是选择所有的节点主机

示例:

1. 主机别名或者IP
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*

2. 一个或多个groups
webservers
webservers:dbservers

3. 排除一个组
webservers:!phoenix 
# 隶属 webservers 组但同时不在 phoenix组

4. 两个组的交集
webservers:&staging
# 同时隶属于 webservers 和 staging 组
5. 列表
webservers[0]
webservers[0-25]

6. 其他

有什么需求,看官方文档吧。

Playbook

编写 yaml 文件,适合执行多步操作的复杂操作。可以看成是Ad-doc 命令的集合。甚至可以看成是一门编程语言。

执行:ansible-playbook example.yml

按照 example.yml 文件里的任务集合按步执行任务。

示例

命令示例,仅举几例,有带参数、有没带参数的。

我们最终的目标是:在节点主机上执行这些命令进行比对两者结果。

目录:

demo-for-ansible:
--- nodepool:
    nodepool-list.yml
    nodepool-node-list.yml
--- node:
    node-list.yml
    node-show.yml
--- task/task-list.yml
--- main.yml



新版本:

命令 说明
command-cli nodepool list 查询资源池
command-cli nodepool node list <id> 查询资源池节点
command-cli node list 查询节点
command-cli node show <node id> 查询某个节点
command-cli task list 查询部署任务

...

旧版本:

命令 说明
old-cli nodepool list 查询资源池
old-cli nodepool node list <id> 查询资源池节点
old-cli node list 查询节点
old-cli node show <node id> 查询某个节点
old-cli task list 查询部署任务

...

第一步:编写主机清单

/etc/ansible/hosts

[test_client]
192.168.100.100 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh
192.168.100.101 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh
192.168.100.102 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh

定义主机连接类型、用户名、密码

第二步:编写 yaml 文件

主要动作:

  • 在节点主机上创建两个文件夹: /etc/client/conf/et/client/commands
  • 拷贝管理主机目录:/etc/client/conf 文件至节点主机: /etc/client/conf
  • 拷贝管理主机二进制文件:/root/gosrc/src/client/command-cli 至节点主机 /etc/client/commands
  • 软连接节点主机二进制文件:/etc/client/commands/command-cli 至节点主机 /usr/bin/command-cli
  • 执行上表中查询命令:nodepool, node, task

main.yml

---
- hosts: test_client
  remote_user: root
  become: yes
  become_user: root
  tasks:
    # 在节点主机上创建目录:/etc/client/conf
    - name: create /etc/client/conf /etc/client/commands
      file:
        path: "/etc/client/{{item}}"
        owner: root
        group: root
        mode: 0755
        state: directory
      with_items:
      - "conf"
      - "commands"
    # 软连接到 /usr/bin/command-cli
    - name: link  /etc/client/commands
      file: src="/ect/client/commands" dest="/usr/bin/command-cli" state=link

    # 拷贝管理主机配置文件/etc/client/conf和二进制文件至 /etc/client/conf, /etc/client/commands
    - name: copy /etc/client/conf
      copy: src="{{ itme.src }}" dest="{{ item.dest }}" owner=root group=root mode=0644
      with_items:
      - { src: "/etc/client/conf", dest: "/etc/client/conf" }
      - { src: "/root/gosrc/src/client/command-cli", dest: "/etc/client/commands"}

    # nodePool list
    - include_tasks: "/nodepool/nodepool-list.yml"
      with_items:
      - { client: "new client", name: "command-cli"}
      - { client: "old client", name: "old-cli"}

    # nodePool node list <id>
    - include_tasks: "/nodepool/nodepool-node-list.yml"
      with_items:
      - { id: "1", client: "new client", name: "command-cli"}
      - { id: "1", client: "old client", name: "old-cli"}

    # node list
    - include_tasks: "node/node-list.yml"
      with_items:
      - { client: "new client", name: "command-cli"}
      - { client: "old client", name: "old-cli"}

    # node show <id>
    - include_tasks: "node/node-show.yml"
      with_items:
      - { client: "new client", name: "command-cli", id: 1}
      - { client: "old client", name: "old-cli", id: 1}

    #  task list
    - include_tasks: "task/task-list.yml"
      with_items:
      - { client: "new client", name: "command-cli"}
      - { client: "old client", name: "old-cli"}



task-list.yml

---
- name: "execute command task list by {{ item.client}}"
  shell: "{{item.name}} task list"
  register: result
- name: show result
  debug:
    msg: "{{result.stdout_lines}}"

第三步: 检查语法

两种方法

ansible-playbook main.yml --syntax-check

先安装 pip install ansible-lint

ansible-lint main.yml

第四步: 执行

ansible-playbook main.yml

整个的编写流程大概是这样。核心是编写 yml 文件,调用 ansible 支持的各种模块完成任务。

下一步

  1. 熟悉 playbook
  2. 熟悉 ansible 模块
  3. 熟悉 ansible api

关注你当前需要解决的问题,切入学习,事半功倍。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容