金鱼哥RHCA回忆录:DO447协调滚动更新--管理滚动更新

本文涉及的产品
网络型负载均衡 NLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
简介: 第五章 协调滚动更新--管理滚动更新
🎹 个人简介:大家好,我是 金鱼哥,CSDN运维领域新星创作者,华为云·云享专家,阿里云社区·专家博主
📚个人资质: CCNA、HCNP、CSNA(网络分析师),软考初级、中级网络工程师、RHCSA、RHCE、RHCA、RHCI、ITIL😜
💬格言:努力不一定成功,但要想成功就必须努力🔥

📜5.2.1 概述

Ansible有几个特性可以支持滚动更新,这是一种将部署堆叠到一批服务器上的策略。使用此策略,部署基础设施更新时没有停机时间。

当出现不可预见的问题时,Ansible可以停止部署,任何错误都可以限制在特定批处理中的那些服务器上。有了测试和监视,您可以将剧本任务配置为:

  • 回滚受影响的批量主机的配置。
  • 隔离受影响的主机以分析失败的部署。
  • 向涉众发送部署通知。

📜5.2.2 控制批量大小

默认情况下,Ansible会在开始执行下一个任务之前,为该剧本中的所有主机运行一个任务。如果一个任务失败,那么所有的主机将只是在任务的一半。这可能意味着您的所有主机都不能正常工作,这可能会导致停机。

理想情况下,在开始下一批主机之前,可以在整个过程中处理一些主机。如果太多主机失败,那么您可以中止整个剧本。在下面的段落中,您将配置您的剧本来做到这一点。


📑设置固定批量大小

如果要通过剧本批量处理主机,请在剧本中使用serial关键字。serial关键字指定每个批处理中应该有多少台主机。在开始下一批之前,Ansible会一直处理每一批主机。如果当前批处理的所有主机都失败。整个剧本被中止,Ansible不启动下一批。

---
- name: Update Webservers
  hosts: web_servers
  serial: 2

在本例中,serial关键字指示Ansible分批处理web_servers主机组中的两台主机。如果剧本没有错误地执行,则剧本将以新一批重复执行。

这一过程将继续进行,直到处理完剧本中的所有主机。因此,如果剧本中的主机总数不能除以批量大小,最后一批主机可能比serial关键字指示的值更少。在前面的示例中,如果web服务器的总数为奇数,则最后一批包含一台主机。

记住,如果使用serial关键字的整数,那么随着主机数量的增加,完成剧本所需的批数也会增加。当串行值为2时,200台主机的主机组需要100批完成,20台主机的主机组需要10批完成。


📑设置批量大小为百分比

可以为serial关键字的值指定一个百分比:

---
- name: Update Webservers
  hosts: web_servers
  serial: 25%

如果您指定了一个百分比,那么该百分比的主机将在每批处理中被处理。如果serial的值为25%,则无论web_servers组中包含20台主机还是200台主机,都需要4批完成所有主机的play。

Ansible将该百分比应用于主机组中主机的总数量。如果结果值不是主机的整数数量,那么该值将被截断(四舍五入)到最接近的整数。其余的主机以较小的批处理运行。批处理大小不能为零主机。如果截断的值为零,Ansible将批处理大小更改为一个主机。

image-20220417183328684


📑将批量大小设置为可更改

您可以在剧本执行时更改批处理大小。例如,您可以在一台主机上批量测试一个剧本,如果该主机失败,那么整个剧本将中止。但是,如果在一个主机上成功运行,您可以将批处理规模增加到10%的主机,然后是50%的管理主机,然后是其余的管理主机。

---
- name: Update Webservers
  hosts: web_servers
  serial:
    - 1
    - 10%
    - 100%

第一批只包含一个主机。

第二批包含web_servers主机组中主机总数的10%。Ansible根据前面讨论的规则计算实际值。

第三批包含所有剩余未处理的主机。这使得Ansible能够有效地处理所有剩余的主机。

如果在serial关键字最后一个条目对应的最后一批后还有未处理的主机,则重复最后一批大小,直到所有主机都处理完毕。考虑下面的操作,它对一个有100台主机的web_servers主机组执行:

---
- name: Update Webservers
  hosts: web_servers
  serial:
    - 1
    - 10%
    - 25%

第一批包含1台主机,第二批包含10台主机(占100台主机的10%)。第三批处理25个主机(占100的25%),剩下64个未处理主机(1 + 10 + 25处理)。Ansible以25台主机(占100台主机的25%)的批量规模继续执行play,直到剩余不到25台未处理主机为止。以剩余的14台主机为例最终批次(1 + 10 + 25 + 25 + 25 + 14 = 100)。


📜5.2.3 中止剧本

既然您已经知道了如何逐步增加批处理大小,那么您必须了解在太多主机失败时如何中止运行。

默认情况下,Ansible会尝试让尽可能多的主机来完成剧本。如果某个主机的任务失败,则该任务将被从剧本中删除,但Ansible将继续为其他主机运行剧本中剩余的任务。只有当所有主机都失败时,剧本执行才会停止。

但是,如果使用serial关键字将主机组织成批量,那么如果当前批处理中的所有主机都失败,Ansible将停止所有剩余主机的执行,而不仅仅是当前批处理中的剩余主机。如果某批处理中所有主机都失败,导致该play停止执行,则不会启动下批处理。

Ansible在ansible_play_batch变量中保存了每个批处理的活动服务器列表。任何任务失败的主机都会从ansible_play_batch列表中删除。Ansible在每个任务之后更新这个列表。

考虑以下假设的脚本,它针对一个拥有100台主机的web_servers主机组执行:

image-20220417183505993

如果99个web服务器在第一个任务中失败,但有一个主机成功,Ansible继续执行第二个任务。当Ansible执行第二个任务时,Ansible只为之前成功的一个主机执行任务。

如果您使用serial关键字,那么只有在当前批处理中没有出现故障的情况下,playbook执行才会继续。考虑一下对假设剧本的修改:

image-20220417183526457

如果第一批包含一个成功的主机和一个失败的主机,那么批处理完成,Ansible继续处理第二个批处理。如果第二批处理中的两台主机都在某个任务上失败,那么Ansible将终止整个任务,不再开始任何批处理。

在这个场景中,在剧本执行之后:

  • 一台主机成功地完成了剧本。
  • 可能有三个主机处于错误状态。
  • 其余的主机保持不变。

📑指定失败比例

默认情况下,Ansible只有在所有主机都失败时才会停止执行。但是,如果清单中超过一定比例的主机失败,即使没有整个批处理失败,您也可能希望终止操作。也有可能“快速失败”,并在任何任务失败时中止剧本。

通过添加max_fail_percentage关键字来改变Ansible的失败行为。当批处理中失败的主机数量超过这个百分比时,Ansible会停止playbook的执行。

考虑以下假设的脚本,它针对包含100台主机的web_servers主机组执行:

image-20220417183631833

第一批包含两台主机。因为2的30%是0.6,单个主机故障会导致执行停止。

如果第一批主机都成功,则Ansible继续处理第二批10台主机。因为10的30%是3。超过3个主机故障必然导致Ansible停止playbook的执行。如果有三个或更少的主机在第二批中出现错误,Ansible将继续进行第三批。

要实现“快速失败”策略,将max_fail_percentage设置为零。


📑重要:

总结Ansible的失败行为:

  • 如果不设置“serial”关键字和“max_fail_percentage”,则批量运行所有主机。如果所有主机都失败,则执行失败。
  • 如果设置了“serial”关键字,则多批次运行主机,如果所有主机都失败,则执行失败。
  • 如果设置了max_fail_percentage关键字,则如果超过该百分比的主机在批处理中失败,则执行失败。

如果play失败了,所有剩余的play都将被取消。


📜5.2.4 运行一个任务一次

某些时候,我们希望某个task只执行一次,即使它被绑定到了多个主机上。例如在一个负载均衡器后面有多台应用服务器,我们希望执行一个数据库迁移,只需要在一个应用服务器上执行操作即可。

为此,向任务添加run_once关键字,其值为布尔值true(或yes)。

- name: Reactivate Hosts
  shell: /sbin/activate.sh {{ active_hosts_string }}
  run_once: yes
  delegate_to: monitor.example.com
  vars:
    active_hosts_string: "{{ ansible_play_batch | join(' ')}}"

此任务运行一次,并在monitor.example.com执行。该任务使用active_hosts_ string变量将活动主机列表作为命令行参数传递给激活脚本。该变量仅包含当前批处理中已成功完成前面所有任务的主机。

注意:设置run_once: yes关键字将导致每批执行一次任务。如果某个剧本中所有主机只需要执行一次任务,且该剧本有多个批量执行,则可以在该任务中添加以下条件:

when: inventory_hostname == ansible_play_hosts[0]

这个条件只对剧本中的第一个主机运行任务。


📜5.2.5 课本练习

[student@workstation ~]$ lab update-management start

📑拉取实验代码

[student@workstation ~]$ cd git-repos/
[student@workstation git-repos]$ git clone http://git.lab.example.com:8081/git/update-management.git
[student@workstation git-repos]$ cd update-management

📑执行剧本。

# 部署一个前端负载均衡器和一组后端web服务器。
[student@workstation update-management]$ ansible-playbook site.yml
[student@workstation update-management]$ curl servera
This is serverb. (version v1.0)
[student@workstation update-management]$ curl servera
This is serverc. (version v1.0)
[student@workstation update-management]$ curl servera
This is serverd. (version v1.0)
[student@workstation update-management]$ curl servera
This is servere. (version v1.0)
[student@workstation update-management]$ curl servera
This is serverf. (version v1.0)

📑查看测试脚本并执行

[student@workstation update-management]$ cat issue_requests.sh 
#!/bin/bash
SERVER=servera.lab.example.com
WAIT_TIME_SECS=0.5
LOG_FILE=curl_output.log

rm -f $LOG_FILE

while true; do
  #Print curl response to stdout and also write to log file.
  curl -s $SERVER | tee -a $LOG_FILE

  sleep $WAIT_TIME_SECS
done
[student@workstation update-management]$ chmod +x issue_requests.sh
[student@workstation update-management]$ ./issue_requests.sh
This is serverb. (version v1.0)
This is serverc. (version v1.0)
This is serverd. (version v1.0)
This is servere. (version v1.0)
This is serverf. (version v1.0)
This is serverb. (version v1.0)
This is serverc. (version v1.0)
This is serverd. (version v1.0)
This is servere. (version v1.0)
This is serverf. (version v1.0)
^C

📑查看可滚动更新的剧本

[student@workstation update-management]$ cat update_webapp.yml 
---
- hosts: web_servers
  serial:
    - 1
    - 25%
    - 100%
# 关键字serial表示该play中的任务分三批处理。
# 第一批为1台主机。在此批处理完成后,仍有4台主机需要处理。
# 第二批包含1台主机,因为25%的主机组大小是1.25,所以被截断为1。
# 第三批处理中有3台主机,因为100%的主机组大小为5,只有3台主机未处理。

  pre_tasks:
    - name: Remove web server from service during the update
      haproxy:
        state: disabled
        backend: app
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ item }}"
      with_items: "{{ groups['lb_servers'] }}"
# 在playbook更新每个服务器上的web应用程序之前,haproxy模块会禁用所有负载均衡器中的服务器。通过这项任务,外部客户端不会暴露在应用程序部署后发现的错误中。

  roles:
  - role: webapp
# webapp角色部署驻留在Git存储库中的web应用程序。webapp_repo变量指定了web应用程序Git存储库的URL。webapp_version变量指定应用程序存储库中的分支或版本tag。这些变量在group_vars/web_servers/webapp.yml文件定义。
# cat group_vars/web_servers/webapp.yml 
# webapp_repo: http://git.lab.example.com:8081/git/simple-webapp.git
# webapp_version: v1.0

  post_tasks:
    # Firewall rules dictate that requests to backend web
    # servers must originate from a load balancer.
    - name: Smoke Test - Ensure HTTP 200 OK
      uri:
        url: "http://{{ inventory_hostname }}:{{ apache_port }}"
        status_code: 200
      delegate_to: "{{ groups['lb_servers'][0] }}"
      become: no
# 在剧本部署web应用程序之后,烟雾测试确保每个后端web服务器都响应一个200 HTTP状态代码。每个web服务器上的防火墙规则只允许来自负载均衡器的web请求,所以所有冒烟测试都被委派给负载均衡器。

    # If the test fails, servers are not re-enabled
    # in the load balancers, and the update process halts.
    - name: Enable healthy server in load balancers
      haproxy:
        state: enabled
        backend: app
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ item }}"
      with_items: "{{ groups['lb_servers'] }}"
# 如果服务器的冒烟测试失败,则该服务器的进一步处理将停止,并且不会在负载均衡器中重新启用web服务器。当冒烟测试通过时,第二个任务启用负载均衡器中的服务器。

📑尝试使用新版本号执行

[student@workstation update-management]$ ansible-playbook update_webapp.yml -e webapp_version=v1.1.0

剧本会失败。
监视issue_requests.sh脚本的输出。
从外部客户机的角度来看,负载均衡器继续提供web应用程序v1.0版本的响应。但是,来自其中一个服务器的响应停止出现在输出中。

📑拉取代码进行排错分析

[student@workstation update-management]$ cd ~/git-repos
[student@workstation git-repos]$ git clone http://git.lab.example.com:8081/git/simple-webapp.git
[student@workstation git-repos]$ cd simple-webapp
[student@workstation simple-webapp]$ git checkout v1.1.0
[student@workstation simple-webapp]$ ls
index.php

[student@workstation simple-webapp]$ cat index.php 
<?php
This is {{ ansible_hostname }}. (version {{ webapp_version}})
?>

# 正确的,应该如下所示,因此,v1.1.0版本是有问题的。
[student@workstation simple-webapp]$ cat index.php 
<?php
echo "This is {{ ansible_hostname }}. (version {{ webapp_version}})\n"
?>

📑进行新版本更新

# 假设已修复的版本为 v1.1.1(课本环境已为我们准备)
[student@workstation update-management]$ ansible-playbook update_webapp.yml -e webapp_version=v1.1.1
# 监视issue_requests.sh脚本的输出。

📑清除实验

[student@workstation ~]$ lab update-management finish

📚章节实验

[student@workstation ~]$ lab update-review start

📑拉取实验代码

[student@workstation ~]$ cd /home/student/git-repos/
[student@workstation git-repos]$ git clone http://git.lab.example.com:8081/git/update-review.git
[student@workstation update-review]$ cd update-review

📑执行剧本

[student@workstation update-review]$ ansible-playbook site.yml

📑按要求编写剧本

[student@workstation update-review]$ vim update_webapp.yml
---
- name: Upgrade Web Application
  hosts: web_servers
  #TODO: Configure max allowable failures
  #TODO: Configure batches
  max_fail_percentage: 0
  serial:
    - 5%
    - 35%
    - 100%
  #TODO: Add a pre-task to disable each web server
  pre_tasks:
    - name: Remove web server from service during the update
      haproxy:
        state: disabled
        backend: app
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ groups['lb_servers'][0] }}"

  roles:
  - role: webapp

  post_tasks:
    - name: Smoke Test - Ensure HTTP 200 OK
      uri:
        url: "http://{{ inventory_hostname }}:{{ apache_port }}"
        status_code: 200
      become: no
      delegate_to: "{{ groups['lb_servers'][0] }}"

    # TODO: Add a post-task to re-enable each web server
    - name: Enable healthy server in load balancers
      haproxy:
        state: enabled
        backend: app
        host: "{{ inventory_hostname }}"
      delegate_to: "{{ groups['lb_servers'][0] }}"

📑执行剧本

[student@workstation update-review]$ ansible-playbook update_webapp.yml

📑上传代码

[student@workstation update-review]$ git add . 
[student@workstation update-review]$ git commit -m "Rolling updates"
[student@workstation update-review]$ git push

📑评分并清除实验

[student@workstation ~]$ lab update-review grade
[student@workstation ~]$ lab update-review finish

💡总结

RHCA认证需要经历5门的学习与考试,还是需要花不少时间去学习与备考的,好好加油,可以噶🤪。

以上就是【金鱼哥】对 第五章 协调滚动更新--管理滚动更新 的简述和讲解。希望能对看到此文章的小伙伴有所帮助。

💾 红帽认证专栏系列:
RHCSA专栏: 戏说 RHCSA 认证
RHCE专栏: 戏说 RHCE 认证
此文章收录在RHCA专栏: RHCA 回忆录

如果这篇【文章】有帮助到你,希望可以给【金鱼哥】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点。

如果有对【运维技术】感兴趣,也欢迎关注❤️❤️❤️ 【金鱼哥】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
存储 消息中间件 网络协议
金鱼哥RHCA回忆录:DO447Ansible Tower的维护和常规管理--基本的故障排除
第十四章 Ansible Tower的维护和常规管理--基本的故障排除
724 0
金鱼哥RHCA回忆录:DO447Ansible Tower的维护和常规管理--基本的故障排除
回顾 | 5G通信领域的应用研讨会内容已全部更新完毕,精彩内容全在这里!
各专家在5G通信领域的应用研讨会上所发表的演讲内容已经全部展示完毕
回顾 | 5G通信领域的应用研讨会内容已全部更新完毕,精彩内容全在这里!
|
存储 运维 算法
金鱼哥RHCA回忆录:DO280管理应用部署--pod调度控制
第七章 DO280管理应用部署--pod调度控制
184 0
金鱼哥RHCA回忆录:DO280管理应用部署--pod调度控制
|
存储 运维 测试技术
金鱼哥RHCA回忆录:CL210管理计算资源--管理计算节点+章节实验
第七章 管理计算资源--管理计算节点+章节实验
275 0
金鱼哥RHCA回忆录:CL210管理计算资源--管理计算节点+章节实验
|
存储 缓存 运维
金鱼哥RHCA回忆录:DO447构建高级作业工作流--使用事实缓存提高性能
第十二章 构建高级作业工作流--使用事实缓存提高性能
243 0
金鱼哥RHCA回忆录:DO447构建高级作业工作流--使用事实缓存提高性能
|
存储 运维 安全
金鱼哥RHCA回忆录:DO447Ansible Tower的维护和常规管理--备份和修复
第十四章 Ansible Tower的维护和常规管理--备份和修复
190 0
金鱼哥RHCA回忆录:DO447Ansible Tower的维护和常规管理--备份和修复
|
运维 Linux API
金鱼哥RHCA回忆录:DO447管理高级清单--创建和更新动态清单
第十二章 管理高级清单--创建和更新动态清单
169 0
金鱼哥RHCA回忆录:DO447管理高级清单--创建和更新动态清单
|
存储 缓存 运维
金鱼哥RHCA回忆录:DO447管理高级清单--使用智能清单过滤主机
第十二章 管理高级清单--使用智能清单过滤主机
134 0
金鱼哥RHCA回忆录:DO447管理高级清单--使用智能清单过滤主机
|
运维 API
金鱼哥RHCA回忆录:DO447协调滚动更新--委派任务和事实
第五章 协调滚动更新--委派任务和事实
121 0
金鱼哥RHCA回忆录:DO447协调滚动更新--委派任务和事实
|
缓存 运维 安全
金鱼哥RHCA回忆录:DO447构建高级作业工作流--作业调度和配置通知
第十章 构建高级作业工作流--作业调度和配置通
125 0
金鱼哥RHCA回忆录:DO447构建高级作业工作流--作业调度和配置通知