Octopus 博客中文翻译(二十二)

原文:Octopus Blog

协议:CC BY-NC-SA 4.0

Java CI/CD:从 JAR 到 Docker——Octopus 部署

原文:https://octopus.com/blog/java-ci-cd-co/from-jar-to-docker

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本文是展示 Jenkins、Docker 和 Octopus 示例部署管道系列的一部分:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

也许没有哪个公共项目比 Spring PetClinic 更好地展示了一个长寿的 Java 应用程序。它诞生于 21 世纪初,至今仍自豪地出现在 Spring 网站上。

我们的 DevOps 生命周期之旅从本地工作站上 PetClinic 的本地构建开始。在这篇博客文章的结尾,我们已经用 Docker 封装了这个应用程序,提供了一个可重复的构建和执行环境

从本地构建开始

首先,我们克隆 PetClinic GIT 存储库,并使用与应用程序源代码一起签入的 Maven 包装器来构建和运行本地 JAR 文件:

git clone https://github.com/spring-projects/spring-petclinic.git
cd spring-petclinic
./mvnw spring-boot:run 

这个初始构建需要一些时间,因为 Maven 下载了组成应用程序的各种 Spring 库。幸运的是,这些库都被缓存了,所以后续的构建会完成得更快。

要查看该应用程序,请打开 http://localhost:8080:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 * PetClinic 本地运行。*

要创建可分发的 JAR 文件,请运行以下命令:

./mvnw package 

这会运行单元测试,然后在target目录下创建一个独立的 JAR 文件,类似于petclinic.2.3.1.BUILD-SNAPSHOT.jar。我们可以使用以下命令运行该文件:

java -jar .\target\petclinic.2.3.1.BUILD-SNAPSHOT.jar 

这个本地测试、构建和运行的过程是每个应用程序的起点。

公平地说,PetClinic 实现了许多特性来使这些构建可重复,并且结果易于分发。mvnw脚本是 Maven 包装器,它提供了跨平台的脚本,如果本地机器没有安装 Maven 的适当版本,这些脚本可以被签入源代码控制。然后,Spring boot 创建易于版本化、复制和部署的自包含 JAR 文件。

然而,您仍然需要 Java 开发工具包(JDK)来构建应用程序,并且需要 JDK 或 Java 运行时环境(JRE)来运行它。PetClinic 依赖于一个相当老的 Java 版本,鉴于每六个月就会发布一个新的 Java 版本,不难想象开发人员必须修改 Java 安装来执行本地构建。

为了提供一个真正自包含的构建和执行环境,我们将把这个应用程序迁移到 Docker。

用 Docker 进行独立构建和执行

Docker 的主要特性之一是它能够将整个应用程序生态系统捆绑在一个自包含的映像中,该映像可以在一个隔离的环境中运行。对我们来说,这意味着我们可以用所需版本的 Java 和我们编译的应用程序构建和分发 Docker 映像,任何安装了 Docker 的人都可以运行它。

PetClinic repo 的一个分支已经用下面的代码在 GitHub 中创建,以便于访问。

Docker 映像由名为Dockerfile的文件中列出的步骤定义。我们的Dockerfile的内容如下所示:

FROM maven:3.6.3-jdk-8 AS build-env
WORKDIR /app

COPY pom.xml ./
RUN mvn dependency:go-offline
RUN mvn spring-javaformat:help

COPY . ./
RUN mvn spring-javaformat:apply
RUN mvn package -DfinalName=petclinic

FROM openjdk:8-jre-alpine
EXPOSE 8080
WORKDIR /app

COPY --from=build-env /app/target/petclinic.jar ./petclinic.jar
CMD ["/usr/bin/java", "-jar", "/app/petclinic.jar"] 

这个Dockerfile利用了一个叫做多阶段构建的特性。这允许我们创建一个更小的最终 Docker 映像来发布,因为它不包含构建应用程序所需的工具。

我们的构建基于 Maven 团队提供的现有 Docker 映像。这个映像预装了 JDK 和 Maven 工具:

FROM maven:3.6.3-jdk-8 AS build-env 

然后我们创建并移入一个名为/app的目录:

WORKDIR /app 

Maven pom.xml文件被复制到/app目录中:

COPY pom.xml ./ 

然后我们运行 Maven dependency:go-offline目标,它下载了构建应用程序所需的大多数库和 Maven 插件。

由于 Docker 缓存构建的方式,只要pom.xml文件没有改变,该映像的任何后续重建都将重用 Maven 的这次执行所执行的下载。对于 PetClinic 应用程序,这可以节省几分钟时间和数百兆字节:

RUN mvn dependency:go-offline 

Spring 包括一个源代码格式化工具,可以确保所有代码都有一致的风格。我们将调用 help 函数来确保 Maven 下载插件,这意味着 Docker 将依次缓存下载内容。这将为我们节省一次下载和随后的 Docker 映像重建:

RUN mvn spring-javaformat:help 

我们现在可以复制应用程序源代码的其余部分。Docker 检测被复制的源代码何时发生了变化,并从这一步重新运行映像构建过程来捕获变化。但是,所有的应用程序依赖项都已被缓存,因此从这一步开始的构建过程会相对较快:

COPY . ./ 

将源代码从 Windows 工作站复制到 Linux Docker 映像通常会导致格式化插件抱怨行尾。在这里,我们运行格式插件来自动修复复制文件的任何问题:

RUN mvn spring-javaformat:apply 

我们现在可以以 Maven package为目标构建应用程序。注意,我们还将变量finalName设置为petclinic。这将覆盖默认文件名petclinic.2.3.1.BUILD-SNAPSHOT.jar,生成一个名为petclinic.jar的一致文件:

RUN mvn package -DfinalName=petclinic 

我们的应用程序现在已经构建好了,我们进入多阶段构建的下一个阶段,生成我们想要分发的 Docker 映像。这个图像基于 OpenJDK JRE。

JRE 可以运行已编译的应用程序,但不包括编译应用程序所需的工具。这减小了最终图像的尺寸。

FROM openjdk:8-jre-alpine 

我们公开端口8080,这是我们的 Spring 应用程序监听的端口:

EXPOSE 8080 

我们创建并移入一个名为/app的目录:

WORKDIR /app 

在前一阶段编译的 JAR 文件被复制到当前映像中:

COPY --from=build-env /app/target/petclinic.jar ./petclinic.jar 

然后,我们指示映像在运行时执行 JAR 文件:

CMD ["/usr/bin/java", "-jar", "/app/petclinic.jar"] 

要构建 Docker 映像,请运行以下命令:

docker build . -t petclinic 

这将构建 Docker 映像,并给它分配标签petclinic:latest。请注意,如果没有指定其他标签,默认情况下会应用latest

最后,使用以下命令运行 Docker 映像:

docker run petclinic 

和以前一样,这个应用程序可以在 http://localhost:8080 上找到。

我们现在有了一个Dockerfile,它包含了构建和运行我们的应用程序所需的所有步骤。现在,除了 Docker 之外,无需任何其他工具,就可以从源代码构建这个应用程序。我们现在有了一个真正独立的构建过程。

分发 Docker 图像

Docker 图像可以与许多 Docker 注册中心在线共享。最受欢迎的是 Docker Hub ,它为托管公开可用的 Docker 图像提供免费账户。

为了共享 PetClinic Docker 图像,我们需要注册一个 Docker Hub 帐户。我的账号叫mcasperson

创建帐户后,使用命令docker login登录 Docker Hub:

docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: mcasperson
Password:
Login Succeeded 

要分享图片,需要用你的用户名进行标记。在我的例子中,我需要构建一个名为mcasperson/petclinic的映像(其中mcasperson是我的 Docker Hub 用户名):

docker build . -t mcasperson/petclinic 

构建应该会很快完成,因为没有文件被更改,所有步骤都被缓存。

要上传图像,运行以下命令,用您的 Docker Hub 用户名替换mcasperson:

docker push mcasperson/petclinic 

这张照片现在被分享到网上,任何人都可以访问。

要运行公共映像,请执行以下命令:

docker run -p 8080:8080 mcasperson/petclinic 

如果本地没有映像,Docker 将下载它,然后像我们之前做的那样运行它。选项-p 8080:8080明确地将本地端口 8080 映射到容器端口 8080。

结论

在本文中,我们采用了一个典型的 Java 应用程序,并将其封装为 Docker 映像。这张图片被上传到 Docker 注册处,供公众使用。

通过这些改变,我们创建了一个可重复的构建和执行过程,任何人只需安装 Docker 就可以使用。如果我们切换到较新版本的 Java,甚至完全切换语言,应用程序仍然可以用相同的 Docker 命令构建和运行。

虽然 Docker 可以方便地封装构建过程,但不能保证源代码编译成功或测试全部通过。随着越来越多的开发人员开始开发一个应用程序,代码库的健康状况需要由一个中心真实来源共享,这样每个人都知道应用程序的状态。这就是持续集成服务器的用武之地。

在下一篇文章中,我们将配置我们的应用程序,由流行的开源 CI 服务器 Jenkins 构建。

Java CI/CD:从本地构建到 Jenkins 持续集成——Octopus 部署

原文:https://octopus.com/blog/java-ci-cd-co/from-local-to-ci

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本文是展示 Jenkins、Docker 和 Octopus 示例部署管道系列的一部分:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在之前的文章中,我们采用了一个典型的 Java 应用程序,并创建了一个Dockerfile,负责构建代码并运行生成的 JAR 文件。通过利用 Maven 和 Java 本身等工具提供的现有 Docker 映像,我们创建了一个可重复和自包含的构建过程,并且生成的 Docker 映像可以由只安装了 Docker 的任何人执行。

这是我们构建过程的坚实基础。然而,随着越来越多的开发人员开始在共享代码库上工作,测试需求增加,产生的包变大,团队需要一个中央共享服务器来管理构建。这就是持续集成(CI)服务器的作用。

有许多 CI 服务器可用。其中最流行的是 Jenkins ,免费开源。在这篇博文中,我们将学习如何配置 Jenkins 来构建和发布我们的 Docker 映像。

Jenkins 入门

开始使用 Jenkins 最简单的方法是使用他们的 Docker 图像。正如我们在上一篇博文中为自己的应用程序创建了一个自包含映像一样,Jenkins Docker 映像为我们提供了在预配置的自包含环境中启动 Jenkins 的能力,只需几个命令。

首先,我们使用以下命令下载 Jenkins Docker 映像的最新长期支持(LTS)版本:

docker pull jenkins/jenkins:lts 

然后,我们用命令启动 Jenkins:

docker run -p 8081:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts 

-p参数将本地工作站的一个端口绑定到映像公开的一个端口。这里我们使用参数-p 8081:8080将本地端口8081绑定到容器端口8080。注意,因为我们自己的 PetClinic 应用程序在默认情况下也监听端口8080,所以我们为 Jenkins 选择了下一个可用的端口8081。将哪个本地端口映射到容器端口完全取决于您。参数-p 50000:50000公开了 Jenkins 代理使用的一个端口,我们将在后面的文章中配置这个端口来执行我们的构建。

-v参数将 Docker 卷挂载到容器中的路径。虽然 Docker 容器可以在运行时修改数据,但最好假设您将无法保留这些更改。例如,每次您调用docker run(您可以使用 Jenkins Docker 映像的更新版本)时,都会创建一个新的容器,其中没有任何被之前的容器修改过的数据。Docker 卷允许我们通过公开可以在容器之间共享的持久文件系统来保留修改过的数据。在本例中,我们创建了一个名为jenkins_home的卷,并将其挂载到目录/var/jenkins_home中。这意味着所有的 Jenkins 数据都是在一个永久卷中捕获的。

当 Docker 映像运行时,您将看到日志输出。作为初始引导的一部分,Jenkins 生成一个随机密码,并在日志中显示如下:

*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

4b9e47bcd9ea469687dc39f23b0adb08

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************
************************************************************* 

当您打开 http://localhost:8081 时,系统会提示您输入此密码来解锁 Jenkins:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 用生成的密码解锁詹金斯。

Jenkins 会提示你要么安装一个常用插件列表,要么只安装你选择的插件。安装推荐插件选项包含了我们需要的大部分插件。

插件下载需要一分钟左右的时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 插件安装。

完成后,创建第一个管理员用户,点击保存并继续

最后,定义 Jenkins URL 并点击保存并完成

Jenkins 现在已经配置好并可以使用了,只需点击开始使用 Jenkins

创建代理

我们需要解决的一个问题是,我们在 Docker 容器中运行 Jenkins,并且还希望 Jenkins 自己使用 Docker 来构建 Docker 映像。这就产生了一个我们想在 Docker 中使用 Docker 的场景。

在 Docker 中运行 Docker 是可能的,但是我们已经运行的 Jenkins 映像不支持开箱即用。已经创建了许多第三方工具,如 KanikoBuildah ,它们支持在不依赖 Docker 守护进程的情况下构建 Docker 映像。尽管这些解决方案相当先进。

一个更简单的解决方案是在 Jenkins Docker 容器之外运行 Jenkins 代理。该代理将在主机操作系统上运行,并有权访问 Docker 守护程序来创建 Docker 映像。

要创建代理,请单击 管理詹金斯➜管理节点和云 :

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 詹金斯管理选项。

点击新节点链接,给新节点起一个名字,比如 Builder ,点击 OK :

输入远程根目录的路径。因为我在 Windows 上运行节点,所以路径类似于C:\JenkinsAgent。然后输入docker作为节点标签,点击保存:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 配置新节点。

该节点现在在 Jenkins 中进行了配置,但是由于没有节点在运行,所以它显示为断开连接。

如果单击新节点,您将看到一个屏幕,其中提供了运行代理的说明。单击 agent.jar 链接下载代理文件,并运行屏幕上显示的命令将代理连接到 Jenkins:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 连接一个节点的指令。

现在,节点已连接,我们有一个连接到 Jenkins 的代理,它能够构建 Docker 映像。

安装 Docker 管道插件

詹金斯的初始配置安装了一些常用插件。然而,为了构建 Docker 镜像,我们还需要一个叫做 Docker Pipeline 的插件。这是通过 管理詹金斯➜管理插件 并在可用选项卡中搜索 Docker 管道插件来完成的。

下载和安装该插件需要几秒钟时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 下载插件。

添加 DockerHub 凭据

为了允许我们的项目将 Docker 映像发布到 Docker Hub,我们需要在 Jenkins 中定义 Docker Hub 凭证。

  1. 点击 管理詹金斯➜管理凭证 ,导航至凭证部分。
  2. 选择詹金斯,点击全球凭证
  3. 点击添加凭证,进入 Docker Hub 凭证,将 ID 设置为 dockerhub ,点击 OK 按钮:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 定义 Docker Hub 凭证。

我们现在拥有了在 Jenkins 中构建 Docker 映像所需的一切。下一步是定义 Jenkins 项目。

定义詹金斯项目

在高层次上,Jenkins 提供了两种类型的项目。

第一种格式称为自由式项目,在 Jenkins UI 中定义。虽然可以导出和共享自由式项目,但这很难做到,因为底层数据格式不是为手动编辑而设计的。

第二种格式称为管道,本质上是一个脚本,其创建和管理方式与应用程序中的代码非常相似。管道可以与您的项目代码一起保存在一个名为Jenkinsfile的文件中,它将您的应用程序代码和构建定义保存在同一个地方。

我们将为我们的项目创建一个Jenkinsfile,用下面的代码构建并发布我们的 Docker 图像:

pipeline {
    agent {
        label 'docker'
    }
    stages {
        stage('Building our image') {
            steps {
                script {
                    dockerImage = docker.build "mcasperson/petclinic:$BUILD_NUMBER"
                }
            }
        }
        stage('Deploy our image') {
            steps {
                script {
                    // Assume the Docker Hub registry by passing an empty string as the first parameter
                    docker.withRegistry('' , 'dockerhub') {
                        dockerImage.push()
                    }
                }
            }
        }
    }
} 

让我们把这个文件分解一下。

所有声明性管道都以pipeline开头:

pipeline { 

运行这个构建的代理在agent部分中定义。在这里,我们已经将构建配置为在任何带有标签docker的代理上运行。这确保了构建运行在我们的外部节点上,它可以访问 Docker 守护进程,而不是运行在 Jenkins 服务器本身上,它不能访问 Docker:

 agent {
        label 'docker'
    } 

组成流水线的阶段包含在stages部分:

stages { 

第一阶段构建 docker 映像。我们利用脚本步骤调用我们之前安装的 Docker Pipeline 插件来构建映像。这个构建的结果保存在一个名为dockerImage的变量中。注意使用$BUILD_NUMBER变量为每个构建分配一个新版本作为图像标签。这确保了该管道的每次执行都将构建一个新的不同的 Docker 映像:

 stage('Building our image') {
            steps {
                script {
                    dockerImage = docker.build "mcasperson/petclinic:$BUILD_NUMBER"
                }
            }
        } 

第二阶段将新创建的映像推送到 Docker Hub。withRegistry方法将 Docker 注册表作为第一个参数,或者如果它留空,则默认为 Docker Hub。第二个参数是我们之前在 Jenkins 中创建的凭证的名称:

 stage('Deploy our image') {
            steps {
                script {
                    // Assume the Docker Hub registry by passing an empty string as the first parameter
                    docker.withRegistry('' , 'dockerhub') {
                        dockerImage.push()
                    }
                }
            }
        } 

这个文件和我们的应用程序代码一起被提交。下一步是创建一个 Jenkins 项目来检查代码并运行管道。

创建管道项目

在 Jenkins 仪表板上,单击新项目链接。输入 Petclinic 作为项目名称,并选择管道选项:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 新项目创建。

管道部分下,从 SCM 中选择管道脚本,输入 Git 存储库 URL(本例中为https://github.com/mcasperson/spring-petclinic.git)并选择要构建的分支(本例中为 main )。然后点击保存**😗*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 定义管道 GIT 库。

从项目仪表板中,单击 Build Now 链接手动运行一个构建,并单击构建链接图标:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 一个詹金斯项目的构建。

点击控制台输出链接查看构建输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 詹金斯项目构建控制台输出。

当构建完成时,Docker 映像在 Jenkins 节点上构建并被推送到 Docker Hub ,带有基于构建号的标签:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 由此产生的图像出现在 Docker 中枢。

这样,我们就成功地配置了 Jenkins 来编译和测试应用程序代码,然后构建 Docker 映像并将其推送到 Docker Hub。

结论

Jenkins 提供了一个中央平台,多个开发人员可以通过这个平台构建、测试和分发他们的代码。Jenkins 维护更改的历史记录以及这些更改是否导致了成功的构建,维护分发 Docker 映像所需的凭证,并消除个人在每次构建时上传可能很大的 Docker 映像的需要。

在本文中,我们逐步完成了将 Jenkins 作为 Docker 容器运行的过程,连接了一个节点来执行构建,并编写了一个 Jenkins 管道来定义 Jenkins 将如何构建和推送 Docker 映像。这样做的最终结果是一个持续的集成系统,它可以自动构建和发布我们的应用程序,消除了单个开发人员手动管理这个过程的需要。我们实现了持续整合。

下一步是在某个地方部署我们新创建的 Docker 映像。为此,我们将在 AWS 中配置一个 Kubernetes 集群。

浏览 DevOps 工程师手册以了解更多关于持续集成和持续交付(CI/CD)的信息。

有趣的输出变量-章鱼部署

原文:https://octopus.com/blog/fun-with-output-variables

在 Octopus 2.4 中,我们增加了一个步骤中的变量在另一个步骤中可用的能力。例如,您可能有一个名为 StepA 的独立 PowerShell 步骤,它的功能如下:

Set-OctopusVariable -name "TestResult" -value "Passed" 

然后,您可以在后续部署步骤(在同一个部署中)中使用它,如下所示:

$TestResult = $OctopusParameters["Octopus.Action[StepA].Output.TestResult"] 

内置输出变量

在一个步骤运行之后,Octopus 捕获输出变量,并保存它们以供后续步骤使用。除了您自己使用Set-OctopusVariable创建的变量,Octopus 还提供了许多内置变量:

  • 对于 NuGet 包步骤:
    • Octopus.Action[StepName].Output.Package.InstallationDirectoryPath:包部署到的路径。
  • 对于手动干预步骤:
    • Octopus.Action[StepName].Output.Manual.Notes:响应手动步骤输入的注释。
    • Octopus.Action[StepName].Output.Manual.ResponsibleUser.Id
    • Octopus.Action[StepName].Output.Manual.ResponsibleUser.Username
    • Octopus.Action[StepName].Output.Manual.ResponsibleUser.DisplayName
    • Octopus.Action[StepName].Output.Manual.ResponsibleUser.EmailAddress

输出变量的范围和索引

重要的是要记住,与构建服务器不同,Octopus 在许多机器上并行运行各个步骤。这意味着每台机器可能对相同的输出变量产生不同的值。

例如,假设我们有两台机器, App01App02 ,我们在这两台机器上运行这个脚本:

Set-OctopusVariable -name "MyMachineName" -value [System.Environment]::MachineName 

显然,我们将有两个不同的值可用,因为两台机器有不同的主机名。为了处理这一点,Octopus 创建了变量,并将它们限定在一台机器上。在这个例子中,Octopus 将存储两个变量:

Octopus.Action[StepA].Output.MyMachineName = App01     (Scope: App01)  # Value from App01 machine
Octopus.Action[StepA].Output.MyMachineName = App02     (Scope: App02)  # Value from App02 machine 

从现在开始,在这些机器上运行的部署中的任何步骤都将从该机器获得适用的输出变量。这意味着您可以:

$name = $OctopusParameters["Octopus.Action[StepA].Output.MyMachineName"] 

有时,您可能需要从一台机器上访问由另一台机器产生的变量。在这种情况下,Octopus 还存储非作用域变量,这些变量由机器用索引:

Octopus.Action[StepA].Output[App01].MyMachineName = App01              # Value from App01 machine
Octopus.Action[StepA].Output[App02].MyMachineName = App02              # Value from App02 machine 

这意味着,例如在 App03 上运行的后续步骤中,您可以:

$app01Name = $OctopusParameters["Octopus.Action[StepA].Output[App01].MyMachineName"]
$app02Name = $OctopusParameters["Octopus.Action[StepA].Output[App02].MyMachineName"]
# Do something with $app01Name and $app02Name 

记住$OctopusParameters只是一个Dictionary<string,string>。这意味着你可以这样做:

$MatchRegex = "Octopus\.Action\[StepA\]\.Output\[(.*?)\]\.MyMachineName"

Write-Host "Machine names:"
$OctopusParameters.GetEnumerator() | Where-Object { $_.Key -match $MatchRegex } | % { 
  Write-Host "$_.Value"
} 

这里,我们迭代字典中的所有键/值对,并找到与我们的 regex 匹配的键/值对,regex 在变量键的机器名组件上有一个通配符。

查找先前软件包的安装位置

对于输出变量来说,这是一个如此常见的用例,以至于我想显式地调用它。

默认情况下,为了避免各种问题,破坏部署和文件锁,触须自动提取包到一个新的,干净的目录。如果您多次部署完全相同的包,您将会得到类似如下的结果:

C:\Octopus\Applications\Production\MyApp\1.0.0
C:\Octopus\Applications\Production\MyApp\1.0.0_1
C:\Octopus\Applications\Production\MyApp\1.0.0_2
C:\Octopus\Applications\Production\MyApp\1.0.0_3 

假设您部署了一个 NuGet 包,但是想要编写一个独立的 PowerShell 脚本,该脚本在包被提取到的目录中的同一服务器上运行,但是不是 NuGet 包的一部分。你可以用这个:

$packageDir = $OctopusParameters["Octopus.Action[MyApp].Output.Package.InstallationDirectoryPath"]
cd $packageDir

# Do your custom logic 

摘要

应用程序部署通常涉及在许多不同的机器上运行部署包和执行代码。Octopus 中的输出变量提供了一种非常强大的方式来在不同的步骤和不同的机器之间共享这些值。我希望你会发现这个功能很有用!

了解更多信息

集装箱化-你需要什么开始-八达通部署

原文:https://octopus.com/blog/get-started-containers

容器正在成为运行和托管应用程序和微服务的最流行的方式。简而言之,容器是轻量级的虚拟环境,可以运行应用程序,而不需要庞大的完整操作系统。

没有膨胀,容器比传统的基础设施和虚拟机有许多好处,包括:

  • 更好的安全性
  • 很少甚至没有系统维护
  • 易于旋转和拆卸
  • 轻松扩展资源以满足应用需求

可部署的容器映像也使您的应用程序运行起来更加容易。容器映像通常包括您的软件、运行应用程序所需的所有运行时和先决条件,以及由代码设置的任何配置。

多年来,许多公司都有自己的容器图像格式,但是 Docker 的“OCI”图像(现在是开源的)很快成为了行业标准。事实上,许多供应商现在互换使用术语“OCI 图像”和“码头图像”。

OCI 主张开放集装箱倡议。该计划是一个容器结构,作为行业标准格式。技术、开发和云服务领域的大多数主要参与者都支持这项倡议,并支持 OCI 格式。在开放容器倡议网站上了解更多信息。

对于那些不熟悉集装箱化概念的人,让我们从高层次上看一下您需要什么,以及它们是如何组合在一起的。

Docker 桌面

适用于 Windows、Mac 和 Linux 的 Docker Desktop 是开始容器化的最简单方法。

它帮助您从所选的操作系统中执行以下操作:

  • 创建、运行和测试容器就绪应用
  • 构建现成的容器化工具和环境,比如 NGINX、MySQL 或 Ubuntu
  • 管理您的图像并将其发送到存储库和注册表
  • 创建开发环境

在撰写本文时,其中一些功能还处于测试或预览阶段。

在 Windows 上,您可以在 Linux 和 Windows 容器映像之间切换兼容性。在大多数情况下,我们建议使用 Linux 映像,因为很少有托管服务支持本机 Windows 映像。

虽然 Docker Desktop 提供了友好的图形界面,但超过 250 名员工的公司每月都要付费。熟悉命令行的 Linux 用户可以像往常一样继续使用容器。

主办;主持

如果你想在一个容器中运行你的应用程序,你需要一个地方来托管它以便人们访问。许多供应商提供容器托管,而不仅仅是三大巨头微软 Azure、T2、谷歌云和 T4 亚马逊网络服务。

您不局限于云服务,因为大多数主要操作系统都支持 Docker 映像。所以,如果你想在你自己的硬件上运行你的应用,比如服务器或者你自己的测试电脑,你可以。

其他示例托管提供商包括:

集装箱登记处

容器注册中心既是存储库的集合(后面将详细介绍),也是用于管理和部署映像的可搜索目录。

注册表在两个重要方面有所帮助:

  1. 他们确保每个人在搜索时都能获得正确版本的软件,无论他们身在何处。
  2. 部署过程使用注册表从存储库中调用正确的映像。

市场上有大量的注册中心,它们都有不同的优势,例如:

  • 私有注册表
  • 地理位置
  • 流行的公共注册表
  • 内部选项
  • 与管道其他区域的兼容性

当你选择一个主机提供商时,你可能会被锁定在一个特定的注册表中。

示例容器注册表包括:

集装箱仓库

注册中心对您的图像进行分类,容器存储库存储这些图像以备部署。通常,您的注册中心供应商会在平面图上提供您的存储库存储空间。

部署您的应用程序时,您的流程将:

  • 检查注册表中的正确版本
  • 从存储库中提取图像
  • 将映像部署到托管服务上新启动的容器中

要部署的东西

如果您想尝试容器化,您需要部署一些东西。如果你没有合适的,我们会帮你的。

章鱼水下应用是一个简单的 JavaScript 应用,帮助你测试不同服务提供商的集装箱化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看看它是如何工作的

Terence 在我们最近的 CI 系列中写了一篇优秀的容器部署指南,展示了这些概念是如何结合在一起的。

他的指南将带您了解完整的流程,包括:

  • 克隆章鱼水下应用的 GitHub 库
  • 建立码头工人形象
  • 将图像添加到谷歌云的注册和存储服务中
  • 从 Google 云注册表部署到 Azure Kubernetes 集群

下一步是什么?

在这篇文章中,我们探索了使容器化应用成为可能的基本组件。我们还有更多关于集装箱化的帖子,包括:

  • 您应该考虑的注册中心
  • 更详细地看集装箱化的好处
  • 微服务的良好平台
  • 深入探讨云流程编排和云自动化
  • 看看“一切都是代码”

愉快的部署!

从 SSISDB 导入变量- Octopus Deploy

原文:https://octopus.com/blog/get-variables-from-ssisdb

介绍

如果您曾经使用过从包中部署 ispac SSIS 项目或从引用的包中部署 ispac SSIS 项目步骤模板,那么您会知道它可以从您的 SSIS 包中提取项目参数和连接管理器信息,并在 SSISDB 中将它们创建为环境变量。您还知道,在执行此操作时,连接管理器的每个属性都被创建为一个单独的环境变量。如果您的 Octopus 项目中没有同名的变量,您会得到一条消息:

OctopusParameters 集合为空或 CM。OctoDemoSql . adventureworks 2017 . sa . connectusingmanagedidentity 不在集合中

该变量仍在 SSISDB 环境中创建,但是,它默认为设计时值。如果您的 SSIS 包有大量的项目参数和/或连接管理器,那么变量列表会非常庞大,老实说,一个一个地创建是非常乏味的。

自动化拯救世界!

作为从一个包部署 ispac SSIS 项目的最初作者,我可以告诉你,我的 SSIS 开发人员拿着干草叉和火把敲我办公室的门,咆哮着说创建所有这些变量是多么耗时。为了避免死于他们眼中的匕首,我求助于 PowerShell 和 Octopus Deploy API,想出一种方法来从 SSISDB 环境中检索变量,并将它们导入到他们的 Octopus Deploy 项目中。

剧本

以下脚本用于演示目的。

下面的脚本从 SSISDB 环境中提取变量和值,并在 Octopus Deploy 中将它们创建为项目变量!这节省了大量的时间,开发人员满意地离开了我的办公室,他们的要求得到了满足。

# Define parameters
param(
    $OctopusServerUrl,
    $APIKey
)

# Define functions
Function Get-EnvironmentVariablesFromSSISDB
{
    # Define parameters
    param(
        $UseIntegratedAuthentication,
        $SqlUserName,
        $SqlPassword,
        $CatalogName,
        $FolderName,
        $EnvironmentName,
        $SqlServerName
    )

    # Import needed assemblies
    [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

    # Create a connection to the server
    $sqlConnectionString = "Data Source=$SqlServerName;Initial Catalog=master;"

    # Check authentication
    if ($UseIntegratedAuthentication)
    {
        # Add integrated
        $sqlConnectionString += "Integrated Security=SSPI;"
    }
    else
    {
        # ass username password
        $sqlConnectionString += "User ID=$SqlUserName; Password=$SqlPassword"    
    }

    $sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString

    # create integration services object
    $integrationServices = New-Object "$ISNamespace.IntegrationServices" $sqlConnection

    try
    {
        # get catalog reference
        $Catalog = Get-Catalog -CatalogName $CataLogName -IntegrationServices $integrationServices
        $Folder = Get-Folder -FolderName $FolderName -Catalog $Catalog
        $Environment = Get-Environment -Folder $Folder -EnvironmentName $EnvironmentName

        # return environment variables
        return $Environment.Variables
    }
    finally
    {
        # close connection
        $sqlConnection.Close()
    }
}

Function Get-Folder
{
    # parameters
    Param($FolderName, $Catalog)

    # try to get reference to folder
    $Folder = $Catalog.Folders[$FolderName]

    # check to see if $Folder has a value
    if(!$Folder)
    {
        Write-Error "Folder not found."
        throw
    }

    # return the folde reference
    return $Folder
}

Function Get-Environment
{
    # define parameters
    Param($Folder, $EnvironmentName)

    # get reference to Environment
    $Environment = $Folder.Environments[$EnvironmentName]

    # check to see if it's a null reference
    if(!$Environment)
    {
        Write-Error "Environment not found."
        throw
    }

    # return the environment
    return $Environment
}

Function Get-Catalog
{
    # define parameters
    Param ($CatalogName, $IntegrationServices)

    # define working varaibles
    $Catalog = $null

    # check to see if there are any catalogs
    if($integrationServices.Catalogs.Count -gt 0 -and $integrationServices.Catalogs[$CatalogName])
    {
        # get reference to catalog
        $Catalog = $integrationServices.Catalogs[$CatalogName]
    }
    else
    {
        Write-Error  "Catalog $CataLogName does not exist or the Tentacle account does not have access to it."

        # throw error
        throw
    }

    # return the catalog
    return $Catalog
}

Function Get-OctopusProject
{
    # Define parameters
    param(
        $OctopusServerUrl,
        $ApiKey,
        $ProjectName
    )

    # Call API to get all projects, then filter on name
    $octopusProject = Invoke-RestMethod -Method "get" -Uri "$OctopusServerUrl/api/projects/all" -Headers @{"X-Octopus-ApiKey"="$ApiKey"}

    # return the specific project
    return ($octopusProject | Where-Object {$_.Name -eq $ProjectName})
}

Function Get-OctopusProjectVariables
{
    # Define parameters
    param(
        $OctopusDeployProject,
        $OctopusServerUrl,
        $ApiKey
    )

    # Get reference to the variable list
    return (Invoke-RestMethod -Method "get" -Uri "$OctopusServerUrl/api/variables/$($OctopusDeployProject.VariableSetId)" -Headers @{"X-Octopus-ApiKey"="$ApiKey"})
}

Function Update-ProjectVariables
{
    param(
        $OctopusServerUrl,
        $ProjectVariables,
        $ApiKey
    )

    # Convert the object into JSON
    $jsonBody = $ProjectVariables | ConvertTo-Json -Depth 5

    # Call the API to update
    Invoke-RestMethod -Method "put" -Uri "$OctopusServerUrl/api/variables/$($ProjectVariables.Id)" -Body $jsonBody -Headers @{"X-Octopus-ApiKey"="$ApiKey"}
}

try
{
    # Store the IntegrationServices Assembly namespace to avoid typing it every time
    $ISNamespace = "Microsoft.SqlServer.Management.IntegrationServices"
    $CataLogName = "SSISDB"

    # Get reference to project
    $octopusProject = Get-OctopusProject -OctopusServerUrl "<Your URL Here>" -ApiKey "<Your API key here>" -ProjectName "<Octopus Deploy project name>"

    # Get list of existing variables
    $octopusProjectVariables = Get-OctopusProjectVariables -OctopusDeployProject $octopusProject -OctopusServerUrl "<Your URL Here>" -ApiKey "<Your API key here>"

    # Get list of SSIS project variables
    $ssisEnvironmentVariables = Get-EnvironmentVariablesFromSSISDB -UseIntegratedAuthentication $false -SqlServerName "<Sql server name>" -SqlUserName "<sql account user name>" -SqlPassword "<sql account password>" -CatalogName "SSISDB" -FolderName "<SSISDB folder name>" -EnvironmentName "<SSISDB environment name>"

    # Loop through the ssis variable set
    foreach ($variable in $ssisEnvironmentVariables)
    {
        # Check to see if variable already exists in Octopus project variables
        if ($null -eq ($octopusProjectVariables.Variables | Where-Object {$_.Name -eq $variable.Name}))
        {
            # Display message
            Write-Output "Adding $($variable.Name) to Octopus Deploy project $($octopusProject.Name)"

            # Create new variable hash table
            $newVariable = @{
                #Id = "$(New-Guid)"
                Name = "$($variable.Name)"
                Value = "$($variable.Value)"
                Description = $null
                Scope = @{}
                IsEditable = $(if ($variable.Sensitive) { $false} else {$true})
                Prompt = $null
                Type = "String"
                IsSensitive = $(if ($variable.Sensitive) { $true} else {$false})
            }

            # Add variable
            $octopusProjectVariables.Variables += $newVariable
        }
    }

    # Update the project
    Update-ProjectVariables -ProjectVariables $octopusProjectVariables -ApiKey $APIKey -OctopusServerUrl $OctopusServerUrl
}
catch
{
    Write-Error $_.Exception.Message

    throw
} 

摘要

在本文中,我向您展示了一种快速填充 Octopus Deploy 项目变量的方法,方法是连接到 SSISDB 并复制环境变量。该解决方案要求至少部署一次 SSIS 包,以便在 SSISDB 中填充环境变量。虽然这个例子是特定于 SSISDB 的,但是使用 API 以编程方式向 Octopus Deploy 项目添加变量的一般方法可以用于各种各样的源。

Bamboo - Octopus 部署入门

原文:https://octopus.com/blog/getting-started-with-bamboo

持续集成(CI)服务器是 CI/CD 流程的重要组成部分。CI 服务器获取一个代码存储库,构建它,并将其推到一个中心位置,在那里像 Octopus 这样的连续交付(CD)工具可以接管和管理部署。

Bamboo 是由 Atlassian 开发的 CI 服务器,可以自动构建和测试软件应用程序。如果您正在开始您的 CI/CD 之旅,从一个简单的用例开始,并有一个可见的结果,会很有帮助。

在本文中,我将向您展示如何构建和推送一个软件构件,Octopus 可以接管它并将其部署到目标环境中。

您将学习如何:

  • 在 Windows 服务器上安装 Bamboo
  • 配置 Bamboo 项目
  • 配置一个 Bamboo 计划来构建 Docker 容器并将其推送到容器注册中心
  • 运行并查看容器图像

正在设置

要关注这篇文章,您需要以下软件和帐户:

在 Windows 服务器上安装 Bamboo

要安装 Bamboo:

  • 注册一个免费试用版,它会给你一个激活密钥
  • 运行安装可执行文件
  • 将安装位置设置为您可以访问的目录,例如C:\Users\Username\Documents(注意,将其设置为 C:\Program files 的默认位置可能会导致权限错误)
  • 设置 Bamboo 主目录,并确保这是一个独立于安装位置的目录,文件夹名为Bamboo-home

安装完成后,运行 Bamboo 服务器:

  • 打开终端并导航到 Bamboo 安装目录
  • 运行bin\start-bamboo.bat
  • 服务器应该在http://localhost:8085/启动

设置用户

在启动屏幕中,会要求您设置一个管理员帐户。填写详细信息并将详细信息存储在密码管理器中。如果你把密码放错了地方,你需要运行一个恢复过程。

代理人

代理是在 Bamboo 中执行工作负载的工人。因为您安装了先决条件技术,所以您可以使用本地机器作为代理进行测试。

要设置本地代理:

  • 在 Bamboo 仪表板中,转到设置图标并选择代理
  • 转到添加本地代理并为其命名
  • 点击添加

设置项目和计划

Bamboo 将您的工作流程组织成项目和计划。一个项目可以包含多个计划,每个计划是一个执行一系列任务的过程。

首先,设置您的第一个项目和计划:

  • 在主菜单中,选择创建,然后选择创建计划
  • 填写您的项目和计划的名称

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在下一个屏幕上,选中显示 Link new repository 的框。

连接到章鱼水下应用程序库

本帖使用章鱼水下 app

要使用此存储库:

  • 把它存入你自己的 GitHub 账户
  • 在 GitHub 的密码设置中,使用一个个人访问令牌来授权 Bamboo 访问你的 GitHub 账户下的存储库
  • 选择主分支
  • 测试连接以确保 Bamboo 连接到这个存储库
  • 点击保存并继续

配置作业

配置作业屏幕上,配置计划为执行您的作业而运行的任务。Bamboo 提供了一套任务步骤供您选择。这些任务执行 CI 路径中的某个步骤,如检出、构建、拉取、推送。

有一个为您预先填写的源代码签出任务。这将链接的 GitHub 存储库签出到 Bamboo 中。

  • 将隔离的构建作为代理环境。这将使用您之前设置的本地代理。

首先,添加构建 Docker 任务:

  • 点击添加任务并搜索Docker
  • 将命令设置为Build a Docker Image
  • 将存储库设置为[Your DockerHub Username]/[The tag of your image]
  • 检查使用位于上下文路径中的现有 docker 文件
  • 点击保存

现在,添加 Push Docker 任务:

  • 点击添加任务并搜索Docker
  • 将命令设置为Push a Docker Image
  • 将存储库设置为[Your DockerHub Username]/[The tag of your image]
  • 检查使用代理的本地凭证
  • 点击保存
  • 点击创建

该计划通过检出代码、构建 Docker 映像并将构建的映像推送到 DockerHub 开始执行

完成后,您会看到一个绿色的勾号框,表示计划成功完成。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

导航到您的 DockerHub 帐户,确认图像已被推送到存储库。

部署步骤

现在映像在 DockerHub 上,任何 CD 工具都可以将它部署到本地或云平台。我们有指南解释如何为以下人员完成此操作:

要在本地查看应用程序:

  • docker pull [Your DockerHub Username]/[The tag of your image]
  • docker run -p 8080:8080 [Your DockerHub Username]/[The tag of your image]
  • http://localhost:8080/

你看到章鱼水下应用程序,你可以了解更多关于 CI/CD 和章鱼的信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

CI 服务器是 CI/CD 流程的重要组成部分,您可以使用许多不同的 CI 服务器和 Octopus Deploy 来完成您的部署。Atlassian 的 Bamboo 允许您构建 Docker 映像并将其推送到 Docker 存储库。

在这篇文章中,你学习了如何安装 Bamboo 和建立一个项目,并计划构建和推送 Octopus 水下应用程序。这是一个简单的入门示例,但使用竹子的方式还有很多。

如果您对更多 CI 服务器资源感兴趣,请查看我们关于 CI 服务器的系列,其中我们重点介绍了 Jenkins、GitHub 操作和基本 CI 概念。

愉快的部署!

Kind 和 Octopus - Octopus 部署入门

原文:https://octopus.com/blog/getting-started-with-kind-and-octopus

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当您第一次开始使用 Kubernetes 时,在部署哪怕是最简单的示例应用程序之前,可用的工具和选项的数量会是一个很大的障碍。与大多数其他平台不同,Kubernetes 不提供可以下载并安装到本地开发 PC 上的标准包。社区用许多选项填补了这一空白,如 MinikubeMicroK8sk3sDocker Desktop with Kubernetes

在这篇博文中,我们将关注。虽然前面提到的任何解决方案都是很好的选择,但我更喜欢 Kind,因为它可以无缝地跨所有主要操作系统工作,并且在 WSL2 中运行良好,这使得 Windows 开发人员可以很容易地在 Windows 和 Linux 之间切换。

安装种类

Kind 创建一个 Kubernetes 集群作为 Docker 容器。想到实现 Kubernetes 平台的 Docker 容器可能有点令人费解,这反过来又编排了更多的 Docker 容器,但在实践中,建立一个友好的 Kubernetes 集群的过程既快又容易。

安装好 Docker 之后,安装 kubectl类可执行文件。kubectl 和 Kind 都是自包含的可执行文件,这意味着它们只需要下载并保存在您的路径下的一个目录中。

然后用命令kind create cluster创建一个集群。这个命令使用名为kind-kind的集群和用户在~/.kube/config创建或更新 Kubernetes 配置文件。下面显示了一个config文件的例子:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSU...
    server: https://127.0.0.1:55827
  name: kind-kind
contexts:
- context:
    cluster: kind-kind
    user: kind-kind
  name: kind-kind
current-context: kind-kind
kind: Config
preferences: {}
users:
- name: kind-kind
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSU...
    client-key-data: LS0tLS1CRUdJTiBSU0EgUF... 

要验证集群是否正在运行,请执行kubectl get nodes。您应该会看到类似这样的输出:

$ kubectl get nodes
NAME                 STATUS   ROLES    AGE    VERSION
kind-control-plane   Ready    master   101s   v1.18.2 

我们现在有了一个本地 Kubernetes 集群,可以进行测试了。

Kind 创建的config文件嵌入了用于保护 API 流量的集群证书,以及用于识别 Kubernetes 用户的客户端密钥和证书。我们需要将这些值提取到可以导入 Octopus 的文件中。

下面的 Bash 和 PowerShell 脚本提取数据,对其进行解码,并将客户端密钥和证书合并到一个 PFX 文件中。这些脚本给了我们两个文件:cluster.crtclient.pfx:

下面是 Bash 脚本:

kubectl config view --raw -o json | jq -r ".users[] | select(.name==\"$1\") | .user[\"client-certificate-data\"]" | base64 -d > client.crt
kubectl config view --raw -o json | jq -r ".users[] | select(.name==\"$1\") | .user[\"client-key-data\"]" | base64 -d > client.key
kubectl config view --raw -o json | jq -r ".clusters[] | select(.name==\"$1\") | .cluster[\"certificate-authority-data\"]" | base64 -d > cluster.crt
openssl pkcs12 -export -in client.crt -inkey client.key -out client.pfx -passout pass:
rm client.crt
rm client.key 

下面是 PowerShell 脚本,其中的openssl可执行文件是从这里的下载的:

param($username)

kubectl config view --raw -o json |
  ConvertFrom-JSON |
  Select-Object -ExpandProperty users |
  ? {$_.name -eq $username} |
  % {
    [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($_.user.'client-certificate-data')) | Out-File -Encoding "ASCII" client.crt
    [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($_.user.'client-key-data')) | Out-File -Encoding "ASCII" client.key
    & "C:\Program Files\OpenSSL-Win64\bin\openssl" pkcs12 -export -in client.crt -inkey client.key -out client.pfx -passout pass:
    rm client.crt
    rm client.key
  }

  kubectl config view --raw -o json |
  ConvertFrom-JSON |
  Select-Object -ExpandProperty clusters |
  ? {$_.name -eq $username} |
  % {
    [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($_.cluster.'certificate-authority-data')) | Out-File -Encoding "ASCII" cluster.crt
  } 

创建章鱼 Kubernetes 目标

文件cluster.crtclient.pfx被上传到八达通证书商店。这里我将这些证书称为类用户类集群证书:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们还需要一个本地环境:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后一步是创建 Kubernetes 目标。该目标使用证书种类用户进行身份验证,使用种类集群证书进行服务器证书授权,使用 https://127.0.0.1:55827 进行集群 URL。这个 URL 来自 Kubernetes config文件中的clusters[].clusters.server字段:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

关于工人的一句话

因为 Kubernetes URL 引用了127.0.0.1(或localhost),所以我们要么需要在本地开发 PC 上运行 Octopus,要么需要在本地 PC 上安装一个 Worker,这允许远程 Octopus 实例通过隧道进入我们的本地 PC。

在下面的截图中,你可以看到触手管理器配置一个工人的一些步骤:

选择一个轮询触手:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将触手配置为工作者:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

向 Octopus 服务器注册员工:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里我们可以看到分配给默认工作线程池的新工作线程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

工作人员就位后,远程 Octopus 服务器上的 Kubernetes 目标现在可以访问我们的本地 Kubernetes 集群:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

我们现在已经成功地用 Kind 创建了一个本地 Kubernetes 集群,从 Kubernetes 配置文件中提取了证书,将证书导入到 Octopus 中,并在 Octopus 中创建了一个 Kubernetes 目标,它通过一个 Worker 连接到我们的本地集群。

从这里,我们可以了解如何使用 Octopus 来部署 Kubernetes 资源。以下博客文章向您展示了如何:

LDAP 身份验证提供者入门- Octopus 部署

原文:https://octopus.com/blog/getting-started-with-ldap-auth-provider

在 Octopus Deploy 2021.2 中,我们增加了轻量级目录访问协议(LDAP) 认证提供者。

在我们的发布公告中了解更多关于 Octopus 2021.2 (Q3)发布的信息。

许多客户希望迁移到 Octopus Linux 容器,但是他们必须通过 Active Directory 进行身份验证。Active Directory 也是一个 LDAP 服务器,这意味着通过新的 LDAP 提供程序,您现在可以使用 Octopus Linux 容器对 Active Directory 进行身份验证。

在本文中,我将带您了解配置 LDAP 身份验证提供者的步骤。在这篇文章结束时,我的 Octopus Deploy 实例将通过 LDAP 认证到我的本地域,devopswalker.local,运行在 Windows Server 2019 上。

本文假设您熟悉目录服务的核心概念。如果您对这些概念不确定,请与您当地的系统管理员联系。

LDAP 背景

LDAP 或轻量级目录访问协议是一种开放的、厂商中立的、行业标准的协议,用于与目录服务器进行交互。

很容易将 LDAP 与目录服务器(如 Active Directory)混淆。LDAP 本身不是目录服务器。它是用于与目录服务器通信的协议,就像http是用于 web 服务器的协议,或者wss是通过套接字与 web 服务器通信的协议。

Active Directory 的默认配置启用 LDAP 支持。如果您在本地运行 Active Directory,您可能已经有一个 LDAP 服务器。

为什么是 LDAP?

有三个主要的使用案例解释了我们为什么添加 LDAP 支持:

  1. 并非所有人都在运行 Active Directory。LDAP 是厂商中立的,所以更多的非微软用户可以利用外部认证。大多数(如果不是全部)目录服务器支持 LDAP。
  2. Active Directory /集成身份验证要求将服务器添加到域中。这不适用于 Octopus Linux 容器。
  3. 使用非 Windows 客户端(特别是 macOS)的用户将拥有与 Windows 客户端相同的体验。有了 Active Directory,如果你在 macOS 上运行的 Chrome 上点击用域名账户按钮登录,你会发现自己陷入了一个无休止的登录提示循环。至少我做到了(而且我没有耐心去修复它)。

使用 LDAP 还有其他优势,比如跨域查询。我推荐阅读《ldap.com》,了解 LDAP 能提供什么和不能提供什么。这是一个灵活的协议,每个目录服务器,无论是 Active Directory 还是 OpenLDAP,都提供了很多功能。

首先保护您的 LDAP 服务器

默认情况下,LDAP 流量不加密。通过监控网络流量,窃听者可以知道你的 LDAP 密码。

在 Octopus Deploy 中配置 LDAP 提供程序之前,请查阅目录服务器的供应商文档,以便通过 SSL 或 TLS 进行通信。

保护 LDAP 服务器不在本文的讨论范围之内,每个供应商都有自己的独特之处。本文的其余部分假设您与系统管理员一起保护了 LDAP 服务器。

了解 DNs

在 LDAP 中,DN(可分辨名称)唯一地标识目录信息树中的条目和位置,就像文件系统中文件的路径。

如前所述,我的领域是devopswalker.local
把它翻译成 LDAP 可以理解的 DN 就是dc=devopswalker,dc=local

存储我的目录服务器的所有用户和组都有一个公共 DNcn=users,dc=devopswalker,dc=local

我的用户账号Bob Walker DN 是cn=Bob Walker,cn=users,dc=devopswalker,dc=local

你需要什么

在配置 LDAP 之前,您需要以下内容:

  • 要查询的服务器的完全限定域名或 FQDN。在我的例子中是DC01.devopswalker.local
  • 要使用的端口号和安全协议。我对我的域控制器和 SSL 使用标准的安全 LDAP 端口 636。
  • 可以执行用户和组查找的服务帐户的用户名和密码。在我的例子中是cn=Octopus Service,cn=users,dc=devopswalker,dc=local
  • 您希望用于用户和组查找的根 DN。在我的例子中,两者都是cn=users,dc=devopswalker,dc=local

使用诸如 Windows ldp.exe 或 LDAP Administrator 之类的工具找到你想要开始的树/森林的最高部分。例如,从根开始dc=devopswalker,dc=local可能会导致性能问题,因为 LDAP 查询被迫遍历数百或数千条记录。要处理的数据越少,查询就越快。由于我的 active directory 配置,所有用户和组都存储在cn=users,dc=devopswalker,dc=local中。您的服务器可能不同。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 Octopus Deploy 中配置 LDAP 身份验证提供程序

导航至配置➜设置➜ LDAP 。在以下字段中输入值:

  • 服务器:输入服务器的 FQDN。
  • 端口:更改端口(如果您的安全端口不同于默认端口)。
  • 安全协议:更改为 SSL 或 StartTLS。
  • 用户名:输入将用于执行用户查找的用户名。可以是[username]@[domain name]也可以是用户的 DN。
  • 用户基本 DN:输入用户的基本 DN,在我的例子中是cn=users,dc=devopswalker,dc=local
  • 组基本 DN:输入您的组的基本 DN,在我的例子中是cn=users,dc=devopswalker,dc=local
  • 已启用:选中复选框以启用该功能。

如前所述,我使用的是运行在 Windows Server 2019 上的 Active Directory。您的根 DN 可能不同。请咨询系统管理员或使用 LDAP 浏览器为您的目录服务找到正确的用户和群组 DNs。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

测试 LDAP 身份验证提供程序

在我配置了 LDAP 身份验证提供者之后,我犯了一个错误,注销并重新登录。我发现了两个简单的测试,我可以不执行认证的舞蹈。

  • 外部用户查找
  • 外部组查找

对于外部用户查找,转到配置➜用户并选择一个用户账户。屏幕加载后,展开登录下的 LDAP 部分,并单击添加登录按钮。

如果一切正常,您会看到一个类似如下的模式窗口:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一开始没看到那个屏幕。相反,我看到了这个:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

错误“无法连接到 LDAP 服务器。如果这种情况再次出现,请咨询您的管理员。错误代码 49 无效凭据”是一个 LDAP 查找错误。我键入了查找用户的密码。

LDAP 还为每个错误代码返回一个数据代码。要找到这些信息,打开你的 Octopus 服务器日志。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于您无法解释的错误,在托管 Octopus Deploy 的同一服务器上使用 LDAP explorer 执行类似的操作。把 Octopus 从等式中去掉,通过 explorer 工具让一切正常工作,然后配置 Octopus Deploy。如果一切都可以通过浏览器工作,而 Octopus Deploy 仍然无法工作,请联系customersuccess@octopus.com寻求更多帮助。

外部组查找类似于外部用户查找。

  • 转到配置➜团队并选择一个团队。
  • 点击按钮添加 LDAP 组并执行搜索。

如果配置正确,您会看到以下消息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果查找失败,请执行与用户查找相同的故障排除。

正在登录

在上述测试成功之后,尝试下一个测试,使用 LDAP 身份验证提供者登录 Octopus。

我创建了一个测试帐户Professor Octopus,并将其添加到了Developers组。

当我第一次尝试以professor.octopus@devopswalker.local的身份登录时,我得到了这个错误:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将用户名改为professor.octopus如预期的那样有效。这是因为默认配置使用sAMAccountName来匹配。新用户已创建并分配给适当的团队。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我更喜欢用professor.octopus@devopswalker.local登录。如果您有类似的偏好(或公司政策),将用户过滤器更改为(&(objectClass=person)(userPrincipalName=*))

在我们的测试中,我们注意到使用user@domain得到的结果不太可靠;但是,您的配置可能与我们的测试环境不同。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我选择了userPrincipalName,因为完全限定名professor.octopus@devopswalker.local存储在我的域控制器中。您的目录服务器可能不同。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

与 Active Directory 身份验证提供程序不同,LDAP 身份验证提供程序更灵活,因为 LDAP 更灵活。不过,这种适应性确实使 LDAP 身份验证提供程序变得更加复杂,所以可能需要进行一些尝试和错误来拨入您的设置。我建议设置一个测试实例来测试所有的 LDAP 认证设置。

拨入设置后,LDAP 鉴定提供程序提供了许多好处。可以将 Octopus Linux 容器与 Active Directory 一起使用,也可以根本不用 Active Directory。

如果你正在使用活动目录,我发现 LDAP 提供者比活动目录更容易使用,因为它是一个开放的标准。我不必担心选择 NTLM 或 Kerberos,或者如何管理托管 Octopus/Active Directory/域控制器关系的 Windows 服务器。

如果您在本地 active directory 上有多个用户帐户,每个帐户在 Octopus 中都有不同的权限,那么注销和登录您的计算机进行测试就不再是问题。LDAP 解决了这些问题,还有许多其他问题。

愉快的部署!

PowerShell 所需状态配置(DSC)入门- Octopus 部署

原文:https://octopus.com/blog/getting-started-with-powershell-dsc

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

PowerShell DSC 是一项非常棒的技术,可以放在您管理基于 Windows 的服务器的工具箱中。这篇文章是一系列文章的一部分:

我们也有关于使用 PowerShell DSC 和 Octopus Deploy 的文章:


无论您是大型组织还是小型组织,使用云基础架构还是机架式服务器,维护服务器的已知状态都是一项挑战。存在一些第三方解决方案,如 Ansible、Chef 和 Puppet,但它们是基于 Linux 的付费产品。对于 Windows 用户,有一个免费的以 Windows 为中心的选项;PowerShell 所需状态配置(DSC)。在这个 PowerShell DSC 教程中,我将向您展示如何开始使用 PowerShell DSC,并提供一些如何使用它的基本示例。

什么是 PowerShell 期望状态配置(DSC)

PowerShell DSC 是一种基础结构代码(IaC)技术,它使用 PowerShell 创建托管对象格式(MOF)文件,Windows Management Instrumentation(WMI)可以使用这些文件来配置计算机。换句话说,PowerShell DSC 使用 PowerShell 以编程方式配置基于 Windows 的计算机。此外,DSC 可以监控已配置资源的状态,以确保您的计算机保持一致。除了监控,DSC 还可以自动纠正系统的配置,使其始终处于所需的状态。

PowerShell!= PowerShell DSC

如果您曾经参加过 PowerShell 的课程,您的讲师可能会提到 PowerShell DSC,但会掩饰地说这是一门完全不同的课程,或者 PowerShell DSC 还有其他课程。DSC 使用 PowerShell 脚本语言,但相似之处仅此而已。

为什么使用 PowerShell DSC

维护基础设施一致性的一种常用方法是为需要启动的不同类型的服务器创建基本映像。需要网络服务器吗?使用 web 服务器映像。需要数据库服务器吗?使用数据库服务器映像。虽然这无疑缩短了用已知/良好的配置供应资源所花费的时间,但是存在一些固有的问题。

例如,当您的首席信息安全官(CISO)更改了您的 web 服务器允许的协议时会发生什么?当然,您可以修复基本映像,或者重新创建所有 web 服务器,或者编写自动化脚本将新的安全配置应用到现有的服务器,但是重新创建服务器或者编写并测试更新脚本可能会花费大量时间,尤其是在您有数百台服务器的情况下。如果新实施的安全标准破坏了与业务合作伙伴的季度接口,该怎么办?现在你必须撤销所有的工作。

使用 PowerShell DSC,您可以定义您想要的状态,所有新的和现有的服务器都可以选择并实现该状态。如果您必须撤销它,只需更改所需的状态即可恢复。

它是如何工作的?

PowerShell DSC 将使用 PowerShell 配置的组件转换成 MOF 文件,供 WMI 用来配置机器。DSC 可以使用两种方法将配置应用到您的机器上;推拉。您还可以使用自动部署工具(如 Octopus Deploy)创建一种混合方法。

推送方法

推送方法可能是最容易开始的方法。这种方法要求用户通过调用Start-DscConfiguration cmdlet 将期望的状态配置推送到服务器。这具有立即开始应用配置的优点。就自动化而言,这种方法的缺点是,如果服务器离线,它将无法应用新的期望状态。这就是拉方法可能是更好的方法的地方。

拉动方法

顾名思义,Pull 方法通过服务器获取所需的状态配置并应用它。这要求您有一个包含服务器配置的拉服务器。这种方法的缺点是需要额外的服务器来托管配置。然后,需要配置已配置的服务器来轮询“拉”服务器,以确定是否有新的 MOF 文件可用。

入门指南

这篇文章是为初学 DSC 的人设计的,所以我们将使用更简单的推送方法开始。对于我们的场景,我们希望确保服务器的配置包括一些 Windows 特性。我们只使用几个例子:

  • 网络服务器
  • 网络管理工具
  • web-默认-文档

如果您想知道我是从哪里得到这些名字的,请使用Get-WindowsFeature cmdlet 获取列表。您也可以使用通配符作为名称,例如Get-WindowsFeature Web*

简单的配置脚本

对于 DSC,我们使用Configuration关键字来定义配置。在本例中,WindowsFeature是我们正在配置的组件。您可以看到我们定义了三个单独的WindowsFeature组件的实例,每个实例对应一个我们想要配置的组件。每个已配置的实例都需要自己唯一的名称,因为该名称在转换为 MOF 文件时用作关键字。您配置的每个组件都有一个Ensure属性,它的值可以是PresentAbsent。当您想确保组件存在时,您可以指定Present。如果您不想在机器上安装组件,您可以指定Absent。对于这个例子,我们希望确保组件安装在服务器上,所以我们为所有组件指定了Present

在我们完成一个Configuration之后,我们像调用一个函数一样调用它,并提供一个OutputPath,这样 DSC 就知道在哪里放置生成的 MOF 文件。对于这个例子,我们将其命名为WebServerConfiguration。DSC Configuration完成后,我们调用Start-DscConfiguration cmdlet 并提供我们生成的 MOF 文件的路径:

Configuration WebServerConfiguration
{  
  Node "localhost"
  {        
    WindowsFeature WebServer
    {
      Name = "Web-Server"
      Ensure = "Present"
    }

    WindowsFeature ManagementTools
    {
      Name = "Web-Mgmt-Tools"
      Ensure = "Present"
    }

    WindowsFeature DefaultDoc
    {
      Name = "Web-Default-Doc"
      Ensure = "Present"
    }
  }
}

WebServerConfiguration -OutputPath "C:\DscConfiguration"

Start-DscConfiguration -Wait -Verbose -Path "C:\DscConfiguration" 

在您的配置运行之后,您应该会看到类似如下的输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

分离节点数据并使脚本更加动态

我们这个简单的例子是非常硬编码的,根本不是动态的。借助 PowerShell DSC,我们能够将配置数据从配置本身中分离出来,并使我们的脚本更加动态。毕竟是 PowerShell😃

DSC 配置数据文件只是一组哈希表,可以包含其他哈希表或数组,通常具有 psd1 文件扩展名。DSC 配置数据必须至少有一个名为AllNodes的密钥。参考微软文档了解更多信息。

让我们将三个 Windows 功能的原始列表放入 DSC 配置数据文件中:

@{
  AllNodes = @(
    @{
      NodeName = $env:COMPUTERNAME
      WindowsFeatures = @(
        @{
          Name = "Web-Server"
          Ensure = "Present"
        },
        @{
          Name = "Web-Mgmt-Tools"
          Ensure = "Present"
        },
        @{
          Name = "Web-Default-Doc"
          Ensure = "Present"
        }
      )
    }
  )
} 

通过分离配置数据,我们可以缩短 DSC PowerShell 脚本并使其更加通用:

Configuration WebServerConfiguration
{  
  Node $AllNodes.NodeName
  {        
    # Loop through the defined features
    ForEach($Feature in $Node.WindowsFeatures)
    {
      # Define component
      WindowsFeature $Feature.Name
      {
        Name = $Feature.Name
        Ensure = $Feature.Ensure
      }
    }
  }
}

WebServerConfiguration -OutputPath "C:\DscConfiguration" -ConfigurationData "C:\DscConfiguration\WebServer.psd1"

Start-DscConfiguration -Wait -Verbose -Path "C:\DscConfiguration" 

在我们的新脚本中有两件事需要注意:

  • WebServerConfiguration的调用现在多了一个参数ConfigurationData。这告诉 DSC 包含要加载的配置数据的文件。
  • 我们可以使用点符号引用 DSC 配置数据文件的属性。

检测漂移

如前所述,DSC 可以检测某样东西是否不再处于所需状态。需要注意的是,DSC 只能检测它被告知要关注的变化。使用我们的示例,如果有人安装了 Web-Ftp-Server Windows 特性,我们的 DSC PowerShell 脚本将不会报告任何内容。然而,如果有人删除了 Web-Default-Doc,DSC 将报告该特性不再处于期望的状态。当 DSC 配置不再处于所需状态时,我们称之为漂移。

要运行当前配置的测试,您可以运行Test-DscConfiguration cmdlet。如果配置处于期望的状态,Test-DscConfiguration返回True,如果发生了漂移,则返回False。传递-Detailed参数将返回漂移内外的资源列表:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们通过运行以下命令来删除 Web-Default-Doc:

Uninstall-WindowsFeature Web-Default-Doc 

运行Test-DscConfiguration -Detailed:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如您所见,机器已经漂移并识别出[windows feature]Default Doc(we b-Default-Doc)不再处于所需状态!

自动校正漂移

您可以将本地配置管理器(LCM)配置为在检测到漂移时自动更正配置。为此,我们在 DSC PowerShell 脚本中放置了一个LocalConfigurationManager节点,并设置了ConfigurationMode属性。ConfigurationMode可以有三个值之一:

  • ApplyOnly:该设置指示 LCM 应用配置,不做任何其他事情。
  • ApplyAndMonitor:该设置指示 LCM 应用配置并定期运行一致性检查(本质上是Test-DscConfiguration)。一致性检查的默认频率是 15 分钟,可以通过设置ConfigurationModeFrequencyMins属性来覆盖。
  • ApplyAndAutoCorrect:该设置指示 LCM 应用配置并定期运行一致性检查。如果一致性检查返回false,LCM 将重新应用配置,使机器回到所需状态。

为了配置 LCM 自动校正漂移,我们将它设置为ApplyAndAutoCorrect:

Configuration WebServerConfiguration
{  
  Node $AllNodes.NodeName
  {
    # Configure the LCM
    LocalConfigurationManager
    {
      ConfigurationMode = "ApplyAndAutoCorrect"
    }        

    # Loop through the defined features
    ForEach($Feature in $Node.WindowsFeatures)
    {
      # Define component
      WindowsFeature $Feature.Name
      {
        Name = $Feature.Name
        Ensure = $Feature.Ensure
      }
    }
  }
}

WebServerConfiguration -OutputPath "C:\DscConfiguration" -ConfigurationData "C:\DscConfiguration\WebServer.psd1"

Start-DscConfiguration -Wait -Verbose -Path "C:\DscConfiguration" 

现在我们的服务器将自动纠正自己每当漂移被检测到!如果您启用了自动漂移校正,请确保您记录了它;否则,你或你团队中的某个人将会试图找出为什么你刚刚删除的东西又回来了!

摘要

这篇博文教程提供了一些关于如何开始使用 PowerShell DSC 的基本信息,以及如何检测和有选择地自动纠正漂移。关于提到的混合方法的例子,请参考本系列的这篇文章,在这篇文章中,我们将 PowerShell DSC 配置为像应用程序一样进行部署。

Octopus Deploy v3 - Octopus Deploy 的 GitHub 动作中的新功能

原文:https://octopus.com/blog/github-actions-for-octopus-deploy-v3

我们在 2021 年 6 月向 GitHub 市场发布了第一组 GitHub 行动。然后在 2022 年 9 月,我们更新了我们的行动,加入了许多新功能

作为我们针对 Octopus Deploy 的 GitHub 动作的第三次迭代的一部分,我们做了进一步的改进,并添加了 5 个新动作。

亮点包括:

在这篇文章中,我从技术上深入探讨了这次迭代的关键变化,并向您展示了使用新动作的示例。

不再需要 Octopus CLI

消除对 Octopus CLI 的依赖是 GitHub 操作的最大架构变化。

我们的操作不再使用 Octopus CLI 来执行工作。相反,它们直接从 TypeScript 与 Octopus API 交互。这意味着您的工作流启动和执行速度比以前快得多。

您仍然可以使用 Octopus CLI,但是如果您只需要使用我们的其他操作,则不再需要将install-Octopus-CLI-action包含在您的工作流中。

如果您有自己需要的脚本,那么install-octopus-CLI-action仍然可供您使用。

安装 Octopus CLI 操作现在安装基于 Go 的 CLI

我们最近将 CLI 实现从 C#转移到了 Go(关于原因的更多信息,请参见构建 Octopus CLI vNext )。Octopus CLI ( octo)将继续得到支持,直到 2023 年年中。实际上,install-Octopus-CLI-action的 v1 会继续安装 Octopus CLI ( octo)。如果您有使用基于 C#的 CLI 的现有工作流,您可以继续使用此操作的 v1。

install-octopus-CLI-actionv3(或更高版本)只会安装新的基于 Go 的 CLI ( octopus)。如果您正在编写新的工作流,我们强烈建议使用 v3。基于 Go 的 CLI ( octopus)具有基于 C#的 CLI 所没有的新特性和改进,但是,也有一些微小的差异。如有必要,这些 CLI 可以同时使用。

环境变量名

为了安全起见,我们提倡在操作中使用环境变量,而不是 CLI 参数。

我们仍然鼓励您使用环境变量来设置敏感值(即 API 键),但是在新版本的操作中,名称已经改变,因为不再是 Octopus CLI 来选择它们。

价值旧变量新变量
Octopus 服务器 URLOCTOPUS_CLI_SERVEROCTOPUS_URL
Octopus API 密钥OCTOPUS_CLI_API_KEYOCTOPUS_API_KEY
章鱼空间名称OCTOPUS_SPACE

部署和运行手册运行操作

GitHub Actions for Octopus Deploy v3 为部署和 runbook 运行引入了 3 项新操作:

创建-释放-动作的 v1 中,我们支持来自 Octopus CLI ( octo)的旧的deploy-to参数。不幸的是,这带来了 Octopus CLI ( octo)支持的所有其他与部署相关的开关。这增加了动作参数,使它们变得复杂和混乱。

作为一个例子,--variable参数经常让人出错。它只适用于为部署设置提示变量的值,但是看起来它可以用于在发布创建期间设置项目变量值。

基于这些参数目前存在的问题,我们在 Octopus Deploy v2 的 GitHub Actions 中删除了它们,以消除混淆。我们的目标是我们现在在 v3 中拥有的,用于排队部署(和 runbooks 运行)的独立动作。

Octopus CLI ( octo)也将是否等待部署完成的概念捆绑到同一个命令中。我们也把它分成了自己的动作。乍一看这似乎有些过分,但是当与 GitHub 动作的其他特性结合使用时,它允许更大的灵活性。我们将在下面的例子中详细讨论这一点。

租赁部署与“标准”部署具有不同的语义。首先,它们支持您可以部署到的环境的不同多样性(标准版可以部署到多个环境,租用版只能部署到一个环境)。为了在动作契约中明确这一点,部署-释放-租赁-动作部署-释放-动作是分开的。

虽然这是这些动作的初始版本,但我们决定将它们发布为 v3,以便更容易将这些新动作作为匹配集进行推理。随着时间的推移,版本会再次出现分歧,因为我们会单独对动作进行修补和更新。

创建 Zip 和 NuGet 包的操作

GitHub Actions for Octopus Deploy v3 引入了 2 个新的包创建操作:

Zip 和 NuGet 包是用于分发和部署软件应用程序的归档文件。

  • Zip 是一种广泛使用的归档格式,可以由许多不同的应用程序打开。
  • NuGet 包是专门为与 Microsoft 开发平台一起使用而设计的,用于分发可以轻松集成到中的库和其他资源。NET 应用程序。

Zip 和 NuGet 包通常用于分发软件,因为它们提供了一种方便有效的方式来打包和分发大量文件。通常,我们观察客户使用 Octopus CLI ( octo)通过pack命令生成包。这些动作消除了这种需求,同时通过 GitHub 动作提供了集成的体验。

链接是一种内置功能

许多动作产生输出,以实现动作的链接。输出如下:

行为输出描述
create-release-actionrelease_number创建的发布号(版本)
deploy-release-actionserver_tasks带有serverTaskIdenvironmentName的 JSON 对象数组
deploy-release-tenanted-actionserver_tasks带有serverTaskIdtenantName的 JSON 对象数组
run-runbook-actionserver_tasks带有serverTaskIdenvironmentNametenantName的对象的 JSON 数组
await-task-actioncompleted_successfully无论任务是否成功完成

在下面的例子中,我们将更详细地展示如何使用 JSON 数组。

await-task-action的输出中,请注意如果任务没有成功完成,操作将失败。然后,如果您想根据部署/运行是否失败和其他失败(比如失去与 Octopus 实例的通信)在工作流中采取不同的行动,您可以使用步骤的结果completed_successfully

常见工作流模式

多合一

一体式是我们看到的使用最广泛的模式,由 CLI 鼓励您做事情的方式驱动。所有行动都是一项工作中的步骤:

- name: Create Zip package 🐙
  id: package
  uses: OctopusDeploy/create-zip-package-action@v3
  with:
    package_id: DemoNetCoreWebAppGHASingleJob
    version: ${{ steps.build.outputs.version }}
    base_path: ${{ steps.build.outputs.output_folder }}
    files: "**/*"
    output_folder: packaged

- uses: actions/upload-artifact@v3
  with:
  name: ${{ steps.package.outputs.package_filename }}
  path: ${{ steps.package.outputs.package_file_path }}

- name: Push a package to Octopus Deploy 🐙
  uses: OctopusDeploy/push-package-action@v3
  with:
    packages: ${{ steps.package.outputs.package_file_path }}

- name: Push build information to Octopus Deploy 🐙
  uses: OctopusDeploy/push-build-information-action@v3
  with:
    version: ${{ steps.build.outputs.version }}
    packages: MyPackage

- name: Create a release in Octopus Deploy 🐙
  uses: OctopusDeploy/create-release-action@v3
  id: "create_release"
  with:
    project: "Pet Shop"
    package_version: ${{ steps.build.outputs.version }}

- name: Deploy the release in Octopus Deploy 🐙
  uses: OctopusDeploy/deploy-release-action@v3
  id: "queue_deployments"
  with:
    project: "Pet Shop"
    release_number: ${{ steps.create_release.outputs.release_number }}
    environments: |
      Development
      Integration

- name: Waiting for 1st deployment in Octopus Deploy 🐙
  uses: OctopusDeploy/await-task-action@v3
  with:
    server_task_id: ${{ fromJson(steps.queue_deployments.outputs.server_tasks)[0].serverTaskId }}

- name: Waiting for 2nd deployment in Octopus Deploy 🐙
  uses: OctopusDeploy/await-task-action@v3
  with:
    server_task_id: ${{ fromJson(steps.queue_deployments.outputs.server_tasks)[1].serverTaskId }} 

GitHub 操作中运行的工作流的输出如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用这种模式有以下好处:

  • 在工作流文件中,步骤相对容易链接在一起(与您在下一个示例中看到的相比)
  • 适合部署到单个环境/租户

这种模式有以下缺点:

  • 在有多个之后,你不能保证它们排队的顺序
  • 您无法一眼看出哪个任务适用于哪个环境
  • 步骤是连续执行的,所以直到第一次部署的等待完成后,第二次部署的等待才开始

将操作分成多个作业

在本例中,我们展示了一个使用多个作业来协调操作的工作流。它既使用了作业,也使用了 GitHub 动作中一个名为矩阵的特性:

jobs:
  build:
    name: Build and unit test code
    runs-on: ubuntu-latest

    outputs:
      version: ${{ steps.build.outputs.version }}
      artifact_name: ${{ steps.package.outputs.package_filename }}

    steps:
      - uses: actions/checkout@v3

      - name: Setup .NET
        uses: actions/setup-dotnet@v2
        with:
          dotnet-version: 6.0.x

      - name: Run Build 🏗
        id: build
        run: |
          # do whatever you do to build your package. Assume this outputs a version variable and the folder where it produced output

      - name: Create Zip package 🐙
        id: package
        uses: OctopusDeploy/create-zip-package-action@v3
        with:
          package_id: MyPackage
          version: ${{ steps.build.outputs.version }}
          base_path: ${{ steps.build.outputs.output_folder }}
          files: "**/*"
          output_folder: packaged

      - uses: actions/upload-artifact@v3
        with:
          name: ${{ steps.package.outputs.package_filename }}
          path: ${{ steps.package.outputs.package_file_path }}

  push:
    name: Push information to Octopus
    needs: build
    runs-on: ubuntu-latest

    env:
      OCTOPUS_URL: ${{ secrets.OCTOPUS_URL }}
      OCTOPUS_API_KEY: ${{ secrets.OCTOPUS_API_KEY }}
      OCTOPUS_SPACE: "Galaxy"

    steps:
      - uses: actions/download-artifact@v3
        with:
          name: MyPackage.${{ needs.build.outputs.version }}
          path: package

      - name: Push a package to Octopus Deploy 🐙
        uses: OctopusDeploy/push-package-action@v3
        with:
          packages: package/MyPackage.${{ needs.build.outputs.version }}.zip

      - name: Push build information to Octopus Deploy 🐙
        uses: OctopusDeploy/push-build-information-action@v3
        with:
          version: ${{ needs.build.outputs.version }}
          packages: MyPackage

  snapshot:
    name: Snapshot information in Octopus
    needs: [build, push]
    runs-on: ubuntu-latest

    outputs:
      release_number: ${{ steps.create_release.outputs.release_number }}

    env:
      OCTOPUS_URL: ${{ secrets.OCTOPUS_URL }}
      OCTOPUS_API_KEY: ${{ secrets.OCTOPUS_API_KEY }}
      OCTOPUS_SPACE: "Galaxy"

    steps:
      - name: Create a release in Octopus Deploy 🐙
        id: "create_release"
        uses: OctopusDeploy/create-release-action@v3
        with:
          project: "Rockets"
          package_version: ${{ needs.build.outputs.version }}

  deploy:
    name: Deploy snapshot using Octopus
    needs: [build, snapshot]
    runs-on: ubuntu-latest

    env:
      OCTOPUS_URL: ${{ secrets.OCTOPUS_URL }}
      OCTOPUS_API_KEY: ${{ secrets.OCTOPUS_API_KEY }}
      OCTOPUS_SPACE: "Galaxy"

    outputs:
      server_tasks: ${{ steps.queue_deployments.outputs.server_tasks }}

    steps:
      - name: Deploy the release in Octopus Deploy 🐙
        uses: OctopusDeploy/deploy-release-tenanted-action@v3
        id: "queue_deployments"
        with:
          project: "Rockets"
          release_number: ${{ needs.snapshot.outputs.release_number }}
          environment: Development
          tenants: Mars
          tenant_tags: |
            planets/gas giants

  wait:
    needs: deploy
    runs-on: ubuntu-latest
    name: ${{ matrix.deployment.tenantName }}

    env:
      OCTOPUS_URL: ${{ secrets.OCTOPUS_URL }}
      OCTOPUS_API_KEY: ${{ secrets.OCTOPUS_API_KEY }}
      OCTOPUS_SPACE: "Galaxy"

    strategy:
      matrix:
        deployment: ${{ fromJson(needs.deploy.outputs.server_tasks) }}

    steps:
      - name: Waiting for deployment in Octopus Deploy 🐙
        uses: OctopusDeploy/await-task-action@v3
        with:
          server_task_id: ${{ matrix.deployment.serverTaskId }} 

GitHub 操作中运行的工作流的输出如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用这种模式有以下好处:

  • 当有多个部署时,很容易确定哪个是哪个
  • 等待任务并行发生(这是 GitHub 动作中矩阵特性发挥作用的时候)
  • 任务出现在图表的可扩展部分,但也作为单独的条目出现在左侧的摘要中(同样使用矩阵)
  • 工作流中的单个作业如果失败,可以重新运行。例如,假设构建了包并推送到 Octopus,但是由于 Octopus 中的配置错误,发布创建失败了。如果您更正了配置,那么您可以从同一点重新运行工作流,而不必重新构建包并再次推送它们(这两种操作都可能是开销很大的操作)

这种模式有以下缺点:

  • 工作流的设置更加复杂——将步骤的输出传递到作业边界需要在 YAML 中做更多的工作
  • 如果只有一次部署,矩阵可能会感觉负担过重

Runbook 运行

执行操作手册类似于部署版本。我们不会在这里提供一个完整的例子,但是我们想指出 action 提供的输出数据的一个特定方面,以及它对矩阵配置的意义。

在前面的示例中,该条目将矩阵作业的名称绑定到来自 JSON 输出数据的租户名称:

name: ${{ matrix.deployment.tenantName }} 

使用 runbook 运行时,输出数据包含tenantNameenvironmentName,因为它允许您一次请求多个这两个值,并为任何与给定环境的给定项目有关联的匹配租户执行。这意味着您的矩阵名称可以这样做,这取决于哪个值对您更重要:

name: ${{ matrix.deployment.tenantName }} - ${{ matrix.deployment.environmentName }} 

或者

name: ${{ matrix.deployment.environmentName }} - ${{ matrix.deployment.tenantName }} 

这很重要,因为在摘要视图中,GitHub Actions UI 会截断长值。将最重要的信息放在最前面会让你一眼就能找到(钻取后你总能看到完整的细节,只需要额外的点击)。

结论

GitHub Actions for Octopus Deploy v3 对 v2 进行了重大改进,阵容中增加了 5 个新动作。这些新操作增强了自动化部署过程、执行任务和创建包的能力。它们还极大地改善了整体用户体验。

我们自己也在使用这些行动,这证明了它们的有效性和可靠性。我们希望这个最新版本通过提供强大的、用户友好的操作来管理您的 GitHub 部署,从而帮助您。

愉快的部署!

宣布 GitHub 对 Octopus Deploy 的操作- Octopus Deploy

原文:https://octopus.com/blog/github-actions-for-octopus-deploy

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们已经为 Octopus Deploy 发布了我们的第一个官方 GitHub 动作。这些初始操作涵盖了将 GitHub 构建与 Octopus 中的部署和 runbook 运行相连接的核心集成场景:

我们计划在今年晚些时候添加更多的 GitHub 动作。

在这篇博文中,我演示了如何开始使用 GitHub Actions 将构建工件推送到 Octopus,创建一个版本,并将其部署到开发环境中。

什么是 GitHub Actions?

GitHub Actions 是一个流行的新平台,用于自动化软件开发工作流,如围绕 GitHub 生态系统构建的 CI/CD。

您使用 YAML 配置文件定义您的工作流,并将其存储在您的 Git 存储库中。您可以用称为操作的可重用构建块来构建自动化。工作流在容器中执行,实现可重复且可靠的流程。

下面是一个 GitHub Action job 工作流的例子。NET web 应用程序。GitHub 提供了大多数编程语言和框架的例子。

name: Build

on:
  push:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Setup .NET
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 5.0.x
    - name: Restore dependencies
      run: dotnet restore
    - name: Build
      run: dotnet publish -o build 
    - name: Test
      run: dotnet test --no-build --verbosity normal 

这个工作流被命名为 build ,每当变更被推送到master分支上的父 Git 仓库时,它就会触发一个单一的作业。准备和执行持续集成构建的步骤包括:

  • 恢复依赖关系
  • 执行构建
  • 运行所有测试

我推荐阅读 GitHub 的文档来了解更多。这篇博文假设您熟悉使用 GitHub 操作构建工作流的基础知识。

Octopus Deploy 的 GitHub 操作入门

为了说明如何为 Octopus 使用新的 GitHub 操作,我们将更新上面的示例构建脚本,以安装 Octopus CLI,打包我们的构建工件并将其推送到 Octopus,然后创建一个发布并将其部署到我们的开发环境中。

完整的工作流文件可以在 GitHub 示例库中找到:

name: Build

on:
  push:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Setup .NET
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 5.0.x
    - name: Restore dependencies
      run: dotnet restore
    - name: Build
      run: dotnet publish -o build 
    - name: Test
      run: dotnet test --no-build --verbosity normal
    - name: Install Octopus CLI 🐙
      uses: OctopusDeploy/install-octopus-cli-action@v1.1.6
      with:
        version: latest
    - name: Package build artifacts
      run: octo pack --id="RandomQuotes" --format="zip" --version="1.0.${{github.run_number}}" --basePath="/home/runner/work/RandomQuotes/RandomQuotes/build/"
    - name: Push packages to Octopus Deploy 🐙
      uses: OctopusDeploy/push-package-action@v1.0.1
      with:
        api_key: ${{ secrets.OCTOPUS_APIKEY }}
        server: ${{ secrets.OCTOPUS_SERVER }}
        packages: "RandomQuotes.1.0.${{github.run_number}}.zip"
    - name: Create a release in Octopus Deploy 🐙
      uses: OctopusDeploy/create-release-action@v1.0.2
      with:
        api_key: ${{ secrets.OCTOPUS_APIKEY }}
        server: ${{ secrets.OCTOPUS_SERVER }}
        project: "Projects-141"
        deploy_to: "Dev" 

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意,我们在这个配置中引用了两个秘密。一个是 Octopus 服务器 URL,另一个是 API 密钥,用于验证和集成 Octopus 实例。在这种情况下,我使用的是一个 Octopus 云实例,然而,如果它是可公开访问的,你也可以连接到一个自托管 Octopus 实例

注意:这是建立一个微软。NET 5 web 应用程序,但也可以是 Spring (Java) web 应用程序或 NodeJS express 服务等。重要的部分是 GitHub 对 Octopus 的操作如何使集成变得容易。

安装 Octopus CLI

 - name: Install Octopus CLI 🐙
      uses: OctopusDeploy/install-octopus-cli-action@v1.1.6
      with:
        version: latest 

要与 Octopus 服务器集成,首先安装 Octopus CLI。这是使用任何其他步骤的先决条件,因为它会使用适当的依赖项引导作业运行器来安装 Octopus CLI。

将构建工件推送到 Octopus

 - name: Pack
      run: octo pack --id="RandomQuotes" --format="zip" --version="1.0.${{github.run_number}}" --basePath="/home/runner/work/RandomQuotes/RandomQuotes/build/" --verbose
    - name: Push a package to Octopus Deploy 🐙
      uses: OctopusDeploy/push-package-action@v1.0.1
      with:
        api_key: ${{ secrets.OCTOPUS_APIKEY }}
        server: ${{ secrets.OCTOPUS_SERVER }}
        packages: "RandomQuotes.1.0.${{github.run_number}}.zip" 

下一步是打包您的构建工件,并将它们推到一个包存储库中。在这种情况下,我们正在推进 Octopus 内置的包存储库,这是一个受欢迎的选择。

打包和推送我的构建工件有两个步骤:

  1. 将我的构建输出打包为 ZIP 文件。
  2. 将包推送到我的 Octopus 实例。

如前所述,我引用了存储在我的存储库配置中的两个秘密。一个是 Octopus 服务器 URL,另一个是我的 GitHub 构建的 API 密钥。

创建一个版本并将其部署到开发环境中

 - name: Create a release in Octopus Deploy 🐙
      uses: OctopusDeploy/create-release-action@v1.0.2
      with:
        api_key: ${{ secrets.OCTOPUS_APIKEY }}
        server: ${{ secrets.OCTOPUS_SERVER }}
        project: "Projects-141"
        deploy_to: "Dev" 

我的构建过程的最后一步是创建我的项目的发布,并将其部署到我的开发环境中。这是一步完成的;我提供了我的项目 ID 和我想要部署到的环境名称。仅此而已。

成功!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们向我们的存储库提交一个 commit,我们可以看到 GitHub 动作的运行及其输出。可能需要几次迭代来修正语法并获得正确的结果,但结果是一个成功的构建。

结论

针对 Octopus Deploy 的 GitHub 操作现已推出。该版本包括安装 Octopus CLI 和将包推送到 Octopus 实例的操作,以及创建和部署版本和执行操作手册的支持。

您现在可以使用 GitHub 操作自动化您的构建,并与 Octopus 集成以满足您所有的部署和 runbook 自动化需求。

我们计划为 Octopus 添加额外的动作。如果你想让我们添加什么,请在评论中告诉我们。

愉快的部署!

使用 GitHub Actions - Octopus Deploy 将包发布到本地 Octopus 实例

原文:https://octopus.com/blog/github-actions-local-runner

今年早些时候,我的同事 Ryan Rousseau 写了一篇关于使用 GitHub Actions 向 Octopus Deploy 发布一个包的博文。在这篇文章中,我将更进一步,发布一个包到一个用自托管 GitHub Actions Runner 部署的本地 Octopus 实例。

GitHub 操作

GitHub Actions 是 GitHub 版本的构建服务器。像许多其他构建工具一样,如 BitBucket PipeLines 和 Azure DevOps,GitHub Actions 使用另一种标记语言(YAML)来定义构建过程,称为工作流。下面是一个 GitHub Actions 工作流 YAML 文件的例子。

该示例构建了 OctoPetShop 示例。NET 核心应用程序,然后将包推送到我们的 Octopus Deploy Samples 实例:

name: .NET Core 

on:
  push:
    branches: [ master ] 
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: ubuntu-latest 

    steps:
    - uses: actions/checkout@v2
    - name: Set Version
      run: echo "::set-env name=PACKAGE_VERSION::$(date +'%Y.%m.%d').$GITHUB_RUN_NUMBER"
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 2.2.207
    - name: Install dependencies
      run: dotnet restore
    - name: Build
      run: dotnet build --configuration Release --no-restore
    - name: Test
      run: dotnet test --no-restore --verbosity normal
    - name: Create artifacts folder
      run: |
        mkdir "$GITHUB_WORKSPACE/artifacts"
        mkdir "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.Database"
        mkdir "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.Web"
        mkdir "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.ProductService"
        mkdir "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.ShoppingCartService"
    - name: Publish OctoPetShopDatabase
      run: dotnet publish OctopusSamples.OctoPetShop.Database/OctopusSamples.OctoPetShop.Database.csproj --configuration Release --no-restore --output "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.Database"
    - name: Publish OctoPetShopWeb
      run: dotnet publish OctopusSamples.OctoPetShop.Web/OctopusSamples.OctoPetShop.Web.csproj --configuration Release --no-restore --output "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.Web"
    - name: Publish OctoPetShopProductService
      run: dotnet publish OctopusSamples.OctoPetShop.ProductService/OctopusSamples.OctoPetShop.ProductService.csproj --configuration Release --no-restore --output "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.ProductService"
    - name: Publish OctoPetShopShoppingCartService
      run: dotnet publish OctopusSamples.OctoPetShop.ShoppingCartService/OctopusSamples.OctoPetShop.ShoppingCartService.csproj --configuration Release --no-restore --output "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetshop.ShoppingCartService"
    - name: Install Octopus CLI
      uses: OctopusDeploy/install-octocli@v1
      with:
        version: 7.4.2
    - name: Package OctoPetShopDatabase
      run: |
        octo pack --id="OctoPetShop.Database" --format="Zip" --version="$PACKAGE_VERSION" --basePath="$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.Database" --outFolder="$GITHUB_WORKSPACE/artifacts"
    - name: Package OctoPetShopWeb
      run: |
        octo pack --id="OctoPetShop.Web" --format="Zip" --version="$PACKAGE_VERSION" --basePath="$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.Web" --outFolder="$GITHUB_WORKSPACE/artifacts"
    - name: Package OctoPetShopProductService
      run: |
        octo pack --id="OctoPetShop.ProductService" --format="Zip" --version="$PACKAGE_VERSION" --basePath="$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.ProductService" --outFolder="$GITHUB_WORKSPACE/artifacts"
    - name: Package OctoPetShopShoppingCartService
      run: |
        octo pack --id="OctoPetShop.ShoppingCartService" --format="Zip" --version="$PACKAGE_VERSION" --basePath="$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetshop.ShoppingCartService" --outFolder="$GITHUB_WORKSPACE/artifacts"
    - name: Push OctoPetShop Database
      run: |
        octo push --package="$GITHUB_WORKSPACE/artifacts/OctoPetShop.Database.$PACKAGE_VERSION.zip" --server="${{ secrets.OCTOPUSSERVERURL }}" --apiKey="${{ secrets.OCTOPUSSERVERAPIKEY }}" --space="${{ secrets.OCTOPUSSERVERSPACE_HYBRID }}"
    - name: Push OctoPetShop Web
      run: |
        octo push --package="$GITHUB_WORKSPACE/artifacts/OctoPetShop.Web.$PACKAGE_VERSION.zip" --server="${{ secrets.OCTOPUSSERVERURL }}" --apiKey="${{ secrets.OCTOPUSSERVERAPIKEY }}" --space="${{ secrets.OCTOPUSSERVERSPACE_HYBRID }}"
    - name: Push OctoPetShop ProductService
      run: |
        octo push --package="$GITHUB_WORKSPACE/artifacts/OctoPetShop.ProductService.$PACKAGE_VERSION.zip" --server="${{ secrets.OCTOPUSSERVERURL }}" --apiKey="${{ secrets.OCTOPUSSERVERAPIKEY }}" --space="${{ secrets.OCTOPUSSERVERSPACE_HYBRID }}"
    - name: Push OctoPetShop ShoppingCartService
      run: |
        octo push --package="$GITHUB_WORKSPACE/artifacts/OctoPetShop.ShoppingCartService.$PACKAGE_VERSION.zip" --server="${{ secrets.OCTOPUSSERVERURL }}" --apiKey="${{ secrets.OCTOPUSSERVERAPIKEY }}" --space="${{ secrets.OCTOPUSSERVERSPACE_HYBRID }}" 

随着 GitHub 托管的 runners 推送到 Octopus Cloud,这个解决方案工作得非常好。然而,如果不穿透防火墙,GitHub 托管的 runners 就无法将包推送到您的自托管 Octopus Deploy 服务器。

本地生成运行程序

GitHub 托管的 runner 预打包了许多功能,但有时您有特定的软件需求,需要能够控制您正在使用的版本,或者需要 runner 能够访问内部资源,如 Octopus Deploy。为了解决这个问题,GitHub 的人开发了本地托管跑步者的功能。本地运行器的工作方式类似于 Octopus 轮询触角,它们伸出 GitHub 动作,而不是 GitHub 动作伸入。

设置跑步者

设置本地跑步者非常简单。感谢 GitHub 让它变得如此简单。创建工作流 YAML 文件后,在 GitHub repo 中进行设置:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在那里,单击操作:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

稍微向下滚动以看到添加流道按钮并点击它:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下一个屏幕为您提供了选择本地 runner 架构的选项,然后提供了下载和配置它所必需的命令:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当运行配置命令时,您将被询问一些基本的问题,比如 runner 名称、标签和工作文件夹位置。在这些提示下按 Enter 键接受默认值。

当你完成后,你将有一个本地的跑步者监听工作:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将工作流配置为使用本地流道

在 YAML 中,将工作流配置为使用本地运行器只需一行代码。以上面的 YAML 为例,我们将行runs-on改为本地实例的标签。runs-on的当前值使用单个标签ubuntu-latest。然而,当你需要多个标签时,你必须把它们放在一个数组中,这个数组是用方括号指定的。对于我们的新跑步者,我们希望它使用标签self-hostedlinux。为此,我们将改变:

runs-on: ubuntu-latest 

收件人:

runs-on: [self-hosted, linux] 

将我们的工作流配置为使用本地运行器后,我们现在可以将包推送到 Octopus Deploy 的本地实例。通过对 YAML 文件进行更改,它启动了一个构建,我可以看到我的本地运行人员通过点击Actions已经获得了它:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在我的虚拟机上,我看到正在运行作业的消息:

 √ Connected to GitHub

2020-06-09 23:47:30Z: Listening for Jobs
2020-06-10 00:27:20Z: Running job: build 

检查日志输出,我们可以看到构建的版本号是 2020.06.10.6:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在我的本地 Octopus 部署实例上,我发现这已经被推了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

这篇文章演示了一种使用云构建服务器通过使用本地构建运行器或代理将包推送到自托管 Octopus Deploy 实例的方法。虽然这里关注的是 GitHub 动作,但同样的想法也可以扩展到 TeamCity、Jenkins 或 Azure DevOps。

GitHub 代码空间私人预览版——Octopus Deploy

原文:https://octopus.com/blog/github-codespaces-private-preview

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有许多源代码控制系统,但让我们面对它,GitHub 可以说是最受欢迎的。

GitHub 最近通过引入 GitHub Actions 加强了他们在 CI/CD 领域的游戏,在微软 Build 2020 上,他们引入了 GitHub Codespaces

GitHub Codespaces 就像 Visual Studio Codespaces,它是 UI 中的 VS 代码,除了 GitHub Codespaces,它内置于 GitHub 中,为您的所有开发需求提供一站式服务。

在这篇博文中,我将介绍一下私人测试版,以及如果你已经被测试版项目接受,该如何使用它。

先决条件

要跟进,您需要:

  • GitHub Codespaces 的私人测试邀请。如果你还没有,你可以请求提前访问
  • GitHub 账户。
  • 至少一个存储库。

为什么选择 GitHub Codespaces?

拥有如此多的开发工具和编写代码的方式有一个大问题;根本没有一个集中的地方来存储您想要的特定配置。以 VS 代码为例,假设您在几台不同的机器上工作,或者您正在与一个队友进行结对编程,要处理相同的代码并使其看起来完全相同,您需要几样东西:

  • 扩展。
  • 登录服务,比如从 VS 代码登录 Azure。
  • 主题。
  • settings.json中的设置。
  • 运行时。
  • 棉绒。

你知道这是怎么回事了。管理起来可能会很麻烦。

有了代码空间这样的东西,你就不用担心这个了。无论您从何处登录,所有设置和配置都在一个位置。

代码空间为您的特定开发需求提供了一个集中的位置。

设置代码空间

如果私人测试版是活跃的,你会在顶部任务栏上看到一个名为 Codespaces 的新图标。它应该是自动添加的,但您可能需要注销 GitHub,然后重新登录。

  1. 登录 GitHub,点击代码空间图标。
  2. 点击绿色的新代码空间按钮。
  3. 您将看到两个选项:

选择您想要在代码空间中打开的存储库。代码将显示在代码空间中,因此任何东西都可以工作。

  1. 点击绿色的创建代码空间按钮。

代码空间将会打开,您将能够像在桌面上使用 VS 代码一样看到来自存储库的代码:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先看看扩展

从扩展的角度来看,什么都没有改变。您通常在 VS 代码中使用的任何扩展都可以在代码空间中使用。

  1. 打开“扩展”选项卡:
  2. 搜索扩展名,例如 Golang:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GitHub 代码空间中的设置

令人惊讶的是,代码空间中的设置与 VS 代码中的设置几乎相同,这使得转换变得熟悉而平稳:

  1. 点击左下角的设置图标。
  2. 从那里,您可以配置环境、用户环境和远程代码空间环境:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

尽管 GitHub Codespaces 仍处于私人预览阶段,但很明显它是一个未来的工具。开发者没有必要离开 GitHub。他们现在可以在一个地方存储和编写代码。

GitHub Feeds - Octopus 部署

原文:https://octopus.com/blog/github-feed

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

给你 GitHub

有时你只是想部署你的应用程序,但它不需要一个构建步骤。它可能是一个存储库,你可以在那里存储你的云形成模板,一堆在 Octopus 中运行的脚本,或者一个你用 nodejs 这样的解释语言运行的简单应用程序。2018.3.0中提供的 GitHub feed 类型为您在 Octopus 部署期间访问资源提供了一种新的方式。没错,你没听错,我们现在支持使用 GitHub 作为提要源。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们现在支持使用 GitHub 作为提要源。

这种新的提要类型允许 Octopus 直接从 GitHub 部署文件,而不需要任何额外的中间构建步骤。这意味着不再打包您的脚本,以便它们可以在 Octopus 中使用,并且在源代码控制中存储您的部分部署过程时有更好的体验。标记、推送,然后直接从 Octopus 部署,无需构建服务器

来龙去脉

从部署资源的角度来看,从一个包存储库中构建工件在许多方面看起来与源代码控制中的代码是完全不同的概念。然而,通过查看我们如何对 NuGet 包的各个部分建模,我们可以看到 GitHub“package”包如何被建模以适应 Octopus 生态系统的一些相似之处。

进料类型源 Uri包裹版本
NuGet任何支持 NuGet v2 或 v3 api 的提要(例如https://api.nuget.org/v3/index.json包的名称,通常在.nuspec文件中定义。(如Octopus.Clients)包的不同实例通过具有 semver 2 版本格式的.nuspec文件进行版本控制。
GitHub任何支持 v3 api 的 GitHub 端点。这可以是标准的公共端点或私有 GitHub 安装。(例如https://api.github.com)完整的存储库身份,包括所有者。(如OctopusDeploy/Calamari)一个可以被解析为 semver 2 版本的独特标签。如果该标签存在一个版本,那么这些版本说明将在 Octopus 中显示在版本详细信息中该包的旁边。

构建这种提要类型是为了提供一种简单的方法,将 GitHub 资源作为包处理,而不会增加处理分支和提交的复杂性。因为这些概念不能很好地映射到现有的 Octopus 概念,所以决定简单地读取和解析存储库上的标签,并在识别要部署的特定包时将它们视为 Octopus 使用的版本。顺便提一下,由于 GitHub 提供了基于标签的可下载 zip 包,这提供了一种简单的机制来检索所需的文件,然后像简单的 zip 包一样集成到现有的 Octopus 部署流程中。在这篇文章的最后还提出了一些进一步的观点,概述了围绕作为提要类型的 Git 的一些未来想法。同样值得指出的是,目前只有源文件被 Octopus 部署。其他链接到 GitHub 发行版的二进制文件目前还没有包括在内,但是这在将来可能会改变。

它看起来像什么?

不需要构建过程的“包”的一个经典例子是存储在 Octopus 之外的版本控制中的脚本,它作为部署的一部分运行。接下来的几节看看我们如何配置一个部署来执行来自OctopusDeploy/AcmeScripts GitHub 存储库的脚本。

设置馈送

首先,让我们看看如何在 Octopus 中创建一个 GitHub 外部提要。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如您所见,我们提供了设置个人访问令牌的能力,而不仅仅是用户名和密码。这允许你创建 GitHub 称之为的机器用户,它实际上是组织中的 GitHub 用户,用于这些种类的自动化任务。

当访问 GitHub 端点时,为 Octopus 提供一个认证选项是很重要的,因为匿名请求被 GitHub 限制为比认证请求低得多的值。

使用软件包

此提要中的“包”被视为与任何其他包完全相同。在这个场景中,我们将选择一个脚本步骤,并从一个包中获取我们的RunMe.ps1脚本。packageID 是标识我们的AcmeScripts存储库的完整的Octopus/AcmeScripts名称。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,当您搜索软件包时,如果您省略了/字符,它将在所有存储库中搜索(您的帐户可以访问的)。添加不带库的/将列出该所有者的所有包,添加库名将搜索该所有者的库。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

添加 GitHub 标签

我们现在已经配置了 Octopus,我们只需要将 PowerShell 脚本添加到我们的 GitHub 存储库OctopusDeploy/AcmeScripts中,它将在我们的项目中执行。

echo Write-Host Hello World > RunMe.ps1
git add RunMe.ps1
git commit -m "Ready To Run"
git tag 0.0.1
git push
git push --tags 

为了更好地衡量,我们还将通过 GitHub 门户网站为这个标签添加一些发行说明。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建版本

由于我们目前不支持从外部源自动创建发布(注意这个空间),Octopus 不知道我们刚刚推了这个新标签,直到我们创建了一个新的发布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在部署时,Octopus 将通过 GitHub API 从标记的 commit 下载源代码。

从这一点上来说,在整个部署过程中,被有效地视为一个典型的 zip 文件,允许它被提取、传输或用作脚本和模板的源。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看马,没身材!

未来计划

值得再次重申的是,这种新的提要类型完全是建立在标签和发布之上的。当使用新的 feed 类型时,分支、提交和 heads 这样的概念并不直接相关。您可以间接地处理分支,方法是在这些分支中适当地标记您的提交(记住,一旦您将这些提交合并回master分支,那么标记可能会引用一个属于master分支的提交)。有计划正在进行中,以提供真正的 Git-as-a-feed 支持,其中提交\分支将被更优先地对待,但是决定保持这个 GitHub feed 工作独立。

上面提到的另一点是 GitHub 缺少触发发布和部署的钩子。由于我们许多客户网络的性质,从外部世界打电话并不总是可用的。因此,我们将考虑其他更实用的机制来支持来自外部提要的 ARC。

GitHib 作为包装饲料

我们对这种新的饲料类型给八达通用户带来的机会感到兴奋。使用 GitHub 作为一些部署依赖项的来源将有助于简化您的 CI 管道,并允许更好的版本控制,而无需花费多余的精力和时间来打包那些并不真正需要打包的资源。请让我们知道您对这一新方向的想法,以及它如何在您的部署过程中派上用场。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将 GitHub NuGet 注册表配置为外部 feed - Octopus 部署

原文:https://octopus.com/blog/github-nuget-external-feed

GitHub 已经不仅仅是一个源代码库。GitHub 的人们已经开发了一些功能,比如他们的构建服务器产品、GitHub 操作和问题跟踪。他们甚至开发了 GitHub 包,这是一个与 Docker 容器、npm、Maven、NuGet 包和 RubyGems 兼容的注册表。

在这篇文章中,我将向您展示如何配置 GitHub Actions 作业来将. NET 核心 NuGet 包推入注册表,并将注册表连接到 Octopus Deploy,作为一个外部提要

正在配置。网络核心应用

要将包推送到 GitHub 包,需要在.csproj文件中指定RepositoryUrl元素。当打包并将包推送到注册表时,dotnet命令会使用这些信息。以下是 OctoPetShop 数据库项目的一个示例:

八分之一样本。OctoPetShop.Database.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
    <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
    <RepositoryUrl>https://github.com/OctopusSamples/OctoPetShop.git</RepositoryUrl>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="dbup" Version="4.2.0" />
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Include="scripts/*.sql" />
  </ItemGroup>

  <ItemGroup>
    <None Update="deploy.sh" CopyToOutputDirectory="PreserveNewest" />
    <None Update="deploy.ps1" CopyToOutputDirectory="PreserveNewest" />
  </ItemGroup>

</Project> 

配置 GitHub 操作构建

除了构建应用程序,GitHub Actions 作业还需要执行以下活动:

  • 将应用程序组件打包到 NuGet 包中
  • 添加 NuGet 存储库源
  • 将包推入包注册表

所有这些命令都可以在。NET CLI。

将应用程序打包到 NuGet 包中

您可以通过多种方式将应用程序打包到 NuGet 包中。这篇文章使用了内置在。NET CLI。

要设置包版本,请使用 MSBuild 语法-p:PackageVersion $PACKAGE_VERSION。变量$PACKAGE_VERSION在之前的 GitHub Actions YAML 中已经声明过了(参见我们的 OctoPetShop 示例了解整个过程)。以下是显示 OctoPetShop 数据库项目打包的构建摘录:

 - name: Pack OctoPetShopDatabase
      run: |
        dotnet pack OctopusSamples.OctoPetShop.Database/OctopusSamples.OctoPetShop.Database.csproj --configuration Release --output "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.Database" -p:PackageVersion=$PACKAGE_VERSION 

添加 NuGet 存储库源

要定位 GitHub 包注册表,您需要添加注册表作为源。source URL 的格式如下:https://nuget.pkg.github.com/YourGitHubUsernameOrOrganizationName/index.json

您还需要指定具有足够权限的凭据,以便将包推送到注册表。您可以创建个人访问令牌(PAT)或使用 GitHub ActionsGITHUB_TOKEN中的内置密码。

 - name: Add source
      run: |
        dotnet nuget add source "https://nuget.pkg.github.com/OctopusSamples/index.json" --username OctopusSamples --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github 

将包推入包注册表

您还需要为push命令指定凭证,并且您还可以使用GITHUB_TOKEN作为--api-key参数:

 - name: Push packages to GitHub Packages NuGet feed
      run: |
        dotnet nuget push "$GITHUB_WORKSPACE/artifacts/OctopusSamples.OctoPetShop.Database/OctopusSamples.OctoPetShop.Database.$PACKAGE_VERSION.nupkg"  --api-key ${{ secrets.GITHUB_TOKEN }} --source "github" 

推送完包后,它们应该出现在 GitHub 项目的部分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将 GitHub 包注册表配置为外部提要

GitHub 包注册中心需要认证来拉包。在配置提要之前,首先需要在 GitHub 中创建一个 PAT。

在 GitHub 中创建 PAT

创建 PAT 相对简单。首先,点击右上角的个人资料,然后选择设置

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

滚动至左侧菜单底部,点击开发者设置

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点击个人访问令牌,然后生成新令牌

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

给令牌一个描述,选择一个到期时间,并分配read:packages权限。点击生成令牌

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

复制新令牌并将其保存在安全的位置。

创建外部源

要创建外部进给,点击,然后点击外部进给,然后点击添加进给

【T2 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

填写饲料表格:

  • 进给类型 : NuGet Feed
  • 名称:输入描述性名称
  • 网址 : https://nuget.pkg.github.com/YourGitHubUsernameOrOrganizationName/index.json
  • 凭证
    • 用户名:令牌的用户名
    • 密码:您之前生成的 PAT

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点击保存并测试。输入您用自己的版本创建的包的部分名称,以确保 feed 正常工作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

在这篇文章中,我演示了如何使用。NET CLI 在 GitHub Actions 中,并将包推送到 GitHub Packages 注册表中。然后,我向您展示了如何在 Octopus Deploy 中将注册中心配置为外部提要。

你可能也会对我关于使用 GitLab feeds 和 Octopus Deploy 的帖子感兴趣。

愉快的部署!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值