Octopus 博客中文翻译(五十)
原文:Octopus Blog
影子是什么?-章鱼部署
在传统组织中,IT 部门监督和管理所有 IT 资源。然而,由于可以如此轻松地访问基于云的 it 资源,缺乏耐心和时间的员工通常会发现,自己构建 IT 基础架构比填写请求和等待 IT 部门更简单、更快速。当员工创建和使用他们自己的 IT 资源,而这些资源对 IT 部门来说是不可见的,这就是所谓的影子 IT。
2017 年,Gartner 预测,IT 部门将做出更少的技术决策,单个业务部门将开始为其团队选择技术,占技术购买的38%。2019 年,珠穆朗玛峰集团预测组织中超过 50%的技术支出是由于影子 IT 。云技术的兴起加剧了这一问题,使员工比以往任何时候都更容易使用未经批准的 it 资源。
影子 IT 给组织带来了新的问题。其中包括:
- IT 部门应该如何应对影子 IT?
- 跟踪 100%的所有 it 资源现实吗,甚至实际吗?
- 是否应该有一个风险可接受的更可控的方法?
- 哪些工具可以帮助管理影子 IT?
这篇文章探讨了这些问题。
企业成本
越来越多的团队正在利用影子 IT,这增加了安全违规的风险,因为资源不在 IT 部门的控制范围内。
EMC 的一项研究估计,由于影子 IT 安全漏洞,数据丢失和停机每年会造成1.7 万亿美元的损失。
在 IBM 的 2021 年数据泄露成本报告中,从 2020 年到 2021 年,数据泄露的平均成本从 386 万美元上升到 424 万美元。
来源:IBM
对于高度管制行业的企业来说,还存在合规性问题。通用数据保护条例(GDPR) 对从欧盟(EU)人民处收集数据的组织实施了严格的规定。违法者将被处以高达数千万欧元的高额罚款。随着影子 IT 的增加,确保只有经过授权的员工才能访问敏感数据变得越来越困难。
影子 IT 也会影响运营成本。当影子 IT 不受管理时,服务变得分散,因为每个业务部门都根据自己的需求采购服务。一个业务部门可能偏好一种产品,而另一个则偏好其竞争对手。这也可能导致云基础架构不可预测的运营成本。想想所有为单一目的而创建的未受监控的虚拟机,它们总是在运行,但从未停止运行。通过允许业务部门采购自己的 IT 基础架构,企业失去了购买力优势和降低 IT 基础架构成本的能力。
影子 IT 的真实成本归结于不断增长的未知资源,这些资源存在运营和安全风险。
员工为什么要用影子 IT?
使用 shadow IT 的主要动机是方便。
IT 政策可能非常严格。通常,员工自己获得 it 解决方案比通过 IT 部门更容易、更快。员工也可能更喜欢特定的解决方案,而不是规定的解决方案,这加剧了问题。员工可能会找到问题的另一种解决方案,再次引入影子 IT,而不是处理支持票证。
不幸的是,使用影子 IT 解决方案的人通常不会意识到后果。他们只想以一种高效的方式完成工作。
自助服务操作手册可以通过确保简化的治理体验来解决这一问题,使员工能够在不避开 IT 部门的情况下提升他们所需的基础架构。
风险缓解
影子 IT 的未知性质增加了组织的风险状况。影子 IT 正在广泛传播和增长,所以这是一个管理风险的问题。Gartner 建议了三种风险缓解策略来解决这一问题:
影子 IT 需要治理、发现和保护。解决方案必须精简,并最大限度地减少支持时间。
影子 IT 发现生命周期
这张图片来自微软的博客文章,展示了影子 IT 发现生命周期的各个阶段。这支持了任何影子 IT 的解决方案都应该有治理和法规遵从性。
T3
T5
来源:微软
在维护治理的同时减少合规障碍是管理影子 IT 的重要一步。Octopus Deploy 的 Runbooks 特性有助于实现整个组织的合规性和治理。
什么是 runbook?
runbook 是一种可重复使用的方法,用于执行经常重复的任务。runbooks 可以自动执行的任务类型包括最大限度地减少应用停机时间、简化日常维护以及提供自助操作。让我们看一下操作团队可能收到的请求,刷新测试数据库中的数据。
通常,当开发人员需要刷新测试数据库中的数据时,需要执行以下操作:
- 开发人员向支持团队创建一个请求来刷新他们数据库中的数据。
- 支持团队审查请求以了解需求。
- 如果支持团队需要额外的信息,他们会向开发人员请求。
- 当支持团队拥有了处理请求所需的一切时,他们就可以运行刷新数据库中数据的过程。
根据支持团队的工作量和周转时间,这个请求可能需要几分钟到几天的时间,并且开发人员通常不知道时间表。操作手册有助于避免这些陷阱。
刷新数据库中数据的步骤可以由 runbook 捕获并执行。runbook 还包括执行任务的所有权限,这意味着 run book 可以自助服务。这允许用户执行任务,而无需请求和等待支持团队成员。
任何可以自动化的任务都可以记录在操作手册中,允许团队成员完成以前需要专门团队完成的任务。
运行手册也引入了一致性。想象一下创建新 AWS 帐户的自助操作手册。用户需要设置访问级别、VPC 设置和其他 IAM 注意事项。如果 50 个不同的用户试图建立一个帐户,这可能导致 50 个不同类型的用户,这是另一个挑战。如果您将此应用于创建虚拟机、容器注册中心或其他 PaaS 基础设施,很容易发现 shadow IT 的问题。
使用操作手册可以限制这一过程,并使 IT 资源标准化。运营团队可以使用操作手册来监控和保护 IT 资源。
虽然 run book 不能解决影子 IT 的所有障碍,但 run book 可以改善 IT 资源管理并简化最终用户的使用。根据 MRC 关于管理影子 IT 风险的规定:
这一步的目标是受控的自助式解决方案。您提供的任何软件都必须满足两个重要标准:
- 自助服务:用户必须在不打扰解决方案的情况下使用它。
- 控制:它必须仍然能够控制数据和用户访问。
当您提供受控的自助服务选项时,您的企业将两全其美。用户可以快速获得他们需要的解决方案,而 IT 仍然可以保护数据和应用程序。"
操作手册让运营团队监控资源并提供安全保障。他们还允许员工在没有支持的情况下自助解决问题。
结论
影子 IT 是指不在组织控制范围内的任何 IT 资源。它给企业带来了多种风险和高成本的问题。
企业需要对 IT 资产进行更多的治理、发现和保护。员工希望流程更加简化,并且能够在没有太多支持的情况下解决问题。
Runbooks 可以通过提供运行常见任务的自助方式来解决这些问题。将这一概念应用于像设置云帐户这样的问题,为 IT 资产提供了标准化。
阅读我们的 Runbooks 系列的其余部分。
愉快的部署!
Selenium 系列:什么是 WebDriver 和 Selenium?-章鱼部署
原文:https://octopus.com/blog/selenium/1-what-is-webdriver-and-selenium/what-is-webdriver-and-selenium
这篇文章是关于创建 Selenium WebDriver 测试框架的系列文章的一部分。
谈到测试 web 应用程序,您可能听说过 WebDriver 和 Selenium。这两个术语通常可以互换使用,甚至可以组合使用,以指代开发人员可以编写代码与 web 浏览器进行交互的平台。然而,这两个术语所指的东西略有不同。
从技术上讲,WebDriver 是一个标准的、基于 HTTP 的 API,用于与 web 浏览器交互。该标准由 W3C 在 https://www.w3.org/TR/webdriver1/提供,任何人都可以免费实现。
大多数浏览器供应商通过浏览器本身附带的附加可执行文件来实现 WebDriver API。下面的列表显示了主要浏览器在哪里提供这个二进制驱动程序:
为了查看 WebDriver API 的运行情况,我们将下载并运行 Chrome 二进制驱动程序。打开https://sites . Google . com/a/chromium . org/chrome driver/downloads,点击最新发布的链接。
然后为您的本地操作系统下载驱动程序。
我用的是 Mac,所以我下载了chromedriver_mac64.zip。在这个归档文件中是名为chromedriver的驱动程序可执行文件。Windows 版本叫做chromedriver.exe。
提取这个文件并运行它。您将获得公开 WebDriver API 的端口:
$ ./chromedriver
Starting ChromeDriver 2.40.565386
(45a059dc425e08165f9a10324bd1380cc13ca363) on port 9515
Only local connections are allowed.
为了与 API 交互,我们需要一个允许我们发出 HTTP 请求的工具。我用过 Postman,它可以从https://www.getpostman.com/买到。
第一步是打开浏览器。这是通过创建新会话来完成的。
为了通过 WebDriver API 创建一个新的会话,我们向/session端点发出一个 HTTP POST 请求。此外,我们需要定义我们希望打开的浏览器的类型。该信息在 POST 主体中的 JSON 对象中发送。在本例中,我们将打开 Chrome:
{
"desiredCapabilities": {
"browserName": "chrome"
}
}
这个请求的响应包括一个sessionId。我们可以用它在刚刚打开的浏览器窗口上执行额外的操作。
下一个逻辑步骤是在浏览器中打开一个 URL。这是通过对/session/<session id>/url的 HTTP POST 请求来完成的,POST 主体包括将要打开的 URL:
{
"url": "http://octopus.com"
}
该调用导致在浏览器中打开所请求的 URL。
此时,你可能会感到有些不知所措。像 Postman 这样的工具使用 JSON body 对 REST API 进行 HTTP 调用……这是一个非常复杂的过程,打开一个浏览器并浏览到一个 URL 的过程并不简单。
但是不用担心。作为开发人员,我们从来不需要直接使用 WebDriver API,事实上这将是我们在这个博客系列中第一次也是最后一次直接查看 WebDriver API。
从这一点开始,我们编写的所有代码都将使用 Selenium API。Selenium 是由第三方提供的一个库,它包装了与浏览器交互时需要进行的所有 WebDriver API HTTP 调用。通过 Java 类和接口公开 WebDriver API 的功能,Selenium API 使得编写与浏览器交互的 Java 应用程序变得更加容易。
下图显示了浏览器、二进制驱动程序、Selenium API 和我们将要编写的 Java 代码之间的关系。
Selenium 与 WebDriver 同义,因为它是利用 WebDriver API 的最流行的方式。我个人从未在现实世界中见过直接针对 WebDriver API 编写代码的案例。因此,术语 WebDriver、Selenium 和 Selenium WebDriver 可以互换使用,指的是 Selenium API,而不是较低级别的 WebDriver API。
这篇博客的关键是:
- WebDriver API 是一个基于开放标准的低级 HTTP 接口。
- Selenium API 是调用 WebDriver API 的类和接口的集合。
- 因为直接使用 WebDriver API 不切实际,所以大家都用 Selenium API。
- 术语 WebDriver、Selenium 和 Selenium WebDriver 可以互换使用,通常指 Selenium API。
既然我们已经知道了 WebDriver 和 Selenium APIs 之间的区别,那么实际上我们可以将它们视为同一个东西。在讨论如何编写 WebDriver 测试时,我们从现在开始编写的所有代码都将使用 Selenium API。因此,尽管你现在知道 WebDriver 和 Selenium APIs 在技术上不是T4 的同一个东西,我们通常称“Selenium WebDriver”为我们与浏览器交互的平台。
这篇文章是关于创建 Selenium WebDriver 测试框架的系列文章的一部分。
Octopus 3.4 的新特性:弹性和瞬态环境——Octopus 部署
原文:https://octopus.com/blog/whats-new-elastic-transient-environments
这篇文章是我们 Octopus 3.4 博客系列的一部分。在我们的博客或我们的推特上关注它。
Octopus Deploy 3.4 已经发货!阅读博文和今天就下载!
Octopus 3.4 的新特性:弹性和瞬态环境
我想从我们的深入探讨和幕后帖子中退一步,给出弹性和瞬态环境特性集的概述。弹性和瞬态环境引入了一系列新特性,这些新特性使得能够更好地支持在机器可以来来去去的环境中工作。
特征
机器政策
机器策略是一组与机器相关的设置,使您能够定制运行状况检查执行的内容(以及执行的频率),控制触手和 Calamari 更新,以及当机器不可用时会发生什么。这些功能极大地改善了您在机器来来去去的环境中的工作方式。机器策略针对每台机器进行设置,并可在环境屏幕中进行配置。
机器策略允许您:
- 定义健康检查的时间间隔
- 定义运行状况检查期间在触手上运行的额外脚本
- 定义运行状况检查期间离线计算机的行为
- 定义乌贼和触手何时更新
- 定义发现离线时是否清理机器


健康检查步骤
基于机器策略,我们还引入了运行状况检查步骤,使您能够触发运行状况检查,作为项目部署过程的一部分。这在定期添加或删除机器以及长期运行部署的环境中很有价值。是的,这意味着在 a 部署期间,您可以重新评估机器是否在线*!*


项目触发器
触发器是一个很棒的新功能,它可以确保添加到环境中的新机器保持最新的适当版本。它们在响应事件时执行,并根据项目进行指定。它允许您创建一个触发器,以便在特定环境中为某些角色提供新的部署目标时自动进行部署。可以通过选择项目屏幕上的触发器菜单项来找到触发器。


项目机器连接设置
通过与其他新功能配合使用,project machine connectivity settings 允许您指定在部署期间计算机不可用时会发生什么情况。这有助于避免在部署时临时计算机不可用时部署失败。这意味着您不必单独选择在线机器作为部署目标!相反,我们将自动跳过离线机器。


包裹
我希望您喜欢探索构成弹性和瞬态环境的高度要求的特性。更多信息,请参见弹性和瞬态环境指南。
Octopus 3.4 的新特性:多租户部署——Octopus 部署
原文:https://octopus.com/blog/whats-new-multi-tenant-deployments
这篇文章是我们 Octopus 3.4 博客系列的一部分。在我们的博客或我们的推特上关注它。
Octopus Deploy 3.4 已经发货!阅读博文和今天就下载!
Octopus 3.4 的新特性:多租户部署
继续上一篇博客文章的主题,我将后退一步,概述新的多租户部署特性集。多租户部署是一个高级特性,它为 Octopus 部署体验增加了一个全新的维度,但我们努力让它变得平易近人!请继续阅读,了解更多信息。😃
为什么我应该关注多租户部署?
如果您曾经想要将项目的多个实例部署到每个环境中,那么您应该考虑在 Octopus Deploy 中进行多租户部署。例如:
- 您希望在您的测试/QA/UAT 环境中有多个独立的部署
- 您想要为每个测试人员提供一个隔离的测试部署
- 您希望为功能分支上的工作提供独立的部署
- 您希望跨环境管理对单个目标的部署,例如管理一组嵌入式设备或一组笔记本电脑/工作站
- 您想将您的项目部署给另一个客户
- 你想把你的项目变成一个 SaaS 应用程序
保罗·斯托弗最近录制了一集《T2》。NET Rocks 谈论构建多租户应用。如果能更好地理解为什么要构建多租户应用程序,以及在设计和部署多租户应用程序时要考虑的因素,这将是一次很好的聆听。强烈推荐的播客!
特征
功能切换
多租户部署的一个最重要的特征是,它被有意设计成一个附加的东西。换句话说,如果你不需要它,你不应该注意到有任何变化。这由 Octopus 功能配置屏幕中的功能开关控制。

同样需要注意的是,如果您启用了多租户部署,您可以继续愉快地部署现有项目,直到您决定将租户连接到它们。如果您将一个项目连接到一个或多个租户,您仍然可以像现在一样通过环境部署它们。我们称之为非租赁部署。


最后,您可以完全控制项目如何支持多租户部署,从禁用它到要求租户进行部署。

头等房客
八达通的租户是一等公民。它们使您能够将项目部署到同一环境中的一个或多个租户。您可以在租户屏幕中创建和管理他们的详细信息,我们已经通过项目和环境更新了部署体验,以支持租户概念。





可变模板
变量模板允许您指定将项目成功部署到租户所需的变量。它们可以在一个项目或一个库变量集上定义,我们根据它们定义的位置以稍微不同的方式解释它们。
在项目中定义变量模板意味着对于租户所连接的每个环境,变量可以有不同的值。这是管理技术设置(如数据库连接字符串或其他特定于环境的细节)的好方法。


在库中定义变量模板意味着无论项目和环境如何,该租户的变量都将有一个常量值。特定于租户的库变量模板值在“通用变量”选项卡下的租户页面上进行管理。


租户标签集
租户标记可帮助您使用自定义标记对租户进行分类,从而为您的项目和环境定制租赁部署。租户标签是在标签集中定义的,用于将相似的标签组合在一起。项目步骤、通道、变量、机器、账户等等都可以被标记。这使您能够与多组租户一起工作,而不是单独工作。例如,您可以将最新版本部署到带有Tenant Important/VIP标签的所有租户。租户标签集可在库租户标签集屏幕中管理。



租户设计者/预览
一些团队可能只有几个租户,而其他团队可能有几千个租户。考虑到这一点,我们建立了一个租户选择设计器/预览工具,以便在您需要时通过 Octopus 轻松找到合适的租户。您可以按名称查找特定租户,按标记集/标记筛选租户,并进一步搜索结果租户。


租户部署
将所有这些功能整合在一起可以实现租户部署。通过增强核心 Octopus 部署体验,将一个版本部署到租户,以支持租户选择一个或多个租户,然后将它们部署到环境中。

Octopus 仪表板现在包括一个租户计数,向您显示一个环境中有多少租户拥有最新版本。这可以进一步定制,以过滤特定租户或标记/标记集值。

默认项目概述指示板让您一目了然地看到哪些版本已经部署到了哪些环境和租户。更好的是,现在可以对仪表板进行过滤和分组,以便只查看您需要的相关信息。


包裹
多租户部署是一项高级功能,但它也是我们最受欢迎的用户意见建议。我们很喜欢在我们构建它的时候从我们的社区收到的反馈,我们迫不及待地想要发布它。有关更多信息,请参见多租户部署指南。
为什么要考虑数据库部署自动化?-章鱼部署
原文:https://octopus.com/blog/why-consider-database-deployment-automation
这是关于数据库部署自动化系列文章的第一篇。
对我来说,数据库是任何部署中最伤脑筋的部分。部署代码的压力要小得多。如果有什么不对劲,代码可以回滚。当它进入生产阶段时,如果它是在开发、QA 和预生产中测试过的相同代码,应该不会有任何意外。
数据库没有那么灵活。假设数据库脚本中有一个错误,所有用户的名字都被删除了。没有一个好的方法来回滚。备份可以恢复,但是备份是在什么时候进行的,自备份以来系统中是否有任何用户?如果恢复备份,哪些数据将会丢失?
手动数据库部署的问题
在 Octopus Deploy 工作之前,我是美国一家大型金融机构贷款发放系统的首席开发人员。在任何时候,都有数亿美元的贷款在外逃。这些都是大额贷款,需要许多个人来处理。每个人可能会在贷款上花费 15 分钟到 1 小时不等的时间。财务人员可能会花半个小时输入客户的财务状况,而承销商可能会花一个小时研究客户,并在贷款上添加注释和条件。不用说,恢复数据库备份是最后的手段。告诉人们他们必须重新输入信息,这种情况只会发生很多次,然后他们才会想要找到我。
我们有自动化的代码部署,但是数据库增量脚本是由数据库开发人员在部署之前手工创建的。对他们来说,花上一两个工作日的时间来整理剧本是很平常的事情。手动创建也意味着很少会发生测试。当脚本在生产中运行时,它很可能是第一次运行。我们还使用了 Redgate 的 SQL Compare 等工具,并在可能的情况下对恢复的备份进行了测试,但这只能做这么多。
由于存在风险,部署只能在下班后进行,这意味着晚上或周末,但这确实意味着我们可以为回滚进行备份。除了进行部署的开发团队之外,我们还有一名在线 DBA 和操作人员。操作人员必须等待 DBA 运行所有脚本,这可能需要一秒钟或二十分钟才能完成。
时间安排上的风险和困难意味着我们只能每个季度部署一次主要版本,在此期间进行小的 bug 修复。在一个主要版本之后,我们通常会发布几个错误修复版本,通常是因为错过了一些模式更改。每季度部署一次意味着一次要做很多改变。变更的验证需要很长时间,通常每个版本都需要两三个小时。
数据库模式更改被遗漏,因为数据库没有真实的来源。索引可能存在于生产前,但不存在于 QA 中,那么哪种环境是正确的呢?那个索引是什么时候添加的?谁加的?更糟糕的是,数据库中有将近 6,000 个对象(大部分是 CRUD 存储过程)。数据库开发人员不得不求助于手动跟踪所有的更改。80%的时间是数据库开发人员进行更改,另外 20%是开发人员进行更改。如果数据库开发人员那天不在,我们试图记住通过电子邮件将更改发送给他们,但是想想您在上一个季度对代码所做的所有更改。你记得他们所有人吗?
简而言之,除了应用程序中最关键的部分,我们已经实现了所有的自动化。完全相同的代码在环境中移动时被测试了多次。为每个环境手动创建了唯一的数据库增量脚本。数据库模式没有真实的来源,数据库管理员正在拔头发,试图让一切保持运行。
总结一下我们面临的挑战:
- 环境都不一样。
- 为每个环境创建了自定义脚本。
- 数据库对象存在于一个环境中,而不存在于另一个环境中。
- 部署耗时数小时。
- Big bang 多个 bug 修复版本的季度发布。
- 手动跟踪更改。
数据库变更控制是狂野的西部。
数据库部署自动化
有些东西必须放弃。数据库更改必须进入源代码控制,这些脚本需要打包并在部署期间自动运行。经过大量的讨论、研究和测试,我们找到了一个工具。工具本身并不重要。重要的是,我们自动化了数据库部署。
这种影响几乎立刻就能被察觉。
将数据库放在源代码控制中可以让我们看到什么时候有人做了更改。我们可以将它与故事联系起来,我们知道为什么要进行更改,我们设置它以便删除不在源代码控制中的更改。如果一个索引在 QA 中,但不在源代码控制中,我们就删除它。这有点苛刻,但它保证了数据库模式匹配源代码控制中的内容。
由于随机视图或存储过程丢失而导致的紧急修复几乎降到了零。我们在 Octopus Deploy 中设置了一个手动干预步骤,这允许我们在部署之前查看和批准数据库增量脚本。每个人真正喜欢手动干预步骤的地方是,如果 delta 脚本中出现意外的数据库更改,可以取消部署。这有助于每个人、开发人员、QA 和 DBA 信任这个过程。
对部署的信心开始增加。很快,我们每月进行一次部署。然后一周一次。一旦通过 QA 和业务所有者的验证,功能就可以交付给用户。可以报告一个 bug,一旦通过验证,修复程序就可以交给用户了。我们发布得如此频繁,以至于每次发布的更改数量都显著减少,部署时间从两到三个小时减少到五到二十分钟。
将这一切都放在 Octopus Deploy 中还有一个好处,那就是让数据库管理员和运营团队的夜晚和周末时光重新回来。现在,他们可以安排部署,并且只在出现问题时才需要上线。
博客系列
这篇文章是我带领您建立数据库生命周期管理(DLM)和数据库部署自动化的系列文章的第一篇。本系列的目标是为您提供一些使用各种数据库部署工具的真实示例。除此之外,我们将讨论一些你会遇到的常见陷阱。
数据库部署自动化系列文章:
为什么在 Kubernetes 部署中使用 Octopus?-章鱼部署
原文:https://octopus.com/blog/why-kubernetes-and-octopus-deploy
回到 Octopus 2018.9,我们引入了一系列功能,为 Octopus 中的 Kubernetes 提供了核心支持。
在本文中,我将介绍使用 Octopus 管理 Kubernetes 部署的一些好处。毕竟,Kubernetes 已经为它的所有资源提供了一个丰富的声明性模型,一个全功能的命令行工具,以及更多的仪表盘。
Octopus 2021 Q3 包括对 Kubernetes 部署的更新支持,以及针对 Google Cloud、AWS 和 Azure 用户的 runbooks。在我们的发布公告中了解更多信息。
建模您的开发环境
开发团队中的一个常见做法是在不同的环境中开发代码。虽然没有两个团队是相同的,但是我曾经合作过的每个团队都采用了一些 开发➜测试➜生产 环境生命周期的变体。
环境进展是 Octopus 的核心概念,这并非巧合。环境是 Octopus 中的核心实体,产品的每个部分都包含了对生产环境部署的管理。
从生命周期到频道再到仪表盘,Octopus 使你的团队如何工作的建模变得容易,并以一种可靠和可见的方式促进发布。
以一个 Octopus 项目的概述为例。该表清楚地显示了在什么时间向什么环境发布了什么版本。只需点击几下鼠标,您就可以获得更详细的信息,例如谁执行了部署以及包含了哪些版本的包。
另一方面,Kubernetes 仪表板关注于显示关于 Kubernetes 资源的信息,比如 pod、服务和部署。这是集群的低级视图,可用于调试和监控。
Octopus 允许您对您的团队已经在使用的环境进行建模,而 Kubernetes 仪表板为调试和其他管理任务提供了一个低级别的资源视图。结合 Octopus 和 Kubernetes,您可以从上到下查看您的基础设施。
管理应用程序变量
Helm 提供了一种表达性模板语言,允许从多个来源提供变量,包括变量 YAML 文件或命令行。这个功能允许定义复杂的和可定制的部署,使得 Helm 成为事实上的 Kubernetes 包管理器。
但是模板语言只是故事的一半。另一半是管理定义特定部署的变量。
Octopus 提供了一个具有全面变量管理功能的解决方案,包括秘密存储和范围规则。这些变量可以传递到 Helm 中,在 Kubernetes 步骤中使用,或者在自定义步骤中使用。
通过利用 Octopus 管理变量,复杂的 Helm 和 Kubernetes 部署可以轻松地跨多个环境和集群进行协调。
版本化您的 Docker 容器
部署流程创建后,通常不会有太大变化。不同部署之间会发生变化的是容器版本。
Octopus 将构建部署的设计时过程与选择包版本的部署时过程分开。这意味着当您推出容器的新版本时,Octopus 会在部署期间选择这些版本,并将它们合并到生成的 YAML 文件中。
正如您在下面的截图中看到的,在设计 Kubernetes 部署时,您指定了容器 ID,但没有指定版本。
然后在部署过程中,您可以选择一个特定的容器版本,或者简单地让 Octopus 为您选择最新的版本。
Octopus 通过分离设计和部署时间问题,使管理可重复部署变得容易,这意味着您只需要在推出新部署时担心您希望部署哪个版本的容器。
单独迭代或集体进步
微服务是一种越来越受欢迎的开发策略,它允许专注的团队在更大的生态系统中快速交付小的变化。
然而,将一组已知版本的单个微服务升级到下一个环境并不是不常见的需求。虽然微服务架构不鼓励这种依赖性,但公司测试或外部法规可能要求您的环境在任何时间点都处于众所周知的状态。
Octopus 可以对这些开发策略进行建模,无论你的团队是通过环境独立推广单个微服务,还是多组微服务一起推广。
对于独立推广自己个人微服务的团队,可以使用个人 Octopus 部署项目。
为了以可预测的顺序提升一组已知版本的微服务,项目可以使用部署发布步骤。通过将其他项目的部署视为可部署的资源,部署发布步骤允许团队在给定的时间点捕获环境的状态,并将该状态部署到下一个环境。
在下面的截图中,你可以看到一个 Octopus 项目的例子,其中包括一系列的部署发布步骤。这些步骤的顺序确保了微服务以固定的顺序部署,一组部署发布步骤代表了一个完整的微服务生态系统,它作为一个单元部署到新环境中。
使用 Octopus 来管理 Kubernetes 部署可以让您在开发过程中自由地快速迭代,同时以可预测的方式在环境之间进行升级。
管理云和从内部迁移
Kubernetes 是您工具箱中的一个优秀工具,但它不太可能是您将使用的唯一工具。Kubernetes 真的是托管静态文件的最佳选择,还是 S3 或 Azure 存储更合适?您还需要使用本地数据库吗?RDS 是不是比容器化数据库更好的选择?
增量迁移、遗留系统和强大的 PaaS 产品通常意味着您的部署策略不会局限于您的 Kubernetes 集群。因为 Octopus 已经支持广泛的云和本地平台,所以您可以跨 Kubernetes 和现有服务无缝集成部署流程。
如果您的部署确实跨越多个技术堆栈,您可以放心,上述所有优势同样适用于您的内部部署和云部署,以创建一个统一的部署流程。
使用最佳实践对 Kubernetes 部署进行建模
互联网安全中心就如何保护您的 Kubernetes 基础设施提供指导。特别是,有两个建议与您的部署策略特别相关:
- 1.6.1 确保仅在需要时使用群集管理角色。
- 1.6.2 使用名称空间在资源之间创建管理边界。
Octopus 鼓励通过目标使用具有有限权限的凭证部署到单独的名称空间。Octopus 中的 Kubernetes 目标捕获集群 URL、帐户和名称空间,并且作用于角色和环境。
通常,Kubernetes 目标对于每个环境和角色都有一个惟一的名称空间。建议关联帐户仅拥有在该命名空间内部署所需的权限。结果是 Kubernetes 目标代表了集群中的权限边界。遵循这种模式可以确保您的部署不依赖于单个管理员帐户,并在名称空间内隔离资源。
【T2 
通过使用目标,Octopus 鼓励您以安全和可管理的方式对 Kubernetes 部署建模。
集中式审计 Kubernetes 集群管理
你曾经通过电子邮件或 Slack 发送过配置文件吗?您是否曾被要求报告一次生产中断,但却不知道发生了什么变化,因为从人们的桌面上进行了未记录的修改?
不幸的是,这些情况非常普遍。随着您的 Kubernetes 集群变得越来越复杂,管理凭证和了解变化的影响会变得越来越困难。
Octopus 通过脚本控制台提供解决方案。通过使用脚本控制台,开发人员和管理员可以与 Kubernetes 集群进行交互,而无需共享凭证。可以对一个或多个 Kubernetes 目标运行特殊命令,运行的命令、运行它的人以及结果都保存在审计日志中,以后可以查看。
通过脚本控制台,Octopus 让团队能够调试和管理他们的 Kubernetes 集群,而不需要分发凭证,并且有一个审计日志来记录每个更改。
结论
Octopus 在交付可重复且可靠的部署方面有着悠久的历史,并且已经发展到支持数千个开发团队中的部署模式。
通过使用 Octopus 来管理您的 Kubernetes 部署,您可以获得快速成为管理高密度基础架构的标准平台的所有好处,并将经过实战检验的部署策略融入 Octopus 中。
愉快的部署!
为什么章鱼不用。网络服务总线(或轮询)- Octopus 部署
原文:https://octopus.com/blog/why-octopus-doesnt-use-the-servicebus
Octopus 服务器将软件部署到许多部署代理(“触角”)。通信模型使用标准的客户机/服务器模型,触手监听 TCP 端口(默认为 10933 ), Octopus 与之连接。
Octopus Server -------> Tentacle
一个常见的功能要求是反转这种通信,因此:
Octopus Server <------- Tentacle
这方面的一些实现选项可能是:
- 让触角“轮询”Octopus 服务器的部署命令
- 使用像 web sockets/SignalR 这样的技术
- 使用。网络服务总线
举个例子,考虑一家向银行销售软件的云创业公司。Octopus 服务器可能安装在 Amazon EC2 上,而触手代理将安装在银行的生产 web 服务器上,深埋在银行管理的数据中心中。
上面描述的特性——让银行的生产 web 服务器调用 Amazon 托管的 Octopus 服务器——听起来是一个很好的解决方案,可以避免银行打开防火墙规则。但是缺点是什么呢?
为什么章鱼是这样工作的
选择当前的通信架构有几个原因:
- “服务器”通常提供一些服务——有可能已经允许到服务器的入站连接,否则您不会向它部署任何东西。根据我的经验,让系统管理员批准一个出站连接和让他们批准一个入站连接一样困难,特别是当 Octopus 服务器与生产 web 服务器处于不同的安全区域时。
- 我发现大多数系统管理员实际上更喜欢这样,因为他们可以创建规则来调节入站连接。如果软件试图“绕过”防火墙规则,这可能会导致系统管理员不信任它。
- 负载/性能——让触手向外连接意味着某种主动连接——无论是使用套接字还是轮询。通过让触手监听,我们只有一个打开的监听套接字和一个等待 I/O 的阻塞线程。虽然这两种方式的开销都很小,但如果触手碰巧运行在生产 web 服务器上,一些人会觉得这种方法更舒服。
- 这与大多数操作工具的工作方式一致——WinRM、PSExec、SSH——都需要“目标”服务器进行监听
- 它更简单,越简单越好
逆转这种模式可能会损害信任

在我看来,逆转这一模式的唯一原因是“绕过”防火墙规则。但是它实际上并不是关于绕过防火墙规则(从技术上讲,这些规则并不难改变);这是关于围绕控制防火墙规则的人工作。
如果我是上述银行的系统管理员,我想我更愿意知道在我的生产服务器上运行的软件需要打开一个端口,并且我有机会批准/拒绝它。如果该软件悄悄地“绕过”我的防火墙规则,我会非常不安。我宁愿有人花时间告诉我这个软件的目的(使应用程序部署更简单)和它的安全方面,这样我就可以做出明智的选择。如果八达通使我周围的工作变得容易,我就不太可能信任该产品。
现在,任何银行系统管理员都不太可能同意更改防火墙规则,以便亚马逊托管的 web 服务器可以将软件部署到银行的生产 web 服务器中。但是如果他们不同意,这难道不是足够的理由来知道试图绕过他们是一个坏主意吗?
有有效的场景吗?
虽然替代通信模型的唯一原因似乎是绕过防火墙(或者换句话说,绕过系统管理员),但是有没有这样的场景,它可能是一个好主意呢?
反转模型可能是一个好主意的一个场景是当使用 Octopus 部署桌面软件时,其中触手运行在每个客户机工作站上。虽然它有可能工作,但我认为将软件部署到客户机工作站与将软件部署到服务器是完全不同的问题领域(由于连接性、大量的机器、需要客户机单独回滚等等),Octopus 首先不适合这种情况。这就是为什么 Windows Update 不构建在 MS Deploy 之上的原因。
另一个例子可能是防火墙由外部提供商管理,虽然系统管理员很乐意更改规则,但及时更改规则可能很困难。同样,这感觉像是对人的问题的技术解决方案,但有时这就是它所需要的。
我很乐意听到您可能遇到过的任何使这种沟通模式成为必要的场景。现在,当我考虑实现它需要做的工作以及这种模型可能在产品中产生的不信任时,我觉得添加一个基于轮询/服务总线的通信模型并不是一个高优先级的特性。
为什么八达通使用自签名证书-八达通部署
Octopus Deploy 服务器和 Tentacles 之间的通信使用 X.509 证书进行保护。安装 Octopus 后,会生成一个新的自签名证书。安装 Tentacles 时,它们还会生成一个新的自签名证书。在这篇文章中,我想讨论一下为什么我们使用自签名证书——毕竟,这不是很糟糕吗?
背景
当触手在 Octopus 中注册时,拇指纹(标识证书的公钥)被交换——也就是说,您手动将 Octopus 拇指纹粘贴到触手设置向导中,并在 Octopus UI 中手动验证触手的拇指纹。这张截图来自 Octopus 1.0,但在 2.6 中也有相同的概念:

当 Octopus 连接到触手时,它会验证触手是否提供了带有它所期望的指纹的证书。同样,当触手处理一个连接时,它会验证这个连接是否来自它信任的 Octopus 服务器。如果对方不是他们认为的那个人,双方都会中止连接。
为什么自签名?
有时会出现一个关于我们为什么使用自签名证书的问题——这难道不是一种糟糕的做法吗?要回答这个问题,让我们反过来问:为什么要使用证书颁发机构?
假设你想做一些网上银行。你去你的银行网站,并被重定向到他们的 HTTPS 网站。

你实际上不知道这是不是美国银行。但是你的浏览器信任赛门铁克(拥有 VeriSign),赛门铁克告诉你“当有人为 BankOfAmerica.com 订购证书时,我们给他们打了电话并做了一些其他检查,我们非常确定这确实是美国银行。你信任我们,因为我们是诺顿,对吗?”
这里有一个更安全的替代方案,可以替代依赖赛门铁克这样的证书颁发机构(CA ):当你在银行分支机构设立账户,与银行经理握手时,他们会给你一个指纹,作为他们网站证书的指纹。你把它写在一些纸上,当你回家时,你把它插在你的电脑上。这样你就不需要任何认证机构:你的计算机将只信任 BankOfAmerica.com,而不需要任何第三方。
为了方便起见,我们有认证机构,因为期望人们为他们计划访问的每个站点写下公钥太费力了。我们没有安全认证机构:它们实际上降低了安全性。CA 受到威胁:还记得 DigiNotar 吗?
如果章鱼用了 CA 的
如果 CA 和 Octopus 一起使用,我们有两种方法可以使用它们:
- 我们只信任由 CA 发布的任何内容。我们没有检查章鱼/触手是否可信,而是假设如果它们提供了由你的公司颁发的证书,那么就可以进行通信了。
- 无论如何,我们都要验证指纹,并用它们来建立信任。
方法#1 是危险的,因为如果 CA 受到威胁,那么网络上的每台机器实际上都受到威胁,因为任何拥有有效证书的人都可以伪装成其他人。无论 CA 是您组织内部的,还是受信任的第三方,这一点都适用。使用我们当前的方法,由于我们单独验证证书,机器 A 不可能在没有机器 B 的私钥的情况下伪装成机器 B。
方法#2 更好,只是我们实际上忽略了 CA。如果我们自己验证指纹,CA 在这种情况下提供了什么价值?
有人可能会说,Octopus 应该支持使用 CA 来颁发证书,只是因为“感觉良好”的因素,因为我们已经习惯于认为自签名证书在某种程度上本质上是不好的。你可以使用Tentacle.exe import-certificate让 Tentacles 使用 CA 颁发的证书(但是目前在 Octopus 服务器上没有办法做到这一点),但是我认为争论是由公司政策驱动的(“禁止自签名证书!”)而不是通过合理的推理。
从安全的角度来看,我们能想到的关于 CA 在 Octopus 中有意义的唯一理由是撤销列表。但是你总是可以告诉 Octopus/触手不再信任一个给定的证书,而不需要 CRL,所以我认为这个论点也站不住脚。
我们在 Octopus 中非常重视安全性,我们也尽力使其易于使用。我们认为从安全的角度来看,交换指纹和使用自签名证书是最好的解决方案,添加任何额外的 CA 支持层似乎会使软件变得比必要的更复杂,并且要么没有增加任何价值,要么根据其实现方式来创建攻击媒介。我希望这篇文章能对我们的推理有所启发。
感谢 OJ 来自 Beyond Binary 对本帖草稿的审阅
使用 NGINX 单元有什么好处?-章鱼部署
NGINX 是当今最流行的 web 服务器和反向代理之一。它提供了高性能和几乎无限的可配置性,是 Kubernetes 等现代堆栈中常用的组件。现在,NGINX 团队有了一个名为 NGINX Unit 的新产品,旨在解决现代开发过程中的一些常见挑战。
如果你跳转到 NGINX 单元文档,你会发现一个精彩的来自 NGINX Conf 17 的现场演示。在同一个会议上还有一个概述会议。这些演示很好地回答了 NGINX 单元是做什么的,但仍然让我想知道为什么有人会选择使用 NGINX 单元。
在这篇博文中,我们将看看 NGINX 单元提供的一些优势。
标准化的 JSON 配置文件
传统的 NGINX 配置文件看起来像这样:
server {
location / {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
虽然花引号语言的开发人员应该对这种格式相当熟悉,但 NGINX 配置文件语法不符合任何通用标准。如果您想定期更新这个文件,您可以编写复杂的sed命令来编辑原始文本。
但是使用正则表达式修改配置文件并不是一种愉快的体验。不可避免地,你会发现你的正则表达式匹配了一些你没有预料到的东西,没有考虑到行尾或者没有完全捕捉到一个值的所有变化。
NGINX 单元通过利用 JSON 进行配置来解决这个问题。对于如何构造配置数据不再有任何模糊之处,而且以编程方式更新配置值要容易得多。依靠公共数据格式使得 NGINX 单元更容易管理。
HTTP 配置 API
每一个现代计算平台都有一个由结构良好的 API 支持的丰富的 CLI 工具。很容易认为这个功能是理所当然的,直到您发现自己在对一个配置文件运行sed,然后重新启动一个服务。
虽然 NGINX 单元没有提供 CLI 工具(文档中的所有例子都使用了curl,但是它通过一个易于理解的 HTTP API 公开了所有的配置。这为您提供了很大的灵活性来选择如何公开 API(即,在本地主机上公开它或者安全地代理它以使它公开可用),这意味着您可以使用您选择的任何脚本工具来与之交互。
常见用例的声明性模型
鉴于 NGINX 无处不在,我发现自己不得不每年阅读几次随机的 NGINX 配置文件。每次我都必须查阅文档来回忆这些命令的作用,每次我都发现自己必须从命令序列中逆向工程配置的意图。
NGINX 单元摒弃了这种命令式配置模型,而是公开了一种声明式配置模型。诚然,NGINX 单元模型远不如传统的 NGINX 配置文件可配置,但它很好地展示了您将使用的常见路由和安全选项。
声明式配置模型使得 NGINX 单元对于那些有配置云服务和像 Kubernetes 这样的平台的经验的人来说更加容易接近。
一致的网络层
多语言开发越来越受欢迎。无论是因为您的团队找到了最适合他们需求的混合语言,还是因为您的基础架构包括用多种语言编写的第三方产品,拥有一个包含多种编程语言的应用程序堆栈并不罕见。
然而,网络层仍然需要以一种内聚的方式来处理,当每个应用程序都有一个以稍微不同的方式配置的网络组件时,这是一个挑战。
NGINX 单元是一种日益增长的趋势的一部分,它将网络问题从单个应用程序中分离出来,使之成为基础设施层的责任。NGINX 单元通过公开一个公共 API 和处理安全和路由等公共网络任务来整合网络问题。
无需重启的重新配置
NGINX 单元在它托管的应用程序进程和它置于顶层的网络层之间提供了一个清晰的分离。这使得无需重启托管应用程序就可以更改网络配置。这也意味着网络更改可以应用到正在运行的系统中,而无需停机。
将这种将更改应用到实时系统的能力与 NGINX 单元托管的所有应用程序都可以利用的一致网络配置相结合,您就拥有了一个可以随着部署数量和应用程序版本的增加而轻松扩展的基础架构。
采用门槛低
NGINX 单元只需几秒钟就能安装完毕,只需一个命令就能启动,并且只需对配置进行一次更新,就能托管您的第一个应用程序。它不需要代理、控制平面、数据库或专用集群来运行。
与普通云部署或第一次启动和运行 Kubernetes 集群的工作量相比,NGINX 是一股新鲜空气。
你所看到的就是你用 NGINX 单元得到的,使它易于部署、推理和诊断。
将应用程序作为服务进行管理
您目前如何管理 Node.js 应用程序的生产部署?Node.js 本身并没有真正提供一个解决方案,这已经产生了一系列的解决方案,如 PM2 、永远、nohup 或通过 systemd 的本地服务管理。
NGINX Unit 是托管传统上依赖第三方解决方案来引导、运行和重启进程的应用程序的有效替代方案,其额外的好处是它可以托管用多种语言编写的应用程序。
使用单位的缺点
使用 NGINX 单元时,有一些缺点,或者至少是需要注意的问题:
- 没有 Windows 端口,这使得 NGINX 单元仅限于 Linux 和 MacOS 商店。
- 必须修改 Go 和 Node.js 代码库才能与 NGINX 单元一起工作。
- NGINX 单元仅限于证书处理和基本路由。例如,您不会发现认证、复杂的重写规则、故障注入、重试、加权流量分割等。
- NGINX 单元不为它管理的进程提供健康检查。
结论
总的来说,我得到的印象是 NGINX Unit 就是 NGINX 如果今天写出来的样子。它提供了一个基于 JSON 的配置模型,通过 HTTP API 公开该配置,并提供了一个用于配置最常见的网络用例的声明性模型,所有这些都是轻量级的,并且易于运行。
这种回归基础的方法确实意味着 NGINX 目前支持的一些用例在 NGINX 单元中是不可能的,但随着每隔几个月就会有一个新版本,我预计 NGINX 单元的功能将会增长。
如果 NGINX 单元提供的功能满足您今天的需求,那么它是部署传统 NGINX 服务的自然选择。
通过 XML 模板或 CLI 脚本配置 wild fly-Octopus Deploy
当用像 Puppet、Chef、Ansible 等自动化工具构建 WildFly 服务器时,你将面临如何从库存下载到定制服务器的问题。定制的很大一部分是在构建过程中如何编辑配置文件(standalone.xml、domain.xml、host.xml和host-slave.xml)。
编辑这些 XML 文件时,您有两个主要选择:直接编辑文本,或者使用 WildFly CLI 进行更改。两者各有利弊,我们将在这篇博文中探讨。
直接编辑 XML
直接编辑 XML 配置文件可能是最自然的选择。由于 XML 文件只是纯文本,并且每个部署工具都有某种形式的模板支持,因此在基本模板中进行所需的更改并在部署期间复制定制版本是非常容易的。
这种方法有许多好处。
首先,您不需要 WildFly 的运行实例来进行配置更改。这消除了您在使用 CLI 工具时会遇到的一些麻烦,默认情况下,CLI 工具需要运行一个实例,并会强制您重新启动服务器以使一些更改生效。
第二,所有的更改本质上都是以“批处理”方式完成的,也就是说所有的更改都是一次性完成的。当您复制一个模板 XML 文件时,这听起来可能很明显,但是它确实删除了在通过 CLI 进行更改时必须考虑的一些内容。
但是,直接编辑 XML 配置文件有一些明显的缺点。
WildFly 使用的一些 XML 文件不是静态的。例如,WildFly 将使用当前部署的应用程序的详细信息更新domain.xml和standalone.xml文件。任何部署脚本的目标都是幂等的,但是如果您在每次部署时盲目地将一个新的 XML 配置文件复制到服务器上,您会发现自己丢失了胡乱做出的运行时更改。此外,您可能会发现带有新 XML 配置文件的服务器没有部署,这可能会给生产带来巨大的冲击。
如果没有预先考虑,您可能还会发现自己处于这样一种情况,即很难看出对 XML 文件做了什么更改。这些配置文件相当长,如果没有 diff 工具,几乎不可能发现定制模板中的更改。
出于同样的原因,在 WildFly 的新版本中,将您的定制应用到配置文件也是一个挑战。鉴于 WildFly 大约每年都会发布一个主要版本(从 WildFly 12 开始,这个发布时间表将会加快),您真的希望能够轻松地将您的定制应用到下一个版本,即使只是为了利用 WildFly 后续版本中的安全补丁。
对于那些直接对 XML 配置文件应用更改的人,我的建议是为每个更改添加清晰的注释。例如,您可以使用如下代码更改配置以绑定到任何网络适配器:
<interfaces>
<interface name="management">
<!-- CHANGE: Bind to any IP address -->
<any-address/>
</interface>
<interface name="public">
<!-- CHANGE: Bind to any IP address -->
<any-address/>
</interface>
</interfaces>
WildFly 在启动时会丢弃这些注释(WildFly 在运行时覆盖 XML 文件是 WildFly 运行时无法编辑这些文件的原因),但通过简单的搜索字符串,您可以找到您在模板中所做的所有更改。这使得将更改移植到新版本变得容易,或者简单地理解您的定制版本与股票下载有何不同。
使用 CLI 更新
使用 WildFly CLI 工具来应用定制比编辑 XML 文件更高级,但它确实有许多优点。
您可能会发现,您的 CLI 脚本将适用于 WildFly 的新版本,无需任何更改。例如,以下 CLI 命令将公共接口绑定到任何地址:
/interface=public/:undefine-attribute(name=inet-address)
/interface=public/:write-attribute(name=any-address,value=true)
我希望这些命令能在 WildFly 的所有最新版本中工作,也希望它们能在即将发布的版本中工作。这使得升级你的 WildFly 版本更加容易。
这些 CLI 命令还提供了一种简洁的方式来理解对股票下载所做的更改。与模板 XML 文件不同,在模板 XML 文件中,更改分散在一个大文件中,CLI 命令易于查看和理解。
因为您正在对当前配置应用有针对性的更改(而不是覆盖整个 XML 文件),CLI 命令有可能是等幂的。通过使用 CLI 流控制语句,可以仅在当前设置不是所需状态时应用更改。
CLI 命令提供了一定程度的错误检查。公平地说,WildFly 中的 XML 验证非常严格,所以不太可能有无效的 XML 和可启动的服务器,但是当您试图做错什么时,CLI 会提供更直接的反馈。
对于复杂的环境,您可以利用 CLI Java 库,用任何 JVM 语言编写您的更改。Groovy 是一个不错的选择。使用 Grape 你可以删除任何需要的依赖项,你的脚本可以像任何其他可执行文件一样在 Linux 或 MacOS 环境中运行。
这个示例 groovy 脚本使用 WildFly CLI 库来执行所需的 CLI 命令。虽然这是一个非常简单的例子,但是可以修改它以适应更复杂的需求。
#!/usr/bin/env groovy
@Grab(group='org.wildfly.core', module='wildfly-embedded', version='2.2.1.Final')
@Grab(group='org.wildfly.security', module='wildfly-security-manager', version='1.1.2.Final')
@Grab(group='org.wildfly.core', module='wildfly-cli', version='3.0.0.Beta23')
import org.jboss.as.cli.scriptsupport.*
final DEFAULT_HOST = "localhost"
final DEFAULT_PORT = "9990"
final DEFAULT_PROTOCOL = "remote+http"
def cli = new CliBuilder()
cli.with {
h longOpt: 'help', 'Show usage information'
c longOpt: 'controller', args: 1, argName: 'controller', 'WildFly controller'
d longOpt: 'port', args: 1, argName: 'port', type: Number.class, 'Wildfly management port'
e longOpt: 'protocol', args: 1, argName: 'protocol', 'Wildfly management protocol i.e. remote+https'
u longOpt: 'user', args: 1, argName: 'username', required: true, 'WildFly management username'
p longOpt: 'password', args: 1, argName: 'password', required: true, 'WildFly management password'
}
def options = cli.parse(args)
if (!options) {
return
}
if (options.h) {
cli.usage()
return
}
def jbossCli = CLI.newInstance()
jbossCli.connect(
options.protocol ?: DEFAULT_PROTOCOL,
options.controller ?: DEFAULT_HOST,
Integer.parseInt(options.port ?: DEFAULT_PORT),
options.user,
options.password.toCharArray())
jbossCli.cmd("/:take-snapshot")
jbossCli.cmd("/interface=public/:undefine-attribute(name=inet-address)")
jbossCli.cmd("/interface=public/:write-attribute(name=any-address,value=true)")
System.exit(0)
该脚本可以在以下情况下运行:
./script.groovy -u admin -p password01
不过,运行 CLI 脚本也有缺点。
通常,您需要有一个正在运行的 WildFly 实例,以便运行您的 CLI 脚本。当服务器没有正确配置以便引导,从而可以对其运行 CLI 脚本时,这可能会很棘手。例如,接口绑定可能不正确,端口可能不正确,或者从属实例可能无法连接到域主节点。
这种情况可以通过运行嵌入式服务器来缓解,这是一种“离线”模式,让您无需运行服务器就可以访问 CLI。
您还需要知道哪些更改需要重新启动服务器,以及哪些更改需要作为批处理的一部分进行。这是在复制 XML 文件和启动服务器时不需要担心的两件事。
最后的想法
如果需要等幂,CLI 脚本是最佳选择。它们允许您只修改不处于所需状态的设置,并且是非破坏性的。CLI 脚本往往更容易移植到新的 WildFly 版本,并提供了您的实例如何不同于股票下载的简明定义。
对于不可变的环境,编辑 XML 文件的简单性是无法超越的。每个系统管理员都知道如何编辑 XML 文件(而对于新手来说,CLI 可能比较棘手),每个部署工具都支持某种类型的模板,可以处理 XML 文件。只要您小心翼翼地清楚识别对股票配置文件所做的更改,将这些更改移植到 WildFly 的新版本是非常容易的。
如果您对 Java 应用程序的自动化部署感兴趣,下载 Octopus Deploy 的试用版,并查看一下我们的文档。
从 Octopus Deploy - Octopus Deploy 部署到 Wildfly
这篇文章是为老版本的 Octopus 写的,在加入原生野生支持之前。
请访问章鱼指南获取关于部署到野外的最新说明。
在 Octopus,我们已经开始了一个项目,研究如何更好地支持 Java 开发人员。在之前的一篇博客文章中,我谈到了如何使用 Octopus Deploy 将 WAR 文件部署到 Tomcat。Tomcat 无疑是当今产品中最受欢迎的 Java 应用服务器(根据来自 Plumbr 和 Rebel Labs 的统计,Tomcat 占据了超过 50%的市场份额)。下一个最受欢迎的应用服务器是 JBoss/wildly,在这篇文章中,我将向您展示如何将 WAR 文件部署到 Wildfly 11(目前在 Alpha 中)。
像 Tomcat 一样,将 WAR 文件部署到 Wildfly 可以简单到只需将它复制到一个特殊的目录。在 Wildfly 的情况下,将 WAR 文件复制到standalone/deployments目录将触发 Wildfly 部署并运行应用程序。这是一个非常有效的部署方法,如果这对您有用,那么关于部署到 Tomcat 的博文同样适用于 Wildfly。
然而,有些情况下简单的文件拷贝在 Wildfly 中不起作用。特别是,部署到 Wildfly 域控制器通常是通过 JBoss CLI 工具完成的。
CLI 部署面临的挑战
当从 Octopus Deploy 部署 WAR 文件时,理想情况下,我们希望这些步骤是等幂的。幂等只是一种花哨的说法,表示部署可以运行任意次,最终结果都是一样的。
JBoss CLI 工具中的部署操作不是这样的。您不能执行 CLI 命令,如
deploy myApplication.war --all-server-groups
多次,因为一旦文件myApplication.war在 Wildfly 内容存储库中,如果没有像--force这样的选项,它就不能被覆盖。这自然会让您尝试运行这样的命令
deploy myApplication.war --all-server-groups --force
这是行不通的。您不能在一个命令中强制上传文件并将其部署到服务器组。
这意味着,如果您希望能够将应用程序部署和重新部署到域环境中,您需要做一些额外的工作来确保正在运行的命令能够正常工作,无论该应用程序是否存在于 Wildfly content repository 中,它是否被分配到服务器组,以及它是否被启用或禁用。
绝妙的解决方案
当我们谈到部署到一个 Wildfly 域时,我们希望完成两项任务:
- 在 Wildfly 内容存储库中创建或更新 WAR 文件的内容。
- 可以选择将 WAR 文件分配给处于启用或禁用状态的服务器组。
这个 Groovy 脚本通过几个命令行参数公开了这些任务。在幕后,做了大量的工作来允许部署根据需要重新运行多次,并利用 Spring retry 框架来确保部署确实到达了 Wildfly 服务器。
利用 Octopus Deploy 的力量
我们可以使用两种方法将文件放入 Wildfly 域控制器。
第一种方法是通过管理界面将文件直接上传到 Wildfly 服务器。在这种情况下,Wildfly 服务器将在公共 IP 地址上公开其管理端口,而 Octopus Deploy 服务器本身将运行脚本,将文件上传到 Wildfly 服务器。
这种解决方案有一些缺点。
- 这些文件的上传没有经过优化,这意味着当您上传 100 MB 的 WAR 文件时,您必须在每次重新部署时发送该数据的每个字节。
- 您的 Wildfly 服务器需要在公共 IP 地址上公开管理接口。
- 运行脚本的负担放在 Octopus Deploy 服务器上
第二种方法是通过 Octopus deploy package 步骤将文件分发到 Wildfly 服务器,然后使用 CLI 工具的本地副本将文件上传到运行在同一实例上的 Wildfly 服务器。
这个解决方案解决了第一种情况的缺点。
- 通过 Octopus Deploy 分发的文件可以利用增量复制。这意味着可能只复制包中已更改的部分,从而减少网络流量并缩短部署时间。
- Wildfly 服务器只需要将其管理接口暴露给本地主机适配器,因为所有 CLI 命令都将从本地服务器运行。
- Octopus Deploy 服务器只负责复制文件和脚本,而 Wildfly 服务器本身将在本地运行脚本。
鉴于第二种方法的明显优势,这就是我们将如何进行。
先决条件
Wildfly 域控制器服务器需要安装以下软件包:
- Groovy,由将部署 WAR 文件的脚本使用。
- 章鱼部署乌贼所用的单色。
使用 SDKMAN 安装 Groovy。它通常比您的 Linux 发行版附带的软件包做得更好。
您需要将一个 WAR 文件打包并推送到 Octopus Deploy 服务器。参见关于部署到 Tomcat 的博文,了解如何打包一个 WAR 文件并将其推送到 Octopus。
您还需要将 Wildfly 域控制器添加到 Octopus 环境中。正如我们在 Tomcat 示例中所做的,Wildfly 服务器很可能使用 SSH 连接。
最后,Wildfly 服务器需要将 Groovy 脚本和jboss-cli.xml文件复制到一个位置,该位置可以被章鱼用来连接 Wildfly 服务器的 SSH 用户访问。我把https://github.com/OctopusDeploy/JBossDeployment.git回购克隆到了/opt,所以所有的文件都在/opt/JBossDeployment下。
部署到 Wildfly 域控制器
将包部署到 Wildfly 将是一个两步的过程。
部署包
第一步将利用Deploy a package步骤将 WAR 文件放到 Wildfly 域控制器文件系统中。点击Configure features链接,勾选Custom installation directory选项。
然后在Install to字段中定义保存 WAR 文件的目录。我用过目录/var/deployments。
确保 Octopus 连接到 Wildfly 服务器的 SSH 用户拥有将文件复制到该目录的权限,否则该步骤将失败。
运行脚本
第二步将利用Run a Script步骤从 Bash 启动 Groovy 脚本。
将Run on选项设置为Deployment targets,选择Bash作为脚本类型,并输入以下内容作为脚本体:
cd /opt/JBossDeployment
./deploy-app.groovy --controller=localhost --user=user --password=password --application=/var/deployments/demo.war --enabled-server-group=main-server-group
脚本第一次运行可能需要几分钟,因为它将下载 Maven 依赖项(由 Groovy 脚本中的@Grab注释引用)并将它们存储在本地缓存中。
如果您想查看下载进度,请像这样运行脚本:
cd /opt/JBossDeployment
groovy -Dgroovy.grape.report.downloads=true deploy-app.groovy --user=user --password=password --application=/var/deployments/demo.war --enabled-server-group=main-server-group
一旦下载了所有的依赖项,部署脚本将把 WAR 文件上传到 Wildfly,将其添加到main-server-group服务器组,并启用它。
部署到独立的 Wildfly 实例
为独立 Wildfly 实例部署包的过程与部署到域控制器非常相似。唯一的区别是传递给 Groovy 脚本的参数。
因为独立服务器没有服务器组的概念,所以删除了参数enabled-server-group。否则所有步骤保持不变。
cd /opt/JBossDeployment
./deploy-app.groovy --controller=localhost --user=user --password=password --application=/var/deployments/demo.war
后续步骤
我们将使用像这里的脚本这样的实验来指导 Octopus 将来对 Java 和 Wildfly 这样的应用服务器的支持。在接下来的几周里,我们将为计划中的 Java 支持准备一份 RFC,如果您对 Java 支持感兴趣,我们将非常感谢您的反馈。
将证书部署到 WildFly - Octopus 部署
Octopus Deploy 最近增加的一个功能是能够在您的基础设施中管理和部署证书。在这篇博文中,我将向您展示如何将证书从 Octopus 导出到 Java 密钥库中,然后使用该密钥库来保护运行在 Windows 上的 WildFly 独立实例或域实例。
先决条件
要运行这篇博文中的命令和脚本,您需要安装一些工具。
第一个是 OpenSSL 客户机。我使用了来自 Shining Light Productions 的 Windows OpenSSL 二进制文件。
第二个是 Groovy SDK。你可以从 Groovy 下载页面下载安装程序。
这些步骤用 WildFly 11.0.0.Alpha1 进行了测试。
最后,你还需要安装 Java 8 JDK。
创建证书存储
首先,我们需要将证书和私钥对上传到 Octopus Deploy 中。最简单的方法是创建一个自签名证书和私钥,然后将它们合并到一个 PKCS12 密钥库中。
要创建私钥和证书,请运行以下命令:
openssl req -x509 -newkey rsa:2048 -keyout private.pem -out certificate.pem -days 356
系统会提示您提供密码并填写一些个人信息,之后会创建两个文件:private.pem和certificate.pem。这些文件是私钥和证书。
然后,我们需要将这两个文件组合成一个 PKCS12 密钥库,我们可以使用以下命令来完成:
openssl pkcs12 -export -in certificate.pem -inkey private.pem -out combined.pfx -name octopus
combined.pfx文件现在包含证书和私钥,可以上传到 Octopus Deploy。
导出证书存储
既然证书是由 Octopus 管理的,我们需要创建一个带有自定义脚本步骤的项目,以便将证书放到我们的 WildFly 服务器上。
首先,我们需要通过变量引用证书。在 Octopus 项目的Variables部分,创建一个名为Certificate的新变量,该变量引用刚刚上传的证书。
【T2 
创建这个变量使我们能够访问证书中保存的信息的种不同表示。
下面的脚本将证书和私钥作为 PEM 文件保存在目标服务器上,将它们合并到组合的 PKCS12 密钥库,然后将 PKCS12 密钥库导入到 Java 密钥库中。
作为我们 Java RFC 的一部分,将这个证书直接公开为 Java 密钥库是我们打算包含在 Octopus 中的一个特性。但是今天,我们必须使用一个手动脚本来提取证书细节并将其导入到 Java 密钥库中。
这个脚本的最终结果是一个名为c:\keystore.jks的文件,它是我们可以从 WildFly 引用的 Java 密钥库,以启用 HTTPS 支持。
if ([String]::IsNullOrWhiteSpace($OctopusParameters["Certificate.CertificatePem"])) {
Write-Error "Certificate is empty"
}
if ([String]::IsNullOrWhiteSpace($OctopusParameters["Certificate.PrivateKeyPem"])) {
Write-Error "Private key is empty"
}
$OctopusParameters["Certificate.CertificatePem"] | Out-File -Encoding ASCII "C:\certificate.pem"
$OctopusParameters["Certificate.PrivateKeyPem"] | Out-File -Encoding ASCII "C:\private.pem"
# Fix the error
# WARNING: can't open config file: /usr/local/ssl/openssl.cnf
$env:OPENSSL_CONF="C:\OpenSSL-Win64\bin\openssl.cfg"
C:\OpenSSL-Win64\bin\openssl.exe pkcs12 -export -inkey C:\private.pem -in C:\certificate.pem -name octopus -out C:\keystore.pfx -password pass:Password01
if (Test-Path C:\keystore.jks) {
rm C:\keystore.jks
}
C:\Java\x86\jdk1.8.0_131\bin\keytool -importkeystore -srckeystore C:\keystore.pfx -srcstoretype pkcs12 -destkeystore C:\keystore.jks -storepass Password01 -srcstorepass Password01 -noprompt
在 WildFly 中配置 HTTPS 支持
在我们开始配置 WildFly 以利用 Java 密钥库之前,有必要回顾一下我们在 WildFly 中配置 HTTPS 支持的确切含义。
WildFly 有两个 web 界面:客户端用来查看已部署的 Java 应用程序的界面,以及管理界面。两者都可以用 HTTPS 保护,尽管两者的过程略有不同。
此外,WildFly 可以以独立模式部署,也可以作为域部署。同样,为独立服务器和域服务器配置 HTTPS 支持也有细微的区别。
虽然 WildFly CLI 工具功能强大,并公开了配置 HTTPS 支持所需的所有功能,但它的运行级别较低,不包括像configureHTTPS()这样的功能。CLI 工具的一个缺点是它不是等幂的,这意味着使用 CLI 工具配置 WildFly 实例通常需要不同的步骤序列,这取决于服务器的当前状态。
当您从像 Octopus 这样的平台进行部署时,这并不理想。您想要的是有一种方法来描述您希望达到的理想状态(比如“配置 HTTPS”),而不必知道服务器的当前状态。
为了方便起见,我们创建了一个 Groovy 脚本,它隐藏了需要通过 CLI 工具发出的低级命令,以便在 WildFly 中配置(或重新配置)HTTPS 支持。
独立模式下的 HTTPS 支持
要配置具有 HTTPS 支持的独立 WildFly 实例,请运行以下命令:
groovy deploy-certificate.groovy --controller localhost --port 9990 --user admin --password password --keystore-file C:\keystore.jks --keystore-password Password01
用户名和密码需要与您已经用 adduser 脚本配置的相匹配。您可以通过打开 http://localhost:9990 并在提示登录时输入这些凭据来验证这些凭据是否有效。
在后台,脚本首先创建一个名为octopus-ssl-realm的安全领域,它引用密钥库:
<management>
<security-realms>
<security-realm name="octopus-ssl-realm">
<server-identities>
<ssl>
<keystore path="C:\keystore.jks" keystore-password="Password01" alias="octopus" />
</ssl>
</server-identities>
</security-realm>
...
</security-realms>
</management>
然后,它将配置一个引用安全领域的 https 侦听器:
<subsystem >
<server name="default-server">
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true" />
<https-listener name="https" socket-binding="https" security-realm="octopus-ssl-realm" enable-http2="true" />
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content" />
<filter-ref name="server-header" />
<filter-ref name="x-powered-by-header" />
<http-invoker http-authentication-factory="application-http-authentication" />
</host>
</server>
...
</subsystem>
最后,重新启动服务器,以便新设置生效。当你打开 https://localhost:8443/的时候,你会看到 WildFly 现在被你的自签名证书保护了。
保护独立管理界面
保护管理接口可以简单地通过添加--management-interface参数来完成。
groovy deploy-certificate.groovy --controller localhost --port 9990 --user admin --password password --keystore-file C:\keystore.jks --keystore-password Password01 --management-interface
虽然这只是对前一个命令的一个参数更改,但是实际完成的工作有点不同。
首先,从ManagementRealm中引用密钥库:
<security-realm name="ManagementRealm">
<server-identities>
<ssl>
<keystore path="C:\keystore.jks" keystore-password="Password01" alias="octopus" />
</ssl>
</server-identities>
...
</security-realm>
然后,管理界面被更新以包括 https 套接字绑定:
<management-interfaces>
<http-interface security-realm="ManagementRealm">
<http-upgrade enabled="true" />
<socket-binding http="management-http" https="management-https" />
</http-interface>
</management-interfaces>
并再次重启 WildFly 实例以使更改生效。
现在,您可以打开 https://localhost:9993,通过 https 与管理控制台进行交互。
域模式下的 HTTPS 支持
如果您作为域的一部分运行 WildFly,那么使用 HTTPS 保护 web 界面的命令实际上与您在独立模式下运行时是一样的。
但是,关于配置 WildFly 域的成员,有一些重要的事情需要记住。
首先,您运行脚本的控制器是域控制器。在后台,域控制器正在更新两个文件:
- 位于从服务器文件系统上的
host.xml文件(或者当 WildFly 从服务器启动时传递到--host-config选项中的任何文件)。 - 位于域服务器文件系统上的
domain.xml文件(或者当 WildFly 域控制器启动时传递给--domain-config选项的任何文件)。
第二件事是密钥库路径是相对于从属服务器的。因此,在运行这个命令之前,将keystore.jks文件复制到从属服务器是很重要的。
groovy deploy-certificate.groovy --controller domaincontroller --port 9990 --user admin --password password --keystore-file C:\keystore.jks --keystore-password Password01
与独立服务器一样,在域中运行该命令将配置一个安全领域,但是这次是在当前域中所有从属服务器的host.xml文件中。
如果您只想更新特定的主机,请将它们传递给--hosts选项。例如,此命令将更新主机 slave1 和 slave2 的安全领域。
groovy deploy-certificate.groovy --controller domaincontroller --port 9990 --user admin --password password --keystore-file C:\keystore.jks --keystore-password Password01 --hosts slave1,slave2
然后,它在域管理的每个配置文件中配置 https 侦听器。WildFly 自带 4 种配置文件:默认、高可用性、完全和完全高可用性。如果你只想更新特定的配置文件,将它们传递到--profiles选项中。例如,该命令将更新默认配置文件和 ha 配置文件中的 https-listener。
groovy deploy-certificate.groovy --controller domaincontroller --port 9990 --user admin --password password --keystore-file C:\keystore.jks --keystore-password Password01 --profiles ha,default
保护域管理界面
保护域管理接口的命令几乎与保护独立管理接口的命令相同。惟一的变化是添加了--management-port参数,该参数定义了管理控制台将暴露的 https 端口。
groovy deploy-certificate.groovy --controller domaincontroller --port 9990 --user admin --password password --keystore-file C:\keystore.jks --keystore-password Password01 --management-interface --management-port 9993
这将在套接字接口上设置secure-port属性。
<management>
<management-interfaces>
<native-interface security-realm="ManagementRealm">
<socket interface="management" port="${jboss.management.native.port:19999}" />
</native-interface>
<http-interface security-realm="ManagementRealm">
<http-upgrade enabled="true" />
<socket interface="management" port="${jboss.management.http.port:9990}" secure-port="9993" />
</http-interface>
</management-interfaces>
...
</management>
使用 HTTPS 管理界面
一旦使用 HTTPS 保护了管理接口,您就需要在运行脚本时指定remote+https协议,这是通过--protocol参数完成的。例如,此命令在具有 HTTPS 安全管理界面的域控制器上配置 ha 和默认配置文件。
groovy deploy-certificate.groovy --controller domaincontroller --port 9993 --protocol remote+https --user admin --password password --keystore-file C:\keystore.jks --keystore-password Password01 --profiles ha,default
已知问题
似乎偶尔域控制器主机不会正常重新启动。更多详情见https://issues.jboss.org/browse/WFLY-8975。
您可以使用--no-restart选项阻止重启。
groovy deploy-certificate.groovy --controller domaincontroller --port 9990 --user admin --password password --keystore-file C:\keystore.jks --keystore-password Password01 --management-interface --management-port 9993 --no-restart
后续步骤
这些 Groovy 脚本正在被开发,作为最终将被移植到 Octopus Deploy 中直接提供的步骤中的概念验证。
如果你对剧本有任何问题,请留下评论。如果有一些 Java 特性你希望 Octopus 在未来部署支持,请加入 Java RFC 帖子的讨论。
创建一个 WildFly 集群- Octopus 部署
在之前的博客文章中,我们看到了在没有固定 IP 地址或网络广播的 AWS 环境中,如何通过将配置设置集中在 S3 桶中来配置 WildFly 域。
在这篇博文中,我们将通过在 AWS 中配置一个 WildFly 实例集群来进一步进行配置。
域与集群
在我们开始配置集群之前,有必要花点时间讨论一下域和集群之间的区别。
一个域由一个域控制器和一个或多个域从属设备组成。域控制器将设置和应用程序分发给域从属服务器,并提供启动、停止和重新启动从属服务器实例的方法。
域只是一个管理工具。除了简化的管理之外,您不会获得任何额外的功能,因为实例是域的一部分。事实上,您可以使用类似于JBoss Operations Network(JON)的工具来替换一个域。
术语集群可能有歧义,因此对于这篇博文来说,集群意味着共享 Servlet 会话状态的两个或更多 WildFly 实例。共享此状态意味着服务器端 web 应用程序可以由集群中的任何节点提供,如果其中一个节点关闭,请求将由拥有会话状态副本的另一个节点来完成。
尽管从理论上讲,集群允许任何节点响应有状态 web 应用程序的请求,但在实践中,您通常会实现粘性会话来将流量从一个会话定向到单个服务器(只要它可用)。Infinispan 文档谈到了使用粘性会话的性能优势。
域可用于将从属实例配置为集群的一部分,或者域可由不构成集群的多个独立节点组成。同样,WildFly 的多个独立实例可以配置成一个集群。
因此,虽然域和集群都是以某种方式协调的 WildFly 实例组,但这两个术语指的是不同的东西。
配置集群
虽然我们不需要域来配置集群,但域是将公共设置分发到多个 WildFly 从属服务器的一种便捷方式,因此我们将使用域来构建我们的集群。我们将在之前的博文中已经完成的工作的基础上构建一个野域名。
扩展域以支持集群需要许多步骤。
定义中央配置数据库
在构建域时,我们使用了一个共享的 S3 存储桶来帮助发现域控制器。以类似的方式,我们将使用共享数据库来促进集群节点的发现。
因为我们正在 AWS 中部署 WildFly 实例,所以我们将使用 Aurora 数据库作为集群配置的中心点。Aurora 与 MySQL 兼容,这意味着我们将配置 WildFly,就像它正在与 MySQL 数据库通信一样。
添加模式
使用 MySQL 客户端工具,登录 RDS 实例,并创建一个名为jgroups的模式。这是通过命令create database jgroups;完成的:
[ec2-user@ip-172-30-0-89 configuration]$ mysql -ujgroups -p -hyour-rds-hostname.cluster-c1ufrgizkeyf.us-east-1.rds.amazonaws.com
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 15
Server version: 5.6.10 MySQL Community Server (GPL)
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database jgroups;
Query OK, 1 row affected (0.04 sec)
添加 MySQL 驱动程序
在每个 WildFly 从属服务器上,我们需要添加一个包含 MySQL 驱动程序的模块。一个模块只是一个 JAR 文件和一些 WildFly 可以用来加载它们的元数据的集合。
首先创建一个名为modules/system/layers/base/com/mysql/driver/main的目录。在这个目录中,创建一个名为module.xml的文件,内容如下:
<module name="com.mysql.driver">
<resources>
<resource-root path="mysql-connector-java-5.1.44.jar" />
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>
然后将 MySQL 驱动 JAR 文件保存到mysql-connector-java-5.1.44.jar目录下。
添加数据源
RDS 实例将通过数据源进行访问。这在ha轮廓下的domain/confguration/domain.xml文件中定义。<profile name="ha">元素的所有子元素组成了ha概要文件。
为了定义我们的数据源,我们需要一个<datasource>元素(定义数据库连接)和一个<driver>元素(定义 MySQL JDBC 驱动程序细节)。
在本例中,我们将数据源指向一个名为jgroups的模式,并连接一个名为jgroups的用户(尽管这两个值不需要相同):
<subsystem >
<datasources>
<datasource jndi-name="java:jboss/datasources/JGroups" pool-name="JGroupsDS">
<connection-property name="url">
jdbc:mysql://your-rds-hostname.cluster-c1ufrgizkeyf.us-east-1.rds.amazonaws.com/jgroups
</connection-property>
<driver>mysql</driver>
<security>
<user-name>jgroups</user-name>
<password>yourpassword</password>
</security>
</datasource>
<drivers>
<driver name="mysql" module="com.mysql.driver">
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
<datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
定义 JGroups 堆栈
JGroups 是 WildFly 用来连接集群成员的库。默认情况下,JGroups 被配置为使用 UDP 和多播,但是 Amazon 不支持 UDP 和多播。
相反,我们将配置 WildFly 使用 TCP,并利用中央数据库作为发现对等点的方式。
在 JGroups 子系统中,我们将通过更改<channel>元素上的stack属性来切换到tcp堆栈:
<channel name="ee" stack="tcp" cluster="ejb"/>
然后我们需要用JDBC_PING替换MPING协议:
<protocol type="org.jgroups.protocols.JDBC_PING">
<property name="datasource_jndi_name">
java:jboss/datasources/JGroups
</property>
</protocol>
完整的堆栈现在是这样的:
<subsystem >
<channels default="ee">
<!-- We are now using the tcp stack -->
<channel name="ee" stack="tcp" cluster="ejb"/>
</channels>
<stacks>
<stack name="udp">
<transport type="UDP" socket-binding="jgroups-udp"/>
<protocol type="PING"/>
<protocol type="MERGE3"/>
<protocol type="FD_SOCK"/>
<protocol type="FD_ALL"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST3"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
</stack>
<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<!-- MPING has been replaced with JDBC_PING -->
<protocol type="org.jgroups.protocols.JDBC_PING">
<property name="datasource_jndi_name">
java:jboss/datasources/JGroups
</property>
</protocol>
<protocol type="MERGE3"/>
<protocol type="FD_SOCK"/>
<protocol type="FD_ALL"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST3"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
</stack>
</stacks>
</subsystem>
使用ha轮廓
为了利用我们对ha概要文件的更改,需要配置从属实例来使用它。这在<server-groups>元件中进行配置。
更改main-server-group以使用ha轮廓:
<server-group name="main-server-group" profile="ha">
还将服务器组更改为使用full-ha-scokets套接字绑定组:
<socket-binding-group ref="full-ha-sockets"/>
完整的<server-groups>元素现在看起来像这样:
<server-groups>
<!-- main-server-group uses the ha profile -->
<server-group name="main-server-group" profile="ha">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<!-- main-server-group uses the full-ha-sockets socket binding group -->
<socket-binding-group ref="full-ha-sockets"/>
</server-group>
<server-group name="other-server-group" profile="full-ha">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="full-ha-sockets"/>
</server-group>
</server-groups>
打开防火墙
套接字绑定组为 JGroups 使用端口7600,所以这个端口需要在我们的防火墙上打开。
启动奴隶
为了在数据库中注册正确的地址,WildFly 从属实例需要将private接口绑定到外部 NIC 的 IP 地址。这是通过将-bprivate=<ip address>参数传递给domain.sh来完成的。
因为这些从属实例需要为外部世界的流量提供服务,我们还需要将public接口绑定到外部 NIC 的 IP 地址。这是通过将参数-b=<ip address>传递给domain.sh来完成的。
例如,这个命令在 IP 地址为172.30.0.88的 EC2 实例上启动一个从属服务器:
[ec2-user@ip-172-30-0-88 bin]$ ./domain.sh --host-config host-slave.xml -bprivate=172.30.0.88 -b=172.30.0.88
我们不绑定到 EC2 实例的公共 IP 地址(如果它甚至有一个公共 IP 地址的话)。负载均衡器将获取公共互联网流量,并将其定向到 WildFly 绑定的本地子网 IP 地址。
创建负载平衡器
至此,我们已经有了一个配置集群的域。WildFly slave 实例将从域控制器获取它们的配置(通过共享的 S3 桶发现),该配置包括一个 JGroups 堆栈,允许形成一个集群(通过查询一个共享的数据库)。
为了真正利用集群,我们需要一个集中的负载均衡器来在从设备之间分配请求。这很重要,因为代表会话的 cookie 将被绑定到负载平衡器的地址,而不是任何单个节点的地址。这样,由单个 cookie 表示的单个会话在集群成员之间共享。
AWS 提供了一个负载平衡器来完成这项工作。
我们的负载平衡器将针对WildFly目标群体:
该目标组有两个 WildFly 从属实例,并将流量定向到端口8080(wild fly 的默认 HTTP 端口):
我们将使用默认的 WildFly 欢迎页面作为健康检查:
部署可分发的 web 应用程序
为了利用复制会话状态,我们的 Java web 应用程序需要标记为可分发的。这是在带有<distributable/>元素的web.xml文件中完成的。这个示例 web 应用程序已经被配置为可分发的。
这个示例应用程序在会话存储中维护一个页面计数,我们可以使用这个值来确保我们的会话数据实际上是跨集群复制的。
我们将构建这个应用程序,并在整个域中部署它:
打开应用程序
部署好应用程序和我们的负载平衡器后,我们就可以打开应用程序了。每次我们刷新页面,Page count就会增加。这是通过增加会话存储中的值来实现的,会话存储是我们的集群正在复制的存储:
如果我们看一下JSESSIONID cookie,我们可以看到它被绑定到负载平衡器域。这很重要,因为这个 cookie 是我们跟踪会话的方式,而且由于浏览器的工作方式,这个 cookie 只会被发送到创建它的域。通过将 WildFly 服务器隐藏在负载平衡器之后,浏览器不知道哪个集群实例正在响应请求。
然而,如果我们仔细观察 cookie 的值,我们可以看到发起会话的从属实例的 IP 地址是172.30.0.88。该值仅代表启动会话的集群成员,如果不同的集群成员响应后续请求,该值不会改变:
我们可以使用这些信息来关闭托管我们会话的从属服务器,将流量强制转移到第二个从属服务器上。
通过定义host-slave.xml文件中<host>元素的name属性,可以避免从机 IP 地址泄露;
<host name="Slave Name" >
启动会话的群集节点现在关闭,所有流量都转移到群集的另一个成员。但是页面计数将继续从其先前的值攀升,而不会重置为 1,因为复制的会话意味着最终用户可以像什么都没发生一样继续。
验证集群配置
部署了可分发的应用程序后,JGroups 将开始在共享数据库中注册信息。使用 MySQL 客户端,我们可以用show tables;命令登录回数据库并列出我们的jgroups模式中的表。
这里我们可以看到JGROUPSPING表已经创建:
[ec2-user@ip-172-30-0-88 log]$ mysql -u jgroups -p -hyour-rds-hostname.cluster-c1ufrgizkeyf.us-east-1.rds.amazonaws.com
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 5.6.10 MySQL Community Server (GPL)
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use jgroups;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-------------------+
| Tables_in_jgroups |
+-------------------+
| JGROUPSPING |
+-------------------+
1 row in set (0.00 sec)
mysql>
结论
在这篇文章中,我们看到了如何配置一个域来创建一个集群,以及如何允许该集群通过一个共享数据库来识别对等体。然后,该集群通过 AWS 负载平衡器公开。
然后,我们将一个可分发的 web 应用程序部署到域中,并通过关闭创建原始会话的实例,将流量转移到一个新的集群节点上。
如果您对 Java 应用程序的自动化部署感兴趣,下载 Octopus Deploy 的试用版,并查看我们的文档。
了解更多信息
野火 S3 域名发现-章鱼部署
在云环境中配置 WildFly 域时,通常不可能依靠固定的 IP 地址或网络广播来发现资源。为 AWS 用户发现域控制器提供的一个解决方案是使用 S3 桶作为中央配置点。在这篇博文中,我们将看看如何在 AWS 中配置一个简单的 WildFly 域,使用 S3 桶来发现域控制器。
AWS IAM 用户
首先,我们需要一个 IAM 用户,他有权限访问 S3 存储桶。WildFly 将使用该用户的密钥来用域控制器的详细信息更新 S3 桶。
在这个例子中,我们将使用一个名为wildfly-domain的桶。为了授予对这个 bucket 的访问权,WildFly 将使用其密钥的 IAM 用户具有以下安全策略。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1496702015000",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::wildfly-domain",
"arn:aws:s3:::wildfly-domain/*"
]
}
]
}
有了这个策略,我们需要创建访问键。生成Access key ID和Secret access key时记下它们,因为 AWS 不会再向您显示秘密访问密钥。
创建存储桶
S3 水桶本身没什么特别的。它不需要启用任何特殊特性,因此只需创建一个名为安全策略中引用的名称的 bucket(在我们的例子中为wildfly-domain)。
配置域控制器
要配置域控制器以允许从属实例通过 S3 存储桶发现它并进行连接,需要很多步骤。
添加从属用户
我们需要做的第一件事是在域控制器上创建一个用户,从属实例将使用它来连接到域控制器。这是通过bin/add-user.sh脚本完成的。用户:
- 是一个
Management User - 不属于任何团体
- 将用于一个 AS 流程连接到另一个 AS 流程
创建名为slave的用户的输出如下所示。
[ec2-user@ip-172-30-0-89 bin]$ ./add-user.sh
What type of user do you wish to add?
a) Management User (mgmt-users.properties)
b) Application User (application-users.properties)
(a):
Enter the details of the new user to add.
Using realm 'ManagementRealm' as discovered from the existing property files.
Username : slave
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
- The password should be different from the username
- The password should not be one of the following restricted values {root, admin, administrator}
- The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
Password :
Re-enter Password :
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[ ]:
About to add user 'slave' for realm 'ManagementRealm'
Is this correct yes/no? yes
Added user 'slave' to file '/home/ec2-user/wildfly-11.0.0.Final/standalone/configuration/mgmt-users.properties'
Added user 'slave' to file '/home/ec2-user/wildfly-11.0.0.Final/domain/configuration/mgmt-users.properties'
Added user 'slave' with groups to file '/home/ec2-user/wildfly-11.0.0.Final/standalone/configuration/mgmt-groups.properties'
Added user 'slave' with groups to file '/home/ec2-user/wildfly-11.0.0.Final/domain/configuration/mgmt-groups.properties'
Is this new user going to be used for one AS process to connect to another AS process?
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value="UGFzc3dvcmQwMSE=" />
记下这条线
To represent the user add the following to the server-identities definition <secret value="UGFzc3dvcmQwMSE=" />
稍后我们将需要它来配置从属实例。
配置 S3 存储桶
在domain/configuration/host-master.xml文件中,用下面的代码替换<domain-controller>元素的默认内容。该配置指示域控制器在启动时将其详细信息保存在wildfly-domain S3 桶中。
<domain-controller>
<local>
<discovery-options>
<discovery-option name="s3-discovery" code="org.jboss.as.host.controller.discovery.S3Discovery" module="org.jboss.as.host-controller">
<property name="access-key" value="AKIAINKG7EYTNEPL2TBA"/>
<property name="secret-access-key" value="yoursecretkeygoeshere"/>
<property name="location" value="wildfly-domain"/>
</discovery-option>
</discovery-options>
</local>
</domain-controller>
运行域控制器
默认情况下,管理接口绑定到 localhost,在这种情况下,域控制器将尽职尽责地将配置保存在 S3 存储桶中,指示它可以在 127.0.0.1 上访问,当从属服务器在另一个实例上运行时,这显然不是有用的信息。
要解决这个问题,域控制器必须将其管理端口绑定到外部接口。这里,我们用-bmanagement=<ip>参数启动了域控制器,它指示 WildFly 将管理端口绑定到外部 NIC 的 IP 地址。
我们还通过--host-config参数提供了主机配置文件的名称。
[ec2-user@ip-172-30-0-89 bin]$ ./domain.sh --host-config=host-master.xml -bmanagement=172.30.0.89
验证 S3 配置
一旦域控制器已经启动,你会发现新的文件创建在 S3 桶。
配置域从属服务器
要配置从机,我们需要编辑domain/configuration/host-slave.xml文件。
用创建slave用户时由add-users.sh脚本生成的<secret>替换<server-identities>元素的内容。
<server-identities>
<!-- Replace this with either a base64 password of your own, or use a vault with a vault expression -->
<secret value="UGFzc3dvcmQwMSE=" />
</server-identities>
然后用下面的代码替换<domain-controller>元素的内容。
<domain-controller>
<remote security-realm="ManagementRealm" username="slave">
<discovery-options>
<discovery-option name="s3-discovery" code="org.jboss.as.host.controller.discovery.S3Discovery" module="org.jboss.as.host-controller">
<property name="access-key" value="AKIAINKG7EYTNEPL2TBA"/>
<property name="secret-access-key" value="yoursecretkeygoeshere"/>
<property name="location" value="wildfly-domain"/>
</discovery-option>
</discovery-options>
</remote>
</domain-controller>
然后,可以使用命令启动从属实例
./domain.sh --host-config host-slave.xml
在管理控制台中验证域
当域控制器和从控制器都在运行时,我们可以使用管理控制台来查看域的详细信息。打开 http://domaincontrollerip:9990。系统将提示您输入凭据。通常我们会为管理控制台创建一个专用用户,但是为了方便起见,我们可以只使用我们之前创建的slave用户。
在Runtime选项卡下,我们可以看到主主机和从主机确实按照预期连接。
结论
使用 S3 桶作为配置的中心点是在 AWS 中配置 WildFly 域的一种简单、方便和可靠的方式。它消除了对固定 IP 地址的需求,并解决了 AWS 阻止网络广播的限制。
如果您对 Java 应用程序的自动化部署感兴趣,下载 Octopus Deploy 的试用版,并查看我们的文档。
将存储库部署到 WildFly - Octopus 部署
在处理密码等敏感信息时, Octopus Deploy 为您提供加密和保存这些值的能力以确保它们的安全。
如果这些密码是用于数据库服务器之类的外部系统,通常需要解密密码,并将其以纯文本形式存储在某个配置文件中,以便实际使用密码。但是以纯文本的形式保存敏感信息并不理想,因为这使得它容易受到许多简单的攻击,例如在编辑配置文件时监视他人,或者在聊天系统中共享、通过电子邮件发送或发布到帮助论坛,或者检查版本控制系统的历史时捕捉内容文件的内容。
WildFly 通过将敏感信息放入保险库中来缓解这些漏洞。
虽然保险库被认为是安全的,但将敏感信息放入保险库仍然是值得的,因为这意味着配置文件的普通观察者将无法提取密码。
作为为 Java 提供一流支持的举措的一部分,我们正计划提供将 Octopus 变量导出到 WildFly vault 的能力。在这篇博文中,我将向你介绍如何在今天实现这一目标。
导出变量
如果您曾经使用过 WildFly 附带的vault脚本,您会知道要存储在 vault 中的每个值都必须一次添加一个。这很乏味,而且很难维护。为了提供一种更快的方式将安全值放入保险库中,我们编写了一个 Groovy 脚本,它从一个 CSV 文件中获取值。
但是首先我们需要从 Octopus 中获取安全值并保存到一个 CSV 文件中。幸运的是,Powershell 附带了Export-Csv命令,这使得事情变得微不足道。下面的代码可以在 Octopus 的脚本步骤中定义,以将一组键/值对导出到 CSV 文件。然后它调用create-vault.groovy脚本将 CSV 文件转换成 WildFly vault。保险库密码保存在名为VaultPassword的输出变量中,CSV 文件被删除。
try {
# Dump all available variables
# $OctopusParameters.GetEnumerator() | sort-object Name | Export-Csv -Path "C:\variables.csv"
# Dump only a few variables
$variables = @{"wildfly_slave_password" = $wildfly_slave_password}
$variables.GetEnumerator() | Select Key,Value | Export-Csv -Path "C:\variables.csv"
cd C:\Apps\JBossDeployment
$vaultPassword = &groovy create-vault.groovy `
--keystore-file C:\wildfly_dc\wildfly-11.0.0.Alpha1\domain\configuration\keystore.vault `
--keystore-password Password01 `
--enc-dir C:\wildfly_dc\wildfly-11.0.0.Alpha1\domain\configuration\vault `
--csv C:\variables.csv
Set-OctopusVariable -name "VaultPassword" -value $vaultPassword
}
finally {
rm "C:\variables.csv"
}
一旦这个脚本运行,我们将有一个名为C:\wildfly_dc\wildfly-11.0.0.Alpha1\domain\configuration\keystore.vault的文件,一个名为C:\wildfly_dc\wildfly-11.0.0.Alpha1\domain\configuration\vault的目录,以及一个可以用来访问保险库的密码。
您需要首先在所有域节点或独立节点上运行此脚本,以便它们都有一个 vault 的本地副本,可以在下一步中进行配置。
配置存储库
创建了保险库之后,我们现在需要配置 WildFly 来使用它。这是通过将以下 XML 添加到 WildFly 主机配置文件中来完成的。
<vault>
<vault-option name="KEYSTORE_URL" value="C:\wildfly_standalone\wildfly-11.0.0.Alpha1\standalone\configuration\keystore.vault"/>
<vault-option name="KEYSTORE_PASSWORD" value="MASK-223/wEo1GLELe8EuQa5u20"/>
<vault-option name="KEYSTORE_ALIAS" value="vault"/>
<vault-option name="SALT" value="12345678"/>
<vault-option name="ITERATION_COUNT" value="50"/>
<vault-option name="ENC_FILE_DIR" value="C:\wildfly_standalone\wildfly-11.0.0.Alpha1\standalone\configuration\vault\/"/>
</vault>
为了简化这个过程,有另一个 Groovy 脚本将为您添加这个配置。
下面的 Powershell 用于运行 Groovy 脚本并将 vault 配置添加到主机。
您只需要在域控制器上运行这个脚本,而不需要在域从属服务器上运行,因为域控制器会将 vault 配置推送到从属服务器。但是,域控制器不会推出实际的 vault 文件,这就是我们在添加此配置之前在所有主机上创建 vault 文件的原因。
如果您有独立的实例,那么这个脚本将在所有的实例上运行。
cd C:\Apps\JBossDeployment
&groovy deploy-vault.groovy `
--controller localhost `
--port 9990 `
--user admin `
--password password `
--keystore-file C:\wildfly_dc\wildfly-11.0.0.Alpha1\domain\configuration\keystore.vault `
--keystore-password $OctopusParameters["Octopus.Action[Create Vault].Output.VaultPassword"] `
--enc-dir C:\wildfly_dc\wildfly-11.0.0.Alpha1\domain\configuration\vault
访问保险库密码
通过 WildFly 配置文件中的一个特殊变量,可以访问存储库中包含的密码。这里,我们引用了我们的 vault 中别名vault的wildfly_slave_password变量。
<server-identities>
<secret value="${VAULT::vault::wildfly_slave_password::1}"/>
</server-identities>
正如您所看到的,实际的密码不再以纯文本的形式保存,即使这个配置文件被泄露,它也不会泄露一个泄漏的密码。
后续步骤
这些 Groovy 脚本正在被开发,作为最终将被移植到 Octopus Deploy 中直接提供的步骤中的概念验证。
如果你对剧本有任何问题,请留下评论。如果有一些 Java 特性你希望 Octopus 在未来部署支持,请加入 Java RFC 帖子的讨论。
部署 ASP.NET 核心应用程序-它会部署吗?第 1 集-章鱼部署
今天,我们将发布**它会部署吗?**这是我们全新的视频系列,我们尝试使用 Octopus Deploy 自动部署不同的技术。
我们以一个有趣的视频开始这个系列,我们试图将 ASP.NET 核心网络应用部署到微软的 Azure 平台上。光是这一点就很简单,所以我们决定通过自动调配我们的云基础架构并确保零停机生产部署来让它变得更有趣一些。
https://www.youtube.com/embed/tQb8PJ0jzvk
VIDEO
问题
技术堆栈
我们的应用程序是一个报价生成器,名为随机报价。这相当简单,但它将让我们了解如何将 web 应用程序自动部署到 Microsoft Azure 平台。
向我们的营销经理安德鲁致敬,他一直在学习编码并开发了这款应用的第一部分。干得好!
部署目标
解决办法
那么它会部署吗?是的,会的!我们的部署流程如下所示。
第一步是添加一个 Octopus Azure 帐户,该帐户拥有使我能够安全地连接到 Azure 平台所需的所有详细信息。它用于在部署或执行脚本时向 Azure 进行身份验证。
然后,我们添加以下步骤来成功部署我们的应用,包括云基础架构配置和零停机生产部署。
- Octopus 部署 Azure 资源组步骤,通过 ARM 模板供应我们的云基础设施。
- Octopus 运行 Azure Powershell 脚本步骤,以确保我们始终有一个新的应用服务部署位置。我们调用 Azure Powershell cmdlets 来删除和创建应用服务部署槽。
- Octopus 部署 Azure Web App 步骤将我们的 Web 应用程序部署到我们的 App Service staging 部署槽。
- Octopus 运行 Azure Powershell 脚本步骤来交换我们的应用服务阶段和生产(现场)部署槽。这仅在生产部署期间进行,以便我们实现零停机时间!
这个项目使用以下变量来存储我们的资源组名称、网站名称和应用程序设置。简单又好看!
本集的 GitHub repo 包含了本视频中使用的所有资源和链接。
总结
我们希望您喜欢这个新系列,并且我们希望它可以帮助世界各地的人们学习如何自动部署他们的应用程序和服务。
不要忘记订阅我们的 YouTube 频道,因为我们会定期添加新视频。如果你想让我们探索某个框架或技术,请在评论中告诉我们。
愉快的部署!😃
了解更多信息
部署 Spring Boot web 应用程序-它会部署吗?第 2 集-章鱼部署
欢迎来到另一个**它会部署吗?**我们尝试使用 Octopus Deploy 自动部署不同技术的那一集。在这一集中,我们将尝试通过云基础设施配置将 Spring Boot web 应用程序部署到亚马逊 web 服务平台,并确保零停机生产部署。
https://www.youtube.com/embed/Pd2Wya6kvIU
VIDEO
问题
技术堆栈
我们的应用程序是一个报价生成器,名为随机报价。这个应用程序非常简单,但是它让我们演示了如何将 Java web 应用程序部署到 Amazon Web Services 平台。
向我们的营销经理安德鲁致敬,他一直在学习编码并开发了这款应用的第一部分。干得好!
部署目标
解决办法
那么它会部署吗?是的,会的!我们的部署流程如下所示。
第一步是添加一个 Octopus AWS 帐户,其中包括安全可靠地连接到 AWS 平台所需的所有详细信息。它用于在部署或执行脚本时向 AWS 进行身份验证。
然后,我们添加以下步骤来成功部署我们的应用,包括云基础架构配置和零停机生产部署。
- Octopus 传送包步骤将 Spring Boot jar 包传送到 Octopus 服务器。
- Octopus 运行 AWS CLI 脚本步骤,将 web 应用程序包复制到 S3 桶中。
- Octopus 部署 AWS CloudFormation 模板步骤来供应我们的云基础设施,包括创建我们的弹性 Beanstalk 应用程序和两个环境。
- Octopus 运行 AWS CLI 脚本步骤,将我们的 web 应用程序部署到绿色或临时环境中。
- Octopus 运行一个 AWS CLI 脚本步骤来交换 Elastic Beanstalk 应用程序环境 URL,以便我们的绿色(暂存)环境接收我们的蓝色(生产)URL。这仅在生产部署期间执行,以便我们实现零停机时间!
这个项目使用以下变量来存储我们的资源组名称、网站名称和应用程序设置。简单又好看!
本集的 GitHub repo 包含了本视频使用的所有资源和链接。
总结
我们希望你喜欢这一集,因为我们有更多的作品!如果你想让我们探索某个框架或技术,请在评论中告诉我们。
不要忘记订阅我们的 YouTube 频道,因为我们会定期添加新视频。愉快的部署!😃
使用实体框架核心部署到 SQL Server 它会部署吗?第 3 集-章鱼部署
欢迎来到另一个**它会部署吗?**我们尝试使用 Octopus Deploy 自动部署不同技术的那一集。在这一集中,我们尝试使用实体框架核心迁移将 Microsoft SQL Server 数据库部署到 Amazon Web Services (AWS)虚拟机(VM)。
https://www.youtube.com/embed/0XfVDc71OpU
VIDEO
问题
技术堆栈
我们的应用程序是一个报价生成器,名为随机报价。这个应用程序非常简单,但是它允许我们演示如何部署数据库更改和更新。
向我们的营销经理安德鲁致敬,他一直在学习编码并开发了这款应用的第一部分。干得好!
部署目标
解决办法
那么它会部署吗?是的,会的!我们的部署流程如下所示。
然后,我们添加以下步骤来成功部署我们的数据库更改和 web 应用程序。
- Octopus 部署包步骤将我们的数据库脚本复制到我们的数据库部署目标
- Octopus 社区贡献了步骤模板- SQL -执行脚本文件 来针对我们的 SQL Server 数据库执行我们的实体框架核心迁移脚本。
- Octopus 部署到 IIS 部署我们的 ASP.NET 核心 web 应用程序的步骤
该项目使用以下变量来存储我们的应用程序设置、数据库连接详细信息和 web 应用程序配置。
本集的 GitHub repo 包含了本视频中使用的所有资源和链接。
总结
我们希望你喜欢这一集,因为我们有更多的作品!如果你想让我们探索某个框架或技术,请在评论中告诉我们。
不要忘记订阅我们的 YouTube 频道,因为我们会定期添加新视频。愉快的部署!😃
使用 DACPAC 部署到 SQL Server 它会部署吗?第 4 集-章鱼部署
欢迎来到另一个**它会部署吗?**我们尝试使用 Octopus Deploy 自动部署不同技术的那一集。在本集中,我们尝试使用数据层应用程序包(DACPAC)将 Microsoft SQL Server 数据库部署到 Amazon Web Services (AWS)虚拟机(VM)上。
https://www.youtube.com/embed/zGJthrY-qTQ
VIDEO
问题
技术堆栈
我们的应用程序是一个报价生成器,名为随机报价。这个应用程序非常简单,但是它允许我们演示如何部署数据库更改和更新。
向我们的营销经理安德鲁致敬,他一直在学习编码并开发了这款应用的第一部分。干得好!
部署目标
解决办法
那么它会部署吗?是的,会的!我们的部署流程如下所示:
然后,我们添加以下步骤来成功部署我们的应用程序。
- Octopus 部署一个包步骤,将我们的数据库脚本复制到我们的数据库部署目标。
- Octopus 社区贡献的步骤模板-**SQL-Deploy DACPAC**将我们的 DAC PAC 部署到我们的 SQL Server 数据库。
- Octopus 部署到 IIS 部署我们的 ASP.NET 核心 web 应用程序的步骤。
这个项目使用以下变量来存储我们的应用程序设置、数据库连接细节和 web 应用程序配置。
本集的 GitHub repo 包含了本视频中使用的所有资源和链接。
包裹
我们希望你喜欢这一集,因为我们有更多的作品!如果你想让我们探索某个框架或技术,请在评论中告诉我们。
不要忘记订阅我们的 YouTube 频道,因为我们会定期添加新视频。愉快的部署!😃
向多个客户部署多租户 Web 应用程序——它能部署吗?第 5 集-章鱼部署
欢迎来到另一个**它会部署吗?**我们尝试使用 Octopus Deploy 自动部署不同技术的那一集。在这特别的两集节目中,我们试图为运行在亚马逊网络服务(AWS)虚拟机上的不同客户部署一个多租户 SaaS 网络应用。
https://www.youtube.com/embed/KGqlKduFohI
VIDEO
问题
技术堆栈
我们的应用程序是一个报价生成器,名为随机报价。该应用程序相对简单,但它包含许多通用特性,使我们能够说明多租户部署的复杂性。
特点:
- 为每位客户定制应用程序设置
- 应用程序启动时的动态特征/模块加载
- 为每位顾客定制颜色和款式
技术:
向我们的营销经理安德鲁致敬,他一直在学习编码并开发了这款应用的第一部分。干得好!
部署目标
解决办法
那么它会部署吗?是的,会的!我们的部署流程如下所示。
然后,我们添加以下步骤来成功部署我们的应用程序。
- Octopus 部署包步骤将我们的数据库脚本复制到我们的数据库部署目标
- Octopus 社区贡献了 step template-**SQL-Execute Script File**来针对我们的 SQL Server 数据库执行我们的实体框架核心迁移脚本。
- Octopus 部署到 IIS 部署多租户 ASP.NET 核心 web 应用程序的步骤
- Octopus 部署一个包步骤,将管理模块复制到客户的网站,如果他们为此功能付费的话
- Octopus 部署一个包步骤,将共享模块复制到客户的网站,如果他们为该功能付费的话
这个项目使用以下变量,变量模板和公共变量模板来存储我们的应用程序设置,数据库连接细节和 web 应用程序配置。
本集的 GitHub repo 包含了本视频使用的所有资源和链接。
总结
我们希望你喜欢这一集,因为我们有更多的作品!如果你想让我们探索某个框架或技术,请在评论中告诉我们。
不要忘记订阅我们的 YouTube 频道,因为我们会定期添加新视频。愉快的部署!😃
使用 AppVeyor 和 Octopus 将 ASP.NET MVC web 应用程序部署到 Azure 它能部署吗?第 6 集-章鱼部署
欢迎来到另一个**它会部署吗?**我们尝试使用 Octopus Deploy 自动部署不同技术的那一集。在这一集中,我们试图将 ASP.NET MVC 5 web 应用部署到微软 Azure 应用服务。我们还探索与 AppVeyor 和 Octopus 建立基于云的交付管道。
https://www.youtube.com/embed/uIWGd7EUxXE
VIDEO
注:章鱼云即将到来!注册您的兴趣,了解我们基于云的解决方案的最新动态。
问题
技术堆栈
我们的应用程序是一个名为随机报价的随机报价生成器 web 应用程序。这相当简单,但它将让我们了解如何将 ASP.NET MVC web 应用程序自动部署到微软的 Azure 平台上。
向我们的营销经理安德鲁致敬,他一直在学习编码并开发了这款应用的第一部分。干得好!
部署目标
解决办法
那么它会部署吗?是的,会的!
我们基于云的交付渠道如下所示:
我们将源代码提交给 GitHub ,用 AppVeyor 自动构建我们的应用,用 Octopus 部署到微软 Azure 。
把 AppVeyor 和 Octopus 集成起来又快又简单。我们只需选择“Package Web Applications for Octopus deploy”构建选项,并配置一个“Octopus Deploy”部署提供程序。
我们的部署过程如下所示:
我们的部署流程中只有一个步骤,即 Octopus 部署 Azure Web App 步骤,将我们的 Web 应用程序部署到我们的应用程序服务。它的配置非常简单,我们大多使用默认设置。我们确实在部署期间打开了配置变量替换特性来更新我们的web.config文件。
该项目使用以下变量来存储我们的 Azure 资源组名称、网站名称以及一些其他应用程序设置,如横幅背景颜色、发布版本和环境名称。这很简单,但它说明了当我们的 web 应用程序在环境中推广时,我们可以如何更改我们的配置。
本集的 GitHub repo 包含了本视频使用的所有资源和链接。
总结
我们希望你喜欢这一集,因为我们有更多的作品!如果你想让我们探索某个框架或技术,请在评论中告诉我们。
不要忘记订阅我们的 YouTube 频道,我们会定期添加新视频。愉快的部署!😃
了解更多信息
将 ASP.NET 核心网络应用程序部署到 Linux——它能部署吗?第 7 集-章鱼部署
欢迎来到另一个**它会部署吗?**我们尝试使用 Octopus Deploy 自动部署不同技术的那一集。在这一集里,我们试图将 ASP.NET 核心 2.0 网络应用程序部署到亚马逊网络服务(AWS)的 Ubuntu Linux 虚拟机(VM)和 SQL Server for Linux 上。我们还探索与 AppVeyor 和 Octopus 建立基于云的交付管道。
https://www.youtube.com/embed/KhKnb58xOWk
VIDEO
注:章鱼云即将到来!注册您的兴趣,了解我们基于云的解决方案的最新动态。
问题
技术堆栈
我们的应用程序是一个名为随机报价的随机报价生成器 web 应用程序。这相当简单,但它将让我们了解如何将 ASP.NET 核心 web 应用程序和数据库自动部署到运行在 AWS 中的 Ubuntu Linux VM 和 SQL Server for Linux 上。
向我们的营销经理安德鲁致敬,他一直在学习编码并开发了这款应用的第一部分。干得好!
部署目标
解决办法
那么它会部署吗?是的,会的!
我们基于云的交付渠道如下所示:
我们将我们的源代码提交给 GitHub ,用 AppVeyor 自动构建我们的应用,并部署到一个 AWS Ubuntu VM 和 Octopus 。
把 AppVeyor 和 Octopus 集成起来又快又简单。我们使用一个定制的构建脚本来构建和打包我们的应用程序,并配置“Octopus Deploy”部署提供程序来部署它。
我们的部署过程如下所示:
- Octopus 部署一个包步骤,在 Octopus 服务器上获取/解压缩我们的数据库脚本。
- Octopus 社区提供了步骤模板- SQL -执行脚本文件 以针对我们的 SQL Server 数据库执行我们的实体框架核心迁移脚本。
- Octopus 部署一个包步骤将我们的 ASP.NET 核心 web 应用程序部署到我们的 Ubuntu Linux 虚拟机上,并对其进行适当的配置。
这个项目使用以下变量来存储我们的应用程序设置和数据库连接细节。
本集的 GitHub repo 包含了本视频中使用的所有资源和链接。
总结
我们希望你喜欢这一集,因为我们有更多的作品!如果你想让我们探索某个框架或技术,请在评论中告诉我们。
不要忘记订阅我们的 YouTube 频道,我们会定期添加新视频。愉快的部署!😃
了解更多信息
在 Windows Server 2008 上终止对 Octopus 服务器的支持。介绍 Linux 上的 Octopus 服务器!-章鱼部署
原文:https://octopus.com/blog/windows-server-2008-eol-hello-linux
章鱼服务器 2019.3 LTS 将是你可以在 Windows Server 2008 上托管的章鱼服务器的最终版本。
这个决定为真正的跨平台 Octopus 服务器铺平了道路。在不久的将来,你将能够在任何现代的 Windows 或 Linux 操作系统上托管 Octopus 服务器,或者在任一平台上托管一个容器。为此,我们需要将托管 Octopus 服务器的最低要求提高到 Windows Server 2008 R2 。
同样值得注意的是,微软将于 2020 年 1 月结束对 Windows Server 2008 和 2008 R2 的扩展支持,谢天谢地,你可以执行就地升级。如果 Octopus 服务器是您业务中的关键资源,您真的应该考虑将其托管在现代操作系统上,以提高安全性和性能。
这篇博文的其余部分应该回答最常见的问题。一如既往,如果您有任何问题或疑虑,请联系我们的支持团队!愉快的部署!
问题:我会受到影响吗?
只有在以下情况下,您才会受到影响:
- 您在 Windows Server 2008 上托管 Octopus 服务器,并且
- 你想升级 Octopus 服务器超过
2019.3 LTS。
别担心,八达通服务器安装程序会防止你意外升级。如果你想升级 Octopus 服务器,你需要升级你的主机操作系统。
问:我们还能在 Windows Server 2008 R2 上托管 Octopus 服务器吗?
是的,Windows Server 2008 R2 仍将是 Octopus 服务器支持的主机。
尽管微软将于 2020 年 1 月终止对 Windows Server 2008 R2 版的扩展支持,但我们现在没有排除 Windows Server 2008 R2 版的实际理由。
问:我的部署会受到影响吗?
不,您的部署不会因升级 Octopus 服务器超过2019.3 LTS而受到影响。这只影响八达通服务器本身的托管。我们仍然高度向后兼容您在 Octopus 中的部署目标,甚至可以追溯到Windows Server 2003。
问:如何升级我的主机操作系统?
您可以将 Windows Server 2008 操作系统就地升级到更现代的操作系统。了解如何升级 Windows 服务器。
或者,你可以将你的八达通服务器转移到另一台已经运行更现代的操作系统的主机上。了解移动你的章鱼服务器。
问题:你们会支持八达通服务器 2019.3 LTS 和 Windows Server 2008 多久?
我们将根据我们的长期支持计划 继续支持 Octopus 服务器2019.3 LTS,直到 2019 年 10 月。要升级 Octopus 服务器超过2019.3 LTS,您需要将您的主机操作系统升级到 Windows Server 2008 R2 或更新的。
问:什么时候可以在 Linux 上托管 Octopus 服务器?
在不久的将来。我们内部已经在这么做了。Octopus Server 2019.5,我们目前在快车道上发布的版本,将开始引入跨平台功能。在此之后,我们将关注 Linux 上 Octopus 服务器的稳定性和性能,随后是运行在 Linux 上的 Octopus 服务器的完全支持版本。
章鱼亮相 WinOps 2018 伦敦-章鱼部署
技术是任何好的商业策略的关键。您的技术、应用和产品的自动化是关键,没有它,您的业务很快就会变得无关紧要。对你和你的企业来说,成功是什么样的?更频繁地释放?发布更靠谱?消除停机时间?减轻开发团队的压力?
为什么不是全部?
在我的会议中,我将讨论一些现实世界中的 DevOps 实现策略。我将根据自己的经验,展示一些真实的案例研究,包括英国一些最大的公司,以及他们是如何实现 CI/CD 渠道自动化的。
在 Octopus Deploy,我们热衷于自动化所有部署,无论是代码、数据库还是基础设施。这就是为什么我很兴奋地宣布,我, Derek Campbell 将在本月的 WinOp 伦敦活动上继续我们关于“Octopus Deploy 如何实现成功的 DevOps 之旅”的讨论。我将在 11 月 16 日发表演讲,我将展示一些我们客户成功案例的真实例子。
现在注册还来得及!您可以使用代码 Octopus10 注册,享受九折优惠。
如果你已经来了,那么一定要向我和我们的英国客户经理卡尔·麦克唐纳问好,并抢一些章鱼贴纸!
WinOps 2019 - Octopus 讲座和研讨会- Octopus 部署
WinOps London 将于 9 月 23-24 日举行,届时章鱼将会到场!我很高兴地分享我正在领导一个 DevOps 研讨会,并谈论如何使用 Octopus 加速 Azure DevOps 部署。
为您的 CI/CD 管道车间增压
您目前的 CI/CD 渠道是否已经无法满足您的需求?是太慢,手动,还是太多的设置需要调整太频繁?有没有不小心成为“DevOps”的负责人?
不用担心,在这个实践研讨会中,我将带您了解 CI/CD 核心概念和最佳实践,并回顾现实世界中的发布管理和自动化问题以及如何克服它们。
在 2019 年 9 月 23 日为期半天的研讨会期间,您将通过 OctoFX 亲自体验 TeamCity 和章鱼云,这是我们用来演示章鱼的一个示例应用程序。您将配置它的构建,运行自动化测试,设计您的部署过程,并最终在开发、测试和生产环境中推广它。
要求
- 笔记本电脑
- VS 代码或 Visual Studio 2017+
- 现代网络浏览器
配备 Octopus Deploy talk 的涡轮增压 Azure DevOps
在 Octopus Deploy,我们对自动化充满热情,无论是代码、数据库还是基础设施,这就是为什么我们很高兴地宣布,我, Derek Campbell 将在 2019 年 9 月 24 日的 WinOp 伦敦活动上,在我们关于涡轮增压 Azure devo PS with Octopus Deploy的演讲中继续这一讨论。
在本节中,我将带您了解如何使用 Azure DevOps 扩展集成 Azure DevOps 和 Octopus Deploy。然后,我将演示一个 Azure 管道,最后将它传递给 Octopus Deploy,Octopus Deploy 将从单个构建部署到 Azure,并一直测试到生产。
如果你已经来了,那么一定要和团队打招呼,抢一些章鱼贴!
向导、对话框和上下文菜单,还是构建服务器和脚本?-章鱼部署
多年来,我一直热衷于使用持续集成工具。早期是有南特剧本的CruiseControl.NET和天龙,后来是团队城。即使是个人项目,我也喜欢使用 CI 服务器,原因有很多,包括:
- 它确保软件是在不是我的机器上构建的
- 它记得标记版本号,使用正确的发布/调试设置,以及其他我可能会忘记的步骤,使构建更加可靠
- 它确保了如果“构建人员”不在,构建仍然可以进行
- 它们为每个人提供了一个中央仪表盘,让他们知道构建的健康状况
中的每个新的持续集成服务器。NET 空间使得实现自动化构建更加容易。但是在从事 Octopus Deploy 之前,我从未找到一个自动化部署的好解决方案(我认为我们还有很长的路要走,但是我希望我们正在朝着正确的方向前进)。
在 Visual Studio 中,已经在上下文菜单和对话框中投入了数以百计的工时,使得将代码放在开发人员的机器上并放到生产服务器上变得很容易。接受这个对话:

我理解为什么 Visual Studio 中需要这样的工具。而且这些选项可以通过命令行使用(如果你有足够多的山羊可以牺牲),所以自动化它们是可能的。但是,正如依赖开发人员的机器进行构建是错误的一样,从开发人员的机器进行部署也是错误的。
- 如果通常负责“通过 front page Server Extensions from Visual Studio 右键单击并发布到产品”的人不在,会发生什么情况?
- 如果您忘记更改为发布模式或更新连接字符串会发生什么?你记得运行单元测试吗?
- 您如何轻松地回滚到以前的版本,或者找到最后一个好的部署版本?
- 您团队中的其他人如何知道哪个版本处于试运行阶段,或者您正在部署到测试环境中?
这就是为什么对于 Octopus,我们致力于使打包应用程序作为自动化构建和部署的一部分变得容易,最好是在构建服务器上,而不是从您的开发机器上。代替向导、对话框和上下文菜单,我们投资了团队城市插件和 MSBuild 扩展。我们相信鼓励我们的客户遵循良好的实践,比如在构建服务器上自动构建,并让他们很容易做到这一点。

当然,好心没好报,是要付出代价的。你不能在没有至少一个 NuGet 服务器和某种自动化构建过程的情况下,就从 Visual Studio 中的代码到 Octopus 的生产部署。我觉得比较好,但是不像向导和上下文菜单,有个问题:演示的不是很好。仅仅是尝试该产品就可能需要大量的前期投资。
所以我对自己说:Octopus 需要一个向导来打包你在工作站上构建的代码,并部署它吗?我们应该把有限的时间投资在 Visual Studio 插件和发布向导上吗?或者,我们应该投资于更好地构建服务器集成吗?期望人们使用命令行和构建脚本来创建包是不是太过分了?
当您第一次尝试 Octopus 时,您必须完成的第一步是创建一个 NuGet 包。你是怎么做到的?很难吗?它是否几乎让你在第一次部署之前就放弃了这个产品?
我们可以做些什么来使自动化部署更容易开始?
员工友好的自定义步骤模板- Octopus 部署
介绍
2018 年 9 月,Michael Richardson 写了一篇博文介绍了在脚本步骤中引用包的功能。“为什么?”中描述的第二个场景说明在此功能之前,您需要先将包推送到目标,然后脚本任务才能针对提取的内容执行。Michael 继续解释说,这种方法既复杂又不能在 Octopus 服务器或工人上运行。
自定义步骤模板
使用 Michael 的想法,就像运行脚本步骤一样,我们能够从自定义步骤模板中引用包
我们还能够通过将包 ID 分配给步骤模板的一个参数来使被引用的包动态化。
这允许我们引用提取的包文件并对它们做一些事情:
$OctopusParameters["Octopus.Action.Package[$myPackageId].ExtractedPath"]
专门的软件呢?
有时候,仅仅让文件在一个工作人员上可用并不足以使它们与工作人员兼容,比如将 SSIS 包部署到 SQL server。工人将有。它可以使用 ispac 文件,但是它没有安装知道如何使用它的软件。解决这个问题的一个方法是在你所有的员工身上安装这个软件。这增加了复杂性,因为您的所有员工都需要维护,以确保安装和/或更新了正确的软件版本。另一种方法是利用 PowerShell Gallery 在部署时安装必要的 PowerShell 模块。对于 SSIS 的例子,PowerShell 图库中的 SqlServer 模块包含必要的。允许工作人员部署。ispac 到 SQL server。
以下脚本用于演示目的。
使用下面的代码,我们可以检查 worker 是否安装了必要的模块。如果模块不可用,请将指定的版本(如果未指定,则为最新版本)下载到临时文件夹中,并将其包含在内,以便 cmdlets 可用。
首先,在当前工作文件夹中创建临时文件夹:
# Define PowerShell Modules path
$LocalModules = (New-Item "$PSScriptRoot\Modules" -ItemType Directory -Force).FullName
接下来,我们将此文件夹添加到此会话的 PowerShell 模块路径中:
# Add folder to the PowerShell Modules Path
$env:PSModulePath = "$LocalModules;$env:PSModulePath"
现在,让我们定义一个函数来检查是否安装了模块:
function Get-ModuleInstalled
{
# Define parameters
param(
$PowerShellModuleName
)
# Check to see if the module is installed
if ($null -ne (Get-Module -ListAvailable -Name $PowerShellModuleName))
{
# It is installed
return $true
}
else
{
# Module not installed
return $false
}
}
然后一个函数会在它丢失时安装它:
function Install-PowerShellModule
{
# Define parameters
param(
$PowerShellModuleName,
$LocalModulesPath
)
# Save the module in the temporary location
Save-Module -Name $PowerShellModuleName -Path $LocalModulesPath -Force
# Display
Write-Output "Importing module $PowerShellModuleName ..."
# Import the module
Import-Module -Name $PowerShellModuleName
}
最后,我们将定义一个函数来加载。以便可以使用它们的命名空间:
如果将它用于 SqlServer 模块,接下来将向 Get-ChildItem 添加一个 Exclude:
Get-ChildItem -Path $ModulePath -Exclude msv*.dll
Function Load-Assemblies
{
# Declare parameters
param(
$PowerShellModuleName
)
# Get the folder where the module ended up in
$ModulePath = [System.IO.Path]::GetDirectoryName((Get-Module $PowerShellModuleName).Path)
# Loop through the assemblies
foreach($assemblyFile in (Get-ChildItem -Path $ModulePath | Where-Object {$_.Extension -eq ".dll"}))
{
# Load the assembly
[Reflection.Assembly]::LoadFile($assemblyFile.FullName) | Out-Null
}
}
一旦定义了这些,调用我们的函数并在必要时安装:
# Check to see if SqlServer module is installed
if ((Get-ModuleInstalled -PowerShellModuleName "SqlServer") -ne $true)
{
# Display message
Write-Output "PowerShell module SqlServer not present, downloading temporary copy ..."
# Download and install temporary copy
Install-PowerShellModule -PowerShellModuleName "SqlServer" -LocalModulesPath $LocalModules
# Dependent assemblies
Load-Assemblies -PowerShellModuleName "SqlServer"
}
else
{
# Load the IntegrationServices Assembly
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Management.IntegrationServices") | Out-Null # Out-Null supresses a message that would normally be displayed saying it loaded out of GAC
}
对于我们的 SSIS 示例,我们的工作人员现在拥有了部署所需的组件。ispac 文件!
摘要
在这篇文章中,我们学习了如何从一个定制的步骤模板中引用一个包,通过使它成为一个步骤模板参数来使包 ID 引用成为动态的,以及动态地下载和安装 PowerShell 模块来制作工人友好的模板。
更多推荐











































































所有评论(0)