#容器化

0 关注者 · 22 帖子

容器化是全机器虚拟化的一种轻量级替代方案,涉及到将应用程序封装在具有其自身操作环境的容器中。

文章 Michael Lei · 九月 27, 2024 6m read

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • 持续交付
  • GitLab 安装和配置
  • GitLab CI/CD
  • 为何使用容器?
  • 容器基础架构
  • 使用容器的 CD
  • 使用 ICM 的 CD
  • 容器架构

在本文中,我们将讨论如何构建并部署您自己的容器。

Durable %SYS

由于容器是临时的,它们不应存储任何应用程序数据。 持久化 %SYS 功能让我们能够实现这一点 – 将设置、配置、%SYS 数据等存储到主机卷上,即:

  • iris.cpf 文件。
  • /csp 目录,包含 Web 网关配置和日志文件。
  • /httpd/httpd.conf 文件,实例的私有 Web 服务器的配置文件。
  • /mgr 目录,包含以下内容:
    • IRISSYS 系统数据库,包括 IRIS.DAT 和 iris.lck 文件、流目录,以及包含 IRISTEMP、IRISAUDIT、IRIS 和 USER 系统数据库的 iristemp、irisaudit、iris 和 user 目录。
    • 写入镜像日志文件,IRIS.WIJ。
    • /journal 目录,包含日志文件。
    • /temp 目录,用于存储临时文件。
    • 日志文件,包括 messages.log、journal.log 和 SystemMonitor.log。

容器架构

另一方面,我们需要将应用程序代码存储在我们的容器内,以便在需要时进行升级。

这一切使我们实现了如下所示的架构:

为了在构建过程中实现这一点,我们至少需要创建一个额外的数据库(用于存储应用程序代码)并将其映射到我们的应用程序命名空间。 在我的示例中,我将使用 USER 命名空间来保存应用程序数据,因为它已经存在且是持久化的。

安装程序

基于上述内容,我们的安装程序需要执行以下任务:

  • 创建 APP 命名空间/数据库
  • 将代码加载到 APP 命名空间
  • 将我们的应用程序类映射到 USER 命名空间
  • 完成所有其他安装(在本例中,我创建了 CSP Web 应用和 REST 应用)
Class MyApp.Hooks.Local
{

Parameter Namespace = "APP";

/// See generated code in zsetup+1^MyApp.Hooks.Local.1 XData Install [ XMLNamespace = INSTALLER ] { <Manifest>

<Log Text="Creating namespace ${Namespace}" Level="0"/> <Namespace Name="${Namespace}" Create="yes" Code="${Namespace}" Ensemble="" Data="IRISTEMP"> <Configuration> <Database Name="${Namespace}" Dir="/usr/irissys/mgr/${Namespace}" Create="yes" MountRequired="true" Resource="%DB_${Namespace}" PublicPermissions="RW" MountAtStartup="true"/> </Configuration>

<Import File="${Dir}Form" Recurse="1" Flags="cdk" IgnoreErrors="1" /> </Namespace> <Log Text="End Creating namespace ${Namespace}" Level="0"/>

<Log Text="Mapping to USER" Level="0"/> <Namespace Name="USER" Create="no" Code="USER" Data="USER" Ensemble="0"> <Configuration> <Log Text="Mapping Form package to USER namespace" Level="0"/> <ClassMapping From="${Namespace}" Package="Form"/> <RoutineMapping From="${Namespace}" Routines="Form" /> </Configuration>

<CSPApplication Url="/" Directory="${Dir}client" AuthenticationMethods="64" IsNamespaceDefault="false" Grant="%ALL" Recurse="1" /> </Namespace>

</Manifest> }

/// This is a method generator whose code is generated by XGL. /// Main setup method /// set vars("Namespace")="TEMP3" /// do ##class(MyApp.Hooks.Global).setup(.vars) ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 0, pInstaller As %Installer.Installer) As %Status [ CodeMode = objectgenerator, Internal ] { Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "Install") }

/// Entry point ClassMethod onAfter() As %Status { try { write "START INSTALLER",! set vars("Namespace") = ..#Namespace set vars("Dir") = ..getDir() set sc = ..setup(.vars) write !,$System.Status.GetErrorText(sc),!

    set sc = ..createWebApp()
} catch ex {
    set sc = ex.AsStatus()
    write !,$System.Status.GetErrorText(sc),!
}
quit sc

}

/// Modify web app REST ClassMethod createWebApp(appName As %String = "/forms") As %Status { set:$e(appName)'="/" appName = "/" _ appName #dim sc As %Status = $$$OK new $namespace set $namespace = "%SYS" if '##class(Security.Applications).Exists(appName) { set props("AutheEnabled") = $$$AutheUnauthenticated set props("NameSpace") = "USER" set props("IsNameSpaceDefault") = $$$NO set props("DispatchClass") = "Form.REST.Main" set props("MatchRoles")=":" _ $$$AllRoleName set sc = ##class(Security.Applications).Create(appName, .props) } quit sc }

ClassMethod getDir() [ CodeMode = expression ] { ##class(%File).NormalizeDirectory($system.Util.GetEnviron("CI_PROJECT_DIR")) }

}

为了创建非持久化数据库,我会使用 /usr/irissys/mgr 的一个子目录,它不是持久的。 请注意,调用 ##class(%File).ManagerDirectory() 会返回持久化目录的路径,而不是内部容器目录的路径。

 

持续交付配置

查看第 7 部分以了解完整信息,但我们需要做的就是在现有配置中添加这两行(加粗)代码。

run image:
  stage: run
  environment:
    name: $CI_COMMIT_REF_NAME
    url: http://$CI_COMMIT_REF_SLUG.docker.eduard.win/index.html
  tags:
    - test
  script:
    - docker run -d
      --expose 52773
      --volume /InterSystems/durable/$CI_COMMIT_REF_SLUG:/data
      --env ISC_DATA_DIRECTORY=/data/sys
      --env VIRTUAL_HOST=$CI_COMMIT_REF_SLUG.docker.eduard.win
      --name iris-$CI_COMMIT_REF_NAME
      docker.eduard.win/test/docker:$CI_COMMIT_REF_NAME
      --log $ISC_PACKAGE_INSTALLDIR/mgr/messages.log

volume 参数将主机目录挂载到容器中,ISC_DATA_DIRECTORY 变量告诉 InterSystems IRIS 使用哪个目录。 引用文档内容:

当您使用这些选项运行 InterSystems IRIS 容器时,会发生以下情况:
  • 指定的外部卷被挂载。
  • 如果由 ISC_DATA_DIRECTORY 环境变量指定的持久化 %SYS 目录(上述示例中的 iconfig/)已经存在且包含持久化 %SYS 数据,则实例的所有内部指针都会重置到该目录,实例使用其中包含的数据。
  • 如果 ISC_DATA_DIRECTORY 环境变量指定的持久化 %SYS 目录已经存在但不包含持久化 %SYS 数据,则不会复制数据,实例使用容器内安装树中的数据运行,这意味着实例特定的数据不是持久的。 因此,您可能需要在脚本中包含对此条件的检查,然后再运行容器。
  • 如果 ISC_DATA_DIRECTORY 指定的持久化 %SYS 目录不存在:
    • 指定的持久化 %SYS 目录已创建。
    • 将持久化 %SYS 目录内容中列出的目录和文件从其安装位置复制到持久化 %SYS 目录(原始文件仍留在原位)。
    • 实例的所有内部指针都会重置到持久化 %SYS 目录,实例使用其中包含的数据。

 

更新

当应用程序演进并发布新版本(容器)时,有时您可能需要运行一些代码。 这可能是预编译/后编译挂钩、架构迁移、单元测试,但归根结底,您需要运行任意代码。 这就是为什么您需要一个管理应用程序的框架。 在之前的文章中,我概述了这种框架的基本结构,但它当然可以大幅度扩展以满足特定应用程序的需求。

结论

创建容器化应用程序需要一些思考,但 InterSystems IRIS 提供了几个功能,可以让此流程更加轻松。

0
0 97
文章 Michael Lei · 九月 27, 2024 9m read

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • 持续交付
  • GitLab 安装和配置
  • GitLab CI/CD
  • 为何使用容器?
  • 容器基础架构
  • 使用容器的 CD
  • 使用 ICM 的 CD

在本文中,我们将使用 InterSystems Cloud Manager 构建持续交付。 ICM 是一个面向基于 InterSystems IRIS 的应用程序的云配置和部署解决方案。 它允许您定义所需部署配置,ICM 会自动提供这些配置。 有关详情,请参阅 ICM 概述

工作流

在我们的持续交付配置中,我们将完成以下任务:

  • 将代码推送到 GitLab 仓库
  • 构建 docker 镜像
  • 将镜像发布到 docker 注册表
  • 在测试服务器上测试镜像
  • 如果测试通过,则在生产服务器上部署

也可以用示意图形式表示此流程:

如您所见,基本操作是相同的,不过我们将使用 ICM 而不是手动方式来管理 Docker 容器。

ICM 配置

在我们开始升级容器之前,需要对它们进行配置。 因此,我们需要定义 defaults.jsondefinitions.json 来描述我们的架构。 我将为 LIVE 服务器提供这 2 个文件,TEST 服务器的 definitions 是相同的,defaults 只在 TagSystemMode 值上有所不同。

defaults.json:

{
    "Provider": "GCP",
    "Label": "gsdemo2",
    "Tag": "LIVE","SystemMode": "LIVE",
    "DataVolumeSize": "10",
    "SSHUser": "sample",
    "SSHPublicKey": "/icmdata/ssh/insecure.pub",
    "SSHPrivateKey": "/icmdata/ssh/insecure",
    "DockerImage": "eduard93/icmdemo:master",
    "DockerUsername": "eduard93",
    "DockerPassword": "...",
    "TLSKeyDir": "/icmdata/tls",
    "Credentials": "/icmdata/gcp.json",
    "Project": "elebedyu-test",
    "MachineType": "n1-standard-1",
    "Region": "us-east1",
    "Zone": "us-east1-b",
    "Image": "rhel-cloud/rhel-7-v20170719",
    "ISCPassword": "SYS",
    "Mirror": "false"
}

definitions.json

[
    {
    "Role": "DM",
    "Count": "1",
    "ISCLicense": "/icmdata/iris.key"
    }
]

在 ICM 容器内部,/icmdata 文件夹从主机挂载,并且:

  • TEST 服务器的定义放置在 /icmdata/test 文件夹中
  • LIVE 服务器的定义放置在 /icmdata/live 文件夹中

获取所有必需的密钥后:

keygenSSH.sh /icmdata/ssh
keygenTLS.sh /icmdata/tls

并将必需的文件放置在 /icmdata 中:

  • iris.key
  • gcp.json(用于部署到 Google Cloud Platform)

调用 ICM 来配置您的实例:

cd /icmdata/test
icm provision
icm run
cd /icmdata/live
icm provision
icm run

这将为每个 TEST 和 LIVE 服务器配置一个独立的 InterSystems IRIS 实例。

有关更详细的指南,请参阅 ICM 概述

构建

首先,我们需要构建镜像。

我们的代码通常存储在仓库中,CD 配置位于 gitlab-ci.yml 中,但为了提高安全性,我们会在构建服务器上存储几个服务器特定的文件。

iris.key

许可证密钥。 或者,它可以在容器构建过程中下载,而不是存储在服务器上。 将密钥存储在仓库中非常不安全。

pwd.txt

包含默认密码的文件。 将这类文件存储在仓库中也非常不安全。 此外,如果您在单独的服务器上托管生产环境,它可能有不同的默认密码。

load_ci_icm.script

初始脚本,它执行以下任务:

  • 加载安装程序
  • 安装程序执行应用程序初始化
  • 加载代码
set dir = ##class(%File).NormalizeDirectory($system.Util.GetEnviron("CI_PROJECT_DIR"))
do ##class(%SYSTEM.OBJ).Load(dir _ "Installer/Global.cls","cdk")
do ##class(Installer.Global).init()
halt

请注意,第一行有意留空。

与之前的示例相比,有几个不同之处。 首先,我们没有启用操作系统身份验证,因为 ICM 会与容器交互而不是直接与 GitLab 交互。 其次,我使用安装程序清单来初始化我们的应用程序,以展示不同的初始化方式。 有关安装程序的更多信息,请参阅这篇文章。 最后,我们将在 Docker Hub 中以私有仓库的形式发布我们的镜像。

 

Installer/Global.cls

我们的安装程序清单如下所示:

<Manifest>
    <Log Text="Creating namespace ${Namespace}" Level="0"/>
    <Namespace Name="${Namespace}" Create="yes" Code="${Namespace}" Ensemble="" Data="IRISTEMP">
        <Configuration>
            <Database Name="${Namespace}" Dir="${MGRDIR}/${Namespace}" Create="yes" MountRequired="true" Resource="%DB_${Namespace}" PublicPermissions="RW" MountAtStartup="true"/>
        </Configuration>

        <Import File="${Dir}MyApp" Recurse="1" Flags="cdk" IgnoreErrors="1" />
    </Namespace>

    <Log Text="Mapping to USER" Level="0"/>
    <Namespace Name="USER" Create="no" Code="USER" Data="USER" Ensemble="0">
        <Configuration>
            <Log Text="Mapping MyApp package to USER namespace" Level="0"/>
            <ClassMapping From="${Namespace}" Package="MyApp"/>
        </Configuration>

        <CSPApplication  Url="/"      Directory="${Dir}client" AuthenticationMethods="64" IsNamespaceDefault="false" Grant="%ALL"  />
        <CSPApplication  Url="/myApp" Directory="${Dir}"       AuthenticationMethods="64" IsNamespaceDefault="false" Grant="%ALL"  />
    </Namespace>
</Manifest>

它实现了以下更改:

  1. 创建应用程序命名空间。
  2. 创建应用程序代码数据库(数据将存储在 USER 数据库中)。
  3. 将代码加载到应用程序代码数据库中。
  4. 将 MyApp 软件包映射到 USER 命名空间。
  5. 创建 2 个 Web 应用程序:分别用于 HTML 和 REST。

gitlab-ci.yml

现在,继续持续交付配置:

build image:
  stage: build
  tags:
    - master
  script:
    - cp -r /InterSystems/mount ci
    - cd ci
    - echo 'SuperUser' | cat - pwd.txt load_ci_icm.script > temp.txt
    - mv temp.txt load_ci.script
    - cd ..
    - docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t eduard93/icmdemo:$CI_COMMIT_REF_NAME .

这里会执行哪些操作?

首先,由于 docker build 只能访问基础构建目录(在我们的示例中为仓库根目录)的子目录,我们需要将我们的“秘密”目录(其中包含 iris.keypwd.txtload_ci_icm.script)复制到克隆的仓库中。

接下来,首次终端访问需要用户名/密码,因此我们会将这些信息添加到 load_ci.script 中(这也是 load_ci.script 开头一行留空的原因)。

最后,我们会构建 docker 镜像并适当地为其添加标签:eduard93/icmdemo:$CI_COMMIT_REF_NAME

其中,$CI_COMMIT_REF_NAME 是当前分支的名称。 请注意,镜像标签的第一部分应与 GitLab 中的项目名称相同,这样才能在 GitLab 的“注册表”标签页中看到它(“注册表”标签页中提供了关于添加标签的说明)。

Dockerfile

构建 docker 镜像是通过 Dockerfile 完成的,具体如下:

FROM intersystems/iris:2018.1.1-released

ENV SRC_DIR=/tmp/src
ENV CI_DIR=$SRC_DIR/ci
ENV CI_PROJECT_DIR=$SRC_DIR

COPY ./ $SRC_DIR

RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/ \
 && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/ \
 && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt \
 && iris start $ISC_PACKAGE_INSTANCENAME \
 && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script \
 && iris stop $ISC_PACKAGE_INSTANCENAME quietly

我们从基本的 iris 容器开始。

首先,我们将仓库(和“秘密”目录)复制到容器中。

接下来,我们将许可证密钥复制到 mgr 目录中。

然后,我们将密码更改为 pwd.txt 中的值。 请注意,此操作会删除 pwd.txt。

之后,实例启动并执行 load_ci.script。

最后,iris 实例停止。

请注意,我使用的是 GitLab Shell 执行器,而不是 Docker 执行器。 当您需要从镜像内部提取某些内容时,将使用 Docker 执行器,例如在 Java 容器中构建 Android 应用程序并且只需要一个 apk 时。 在我们的示例中,我们需要整个容器,因此需要使用 Shell 执行器。 因此,我们通过 GitLab Shell 执行器运行 Docker 命令。

发布

现在,我们将镜像发布到 Docker Hub

publish image:
  stage: publish
  tags:
    - master
  script:
    - docker login -u eduard93 -p ${DOCKERPASSWORD}
    - docker push eduard93/icmdemo:$CI_COMMIT_REF_NAME

注意 ${DOCKERPASSWORD} 变量,它是 GitLab 的秘密变量。 我们可以在“GitLab > 项目 > 设置 > CI/CD > 变量”中添加它们:

作业日志中也不包含密码值:

Running with gitlab-runner 10.6.0 (a3543a27)
  on icm 82634fd1
Using Shell executor...
Running on docker...
Fetching changes...
Removing ci/
HEAD is now at 8e24591 Add deploy to LIVE
Checking out 8e245910 as master...Skipping Git submodules setup$ docker login -u eduard93 -p ${DOCKERPASSWORD}
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
$ docker push eduard93/icmdemo:$CI_COMMIT_REF_NAME
The push refers to repository [docker.io/eduard93/icmdemo]
master: digest: sha256:d1612811c11154e77c84f0c08a564a3edeb7ddbbd9b7acb80754fda97f95d101 size: 2620
Job succeeded

在 Docker Hub 中,我们可以看到新镜像:

 

运行

我们有了镜像,接下来在我们的测试服务器上运行它。 脚本如下。

run image:
  stage: run
  environment:
    name: $CI_COMMIT_REF_NAME
  tags:
    - master
  script:
    - docker exec icm sh -c "cd /icmdata/test && icm upgrade -image eduard93/icmdemo:$CI_COMMIT_REF_NAME"

使用 ICM,我们只需要运行一个命令 (icm upgrade) 即可升级现有部署。 我们通过运行“docker exec icm sh -c”来调用它,这会在 icm 容器内执行指定的命令。首先,我们进入 /icmdata/test,这里定义了我们为 TEST 服务器准备的 ICM 部署定义。 之后,我们调用 icm upgrade 将当前存在的容器替换为新容器。

测试

我们来运行一些测试。

test image:
  stage: test
  tags:
    - master
  script:
    - docker exec icm sh -c "cd /icmdata/test && icm session -namespace USER -command 'do \$classmethod(\"%UnitTest.Manager\",\"RunTest\",\"MyApp/Tests\",\"/nodelete\")' | tee /dev/stderr | grep 'All PASSED' && exit 0 || exit 1"

同样,我们在 icm 容器内执行一条命令。 icm 会话在一个已部署的节点上执行命令。 该命令运行单元测试。 之后,它将所有输出传输到屏幕,同时也传输给 grep 以查找单元测试结果,并成功退出进程或以出错方式退出。

部署

生产服务器上的部署与测试服务器上的部署完全相同,只是为 LIVE 部署定义使用了另一个目录。 如果测试失败,此阶段将不会被执行。

deploy image:
  stage: deploy
  environment:
    name: $CI_COMMIT_REF_NAME
  tags:
    - master
  script:
    - docker exec icm sh -c "cd /icmdata/live && icm upgrade -image eduard93/icmdemo:$CI_COMMIT_REF_NAME"

结论

ICM 为您提供了一种简单直观的方式来配置云基础架构并在它上面部署服务,帮助您立即进入云,无需大规模开发或重新工具化。 基础架构即代码 (IaC) 和容器化部署的优势使您可以轻松地在公共云平台(如 Google、Amazon 和 Azure)或者在您的私有 VMware vSphere 云上部署基于 InterSystems IRIS 的应用程序。 定义您的需求,发出几条命令,ICM 会完成其余工作。
即使您已经在使用云基础架构、容器或两者,ICM 也能通过自动执行大量原本需要手动完成的步骤,极大地减少配置和部署应用程序所需的时间和精力。
0
0 87
文章 Michael Lei · 九月 27, 2024 9m read

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • 持续交付
  • GitLab 安装和配置
  • GitLab CI/CD
  • 为何使用容器
  • 容器基础架构
  • 使用容器的 CD

第一篇文章中,我们介绍了 Git 基础知识、深度理解 Git 概念对现代软件开发至关重要的原因,以及如何使用 Git 开发软件。

第二篇文章中,我们介绍了 GitLab 工作流 – 一个完整的软件生命周期流程,并介绍了持续交付。

第三篇文章中,我们介绍了 GitLab 安装和配置以及将环境连接到 GitLab

第四篇文章中,我们编写了 CD 配置。

第五篇文章中,我们讨论了容器以及使用容器的方式(和原因)。

第六篇文章中,我们将探讨运行包含容器的持续交付管道所需的主要组件以及这些组件如何协同运行。

在这篇文章中,我们将构建上一篇文章中探讨的持续交付配置。

工作流

在持续交付配置中,我们会:

  • 将代码推送到 GitLab 仓库
  • 构建 docker 镜像
  • 进行测试
  • 将镜像发布到 docker 注册表
  • 将旧容器换为注册表中的新版本

也可以用示意图形式表示此流程:

我们开始吧。

构建

首先,我们需要构建镜像。

我们的代码通常存储在仓库中,CD 配置位于 gitlab-ci.yml 中,但为了提高安全性,我们会在构建服务器上存储几个服务器特定的文件。

GitLab.xml

包含 CD 挂钩代码。 该代码是在上一篇文章中开发的,并在 GitHub 上提供。 这是一个小型库,用于加载代码、运行各种挂钩以及测试代码。 作为更好的替代方案,您可以使用 git 子模块将此项目或类似项目包含到您的仓库中。 最好选择子模块,因为子模块更容易保持最新状态。 另一个替代方案是在 GitLab 上为版本添加标签,并使用 ADD 命令加载这些版本。

iris.key

许可证密钥。 或者,它可以在容器构建过程中下载,而不是存储在服务器上。 将密钥存储在仓库中非常不安全。

pwd.txt

包含默认密码的文件。 将这类文件存储在仓库中也非常不安全。 此外,如果您在单独的服务器上托管生产环境,它可能有不同的默认密码。

load_ci.script

初始脚本,它执行以下任务:

  • 实现操作系统身份验证
  • 加载 GitLab.xml
  • 初始化 GitLab 实用工具设置
  • 加载代码

set sc = ##Class(Security.System).Get("SYSTEM",.Properties) write:('sc) $System.Status.GetErrorText(sc) set AutheEnabled = Properties("AutheEnabled") set AutheEnabled = $zb(+AutheEnabled,16,7) set Properties("AutheEnabled") = AutheEnabled set sc = ##Class(Security.System).Modify("SYSTEM",.Properties) write:('sc) $System.Status.GetErrorText(sc) zn "USER" do ##class(%SYSTEM.OBJ).Load(##class(%File).ManagerDirectory() _ "GitLab.xml","cdk") do ##class(isc.git.Settings).setSetting("hooks", "MyApp/Hooks/") do ##class(isc.git.Settings).setSetting("tests", "MyApp/Tests/") do ##class(isc.git.GitLab).load() halt

请注意,第一行有意留空。

由于某些设置可以是服务器特定的,脚本不会存储在仓库中,而是单独存储。 如果此初始挂钩始终相同,将其存储在仓库中即可。

gitlab-ci.yml

现在,继续持续交付配置:

构建镜像:
  stage: build
  tags:
    - test
  script:
    - cp -r /InterSystems/mount ci
    - cd ci
    - echo 'SuperUser' | cat - pwd.txt load_ci.script > temp.txt
    - mv temp.txt load_ci.script
    - cd ..
    - docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t docker.domain.com/test/docker:$CI_COMMIT_REF_NAME .

这里会执行哪些操作?

首先,由于 docker build 只能访问基础构建目录的子目录(本例中是仓库根目录),我们需要将“秘密”目录(包含 GitLab.xmliris.keypwd.txt 和 load_ci.script 的目录)复制到克隆的仓库中。

接下来,首次终端访问需要用户名/密码,因此我们会将这些信息添加到 load_ci.script 中(这也是 load_ci.script 开头一行留空的原因)。

最后,我们会构建 docker 镜像并适当地为其添加标签:docker.domain.com/test/docker:$CI_COMMIT_REF_NAME

其中,$CI_COMMIT_REF_NAME 是当前分支的名称。 请注意,镜像标签的第一部分应与 GitLab 中的项目名称相同,这样才能在 GitLab 的“注册表”标签页中看到它(“注册表”标签页中提供了关于添加标签的说明)。

Dockerfile

构建 docker 镜像是通过 Dockerfile 完成的,具体如下:

FROM docker.intersystems.com/intersystems/iris:2018.1.1.611.0

ENV SRC_DIR=/tmp/src ENV CI_DIR=$SRC_DIR/ci ENV CI_PROJECT_DIR=$SRC_DIR

COPY ./ $SRC_DIR

RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/
&& cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/
&& $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt
&& iris start $ISC_PACKAGE_INSTANCENAME
&& irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script
&& iris stop $ISC_PACKAGE_INSTANCENAME quietly

我们从基本的 iris 容器开始。

首先,我们将仓库(和“秘密”目录)复制到容器中。

接下来,我们将许可证密钥和 GitLab.xml 复制到 mgr 目录中。

然后,我们将密码更改为 pwd.txt 中的值。 请注意,此操作会删除 pwd.txt。

之后,实例启动并执行 load_ci.script。

最后,iris 实例停止。

以下是作业日志(部分日志,跳过了加载/编译日志):

Running with gitlab-runner 10.6.0 (a3543a27)
  on docker 7b21e0c4
Using Shell executor...
Running on docker...
Fetching changes...
Removing ci/
Removing temp.txt
HEAD is now at 5ef9904 Build load_ci.script
From http://gitlab.eduard.win/test/docker
   5ef9904..9753a8d  master     -> origin/master
Checking out 9753a8db as master...
Skipping Git submodules setup
$ cp -r /InterSystems/mount ci
$ cd ci
$ echo 'SuperUser' | cat - pwd.txt load_ci.script > temp.txt
$ mv temp.txt load_ci.script
$ cd ..
$ docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t docker.eduard.win/test/docker:$CI_COMMIT_REF_NAME .
Sending build context to Docker daemon  401.4kB

Step 1/6 : FROM docker.intersystems.com/intersystems/iris:2018.1.1.611.0 ---> cd2e53e7f850 Step 2/6 : ENV SRC_DIR=/tmp/src ---> Using cache ---> 68ba1cb00aff Step 3/6 : ENV CI_DIR=$SRC_DIR/ci ---> Using cache ---> 6784c34a9ee6 Step 4/6 : ENV CI_PROJECT_DIR=$SRC_DIR ---> Using cache ---> 3757fa88a28a Step 5/6 : COPY ./ $SRC_DIR ---> 5515e13741b0 Step 6/6 : RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/ && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/ && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt && iris start $ISC_PACKAGE_INSTANCENAME && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script && iris stop $ISC_PACKAGE_INSTANCENAME quietly ---> Running in 86526183cf7c . Waited 1 seconds for InterSystems IRIS to start This copy of InterSystems IRIS has been licensed for use exclusively by: ISC Internal Container Sharding Copyright (c) 1986-2018 by InterSystems Corporation Any other use is a violation of your license agreement

%SYS> 1

%SYS> Using 'iris.cpf' configuration file

This copy of InterSystems IRIS has been licensed for use exclusively by: ISC Internal Container Sharding Copyright (c) 1986-2018 by InterSystems Corporation Any other use is a violation of your license agreement

1 alert(s) during startup. See messages.log for details. Starting IRIS

Node: 39702b122ab6, Instance: IRIS

Username: Password:

Load started on 04/06/2018 17:38:21 Loading file /usr/irissys/mgr/GitLab.xml as xml Load finished successfully.

USER>

USER>

[2018-04-06 17:38:22.017] Running init hooks: before

[2018-04-06 17:38:22.017] Importing hooks dir /tmp/src/MyApp/Hooks/

[2018-04-06 17:38:22.374] Executing hook class: MyApp.Hooks.Global

[2018-04-06 17:38:22.375] Executing hook class: MyApp.Hooks.Local

[2018-04-06 17:38:22.375] Importing dir /tmp/src/

Loading file /tmp/src/MyApp/Tests/TestSuite.cls as udl

Compilation started on 04/06/2018 17:38:22 with qualifiers 'c' Compilation finished successfully in 0.194s.

Load finished successfully.

[2018-04-06 17:38:22.876] Running init hooks: after

[2018-04-06 17:38:22.878] Executing hook class: MyApp.Hooks.Local

[2018-04-06 17:38:22.921] Executing hook class: MyApp.Hooks.Global Removing intermediate container 39702b122ab6 ---> dea6b2123165 [Warning] One or more build-args [CI_PROJECT_DIR] were not consumed Successfully built dea6b2123165 Successfully tagged docker.domain.com/test/docker:master Job succeeded

请注意,我使用的是 GitLab Shell 执行器,而不是 Docker 执行器。 当您需要从镜像内部提取某些内容时,将使用 Docker 执行器,例如在 Java 容器中构建 Android 应用程序并且只需要一个 apk 时。 在我们的示例中,我们需要整个容器,因此需要使用 Shell 执行器。 因此,我们通过 GitLab Shell 执行器运行 Docker 命令。

 

运行

我们构建了镜像,接下来要运行镜像。如果是功能分支,我们销毁旧容器并启动新容器即可。 如果是环境,我们可以运行临时容器,在测试成功的情况下,可以替换环境容器(此内容留给读者作为练习)。

脚本如下。

destroy old:
  stage: destroy
  tags:
    - test
  script:
    - docker stop iris-$CI_COMMIT_REF_NAME || true
    - docker rm -f iris-$CI_COMMIT_REF_NAME || true

此脚本会销毁当前运行的容器,并且始终都会成功(默认情况下,如果 docker 尝试停止/移除不存在的容器,则会失败)。

接下来,我们启动新镜像并将其注册为环境。 Nginx 容器 使用 VIRTUAL_HOST 环境变量和 expose 指令(用于了解要代理的端口)自动代理请求。

run image:
  stage: run
  environment:
    name: $CI_COMMIT_REF_NAME
    url: http://$CI_COMMIT_REF_SLUG. docker.domain.com/index.html
  tags:
    - test
  script:
    - docker run -d
      --expose 52773
      --env VIRTUAL_HOST=$CI_COMMIT_REF_SLUG.docker.eduard.win
      --name iris-$CI_COMMIT_REF_NAME
      docker.domain.com/test/docker:$CI_COMMIT_REF_NAME
      --log $ISC_PACKAGE_INSTALLDIR/mgr/messages.log

 

测试

我们来运行一些测试。

test image:
  stage: test
  tags:
    - test
  script:
    - docker exec iris-$CI_COMMIT_REF_NAME irissession iris -U USER "##class(isc.git.GitLab).test()"

发布

最后,我们将镜像发布到注册表中

publish image:
  stage: publish
  tags:
    - test
  script:
    - docker login docker.domain.com -u dev -p 123
    - docker push docker.domain.com/test/docker:$CI_COMMIT_REF_NAME

可以使用 GitLab 秘密变量传递用户名/密码。

现在,我们可以在 GitLab 中看到该镜像:

其他开发者可以从注册表中拉取该镜像。 “环境”标签页上提供了我们所有的环境,可以轻松进行浏览:

 

结论

在这一系列文章中,我介绍了持续交付的常规方式。 这是一个涉及面非常广的话题,您应将这一系列文章视为方法集合,而不是确定性内容。 如果您想自动构建、测试和交付应用程序,可以选择持续交付(一般情况)和 GitLab(特殊情况)。 利用持续交付和容器,您可以根据需要自定义工作流。

链接

后续内容

就是这些! 希望我已介绍了持续交付和容器的基础知识。

但还有一些主题我没有介绍(可能后面会介绍),特别是关于容器的内容:

  • 数据可以在容器外持久保持,以下是相关文档
  • kubernetes 等编排平台
  • InterSystems Cloud Manager
  • 环境管理 – 创建临时环境以进行测试,在功能分支合并后移除旧环境
  • Docker compose 可以实现多容器部署
  • 缩减 docker 镜像大小并缩短构建时间
  • ...
0
0 110
文章 Michael Lei · 九月 27, 2024 2m read

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • 持续交付
  • GitLab 安装和配置
  • GitLab CI/CD
  • 为何使用容器?
  • 容器基础架构
  • 使用容器的 GitLab CI/CD

第一篇文章中,我们介绍了 Git 基础知识,以及为什么对 Git 概念的高层次理解对于现代软件开发如此重要,以及如何使用 Git 开发软件。

第二篇文章中,我们介绍了 GitLab 工作流 – 一个完整的软件生命周期流程和持续交付。

第三篇文章中,我们介绍了 GitLab 的安装和配置以及如何将环境连接到 GitLab。

第四篇文章中,我们编写了 CD 配置。

第五篇文章中,我们讨论了容器与如何(以及为什么)使用它们。

在本文中,我们将探讨运行使用容器的持续交付管道所需的主要组件,以及它们如何协同工作。

我们的配置如下所示:

在这里,我们可以看到三个主要阶段的分离:

  • 构建
  • 传送
  • 运行

构建

在之前的部分中,构建通常是增量式 – 我们计算当前环境与当前代码库之间的差异,并修改我们的环境以与代码库相对应。 使用容器时,每次构建都是完整构建。 构建的结果是一个可以通过依赖关系在任何地方运行的镜像。

传送

在我们的镜像构建并通过测试后,它会被上传到注册表 – 用于托管 docker 镜像的专用服务器。 在那里,它可以替换具有相同标签的旧镜像。 例如,由于对 master 分支的新提交,我们构建了新镜像 (project/version:master),如果测试通过,我们可以用相同标签的新镜像替换注册表中的旧镜像,这样,所有拉取 project/version:master 的人都会获得新版本。

运行

最后,我们的镜像部署完成。 CI 解决方案(如 GitLab)可以控制此流程,也可以由专门的编排器控制,但目的都一样 – 执行一些镜像,定期检查健康状态,如果有新镜像版本可用就进行更新。

查看 docker 网络研讨会以了解这些不同阶段的解释。

或者,从提交的角度来看:<

在我们的交付配置中,我们会:

  • 将代码推送到 GitLab 仓库
  • 构建 docker 镜像
  • 测试该镜像
  • 将镜像发布到我们的 docker 注册表
  • 用新版本替换注册表中的旧容器

为此,我们需要:

  • Docker
  • Docker 注册表
  • 注册域(可选但推荐)
  • GUI 工具(可选)

 

Docker

首先,我们需要在某个地方运行 docker。 我建议从一台运行主流 Linux 发行版(如 Ubuntu、RHEL 或 Suse)的服务器开始。 不要使用面向云的发行版(如 CoreOS、RancherOS 等) - 它们并不适合初学者。 别忘了将存储驱动程序切换为 devicemapper。 

如果我们在讨论大规模部署,那么使用像 Kubernetes、Rancher 或 Swarm 这样的容器编排工具可以自动执行大多数任务,但我们不会探讨它们(至少在这一部分中)。

 

Docker 注册表

这是我们需要运行的第一个容器,它是一个无状态、可扩缩的服务器端应用程序,作用是存储和分发 Docker 镜像。
您应当在想要实现以下目的时使用注册表:

  •  严格控制您的镜像存储位置
  •  完全掌控您的镜像分发管道
  •  将镜像存储和分发紧密整合到您的内部开发工作流中

此处提供了注册表的文档

连接注册表和 GitLab

注:GitLab 包含内置注册表。 您可以运行它而不使用外部注册表。 请阅读本段中链接的 GitLab 文档。

要将您的注册表连接到 GitLab,您需要运行支持 HTTPS的注册表 – 我使用 Let's Encrypt 获取证书,并按照此 Gist 获取证书并将其传递到容器中。 在确认注册表可以通过 HTTPS 访问后(您可以从浏览器检查),请按照这些说明将注册表连接到 GitLab。根据您的需要和 GitLab 安装情况,这些说明会有所不同。就我而言,配置是将注册表证书和密钥(正确命名且具有正确的权限)添加到 /etc/gitlab/ssl 并将以下行添加到 /etc/gitlab/gitlab.rb 中:

registry_external_url 'https://docker.domain.com'
gitlab_rails['registry_api_url'] = "https://docker.domain.com"

重新配置 GitLab 后,我可以看到一个新的注册表标签页,其中提供了如何正确为新构建的镜像添加标签以便它们会出现在这里的信息。

 

在我们的持续交付配置中,我们将为每个分支自动构建一个镜像,如果镜像通过测试,那么我们会将其发布到注册表并自动运行,因此我们的应用程序将在所有“状态”下自动可用,例如,我们可以访问:

  • 几个功能分支,网址为 <featureName>.docker.domain.com
  • 测试版本,网址为 master.docker.domain.com
  • 试生产版本,网址为 preprod.docker.domain.com
  • 生产版本,网址为 prod.docker.domain.com

为此,我们需要一个域名并添加一条通配符 DNS 记录,将 *.docker.domain.com 指向 docker.domain.com 的 IP 地址。 另一种选项是使用不同的端口。

Nginx 代理

由于我们有几个功能分支,需要将子域自动重定向到正确的容器。 为此,我们可以使用 Nginx 作为反向代理。 此处提供了一份指南

GUI 工具

要开始使用容器,您可以使用命令行或 GUI 界面之一。 有许多可用工具,例如:

  • Rancher
  • MicroBadger
  • Portainer
  • Simple Docker UI
  • ...

它们允许您从 GUI 而不是 CLI 创建和管理容器。 下面是 Rancher 的外观:

 

GitLab Runner

与之前相同,要在其他服务器上执行脚本,我们需要安装 GitLab 运行程序。 我在第三篇文章中探讨过这一点。

请注意,您需要使用 Shell 执行器而不是 Docker 执行器。 当您需要从镜像内部提取某些内容时,将使用 Docker 执行器,例如在 Java 容器中构建 Android 应用程序并且只需要一个 apk 时。 在我们的示例中,我们需要整个容器,因此需要使用 Shell 执行器。

 

结论

开始运行容器十分容易,并且有许多工具可供选择。

使用容器的持续交付与常规的持续交付配置在以下几个方面有所不同:

  • 依赖关系的需求在构建时得到满足,并且在镜像构建后无需考虑依赖关系。
  • 可重现性 – 您可以通过本地运行相同的容器轻松重现任何现有环境。
  • 速度 – 由于容器仅包含您显式添加的内容,它们的构建速度更快,更重要的是,它们仅需构建一次并在需要时使用。
  • 效率 – 同上,与虚拟机等相比,容器产生的开销更少。
  • 可扩缩性 – 使用编排工具,您可以根据工作负载自动扩缩应用程序,并且仅消耗当前所需的资源。

后续内容

在下一篇文章中,我们将创建一个利用 InterSystems IRIS Docker 容器的 CD 配置。

0
0 148
文章 Michael Lei · 九月 27, 2024 4m read

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • 持续交付
  • GitLab 安装和配置
  • GitLab CI/CD
  • 为何使用容器
  • 使用容器的 GitLab CI/CD

第一篇文章中,我们介绍了 Git 基础知识、深度理解 Git 概念对现代软件开发至关重要的原因,以及如何使用 Git 开发软件。

第二篇文章中,我们介绍了 GitLab 工作流 – 一个完整的软件生命周期流程,并介绍了持续交付。

第三篇文章中,我们介绍了 GitLab 安装和配置以及将环境连接到 GitLab

第四篇文章中,我们编写了 CD 配置。

在这篇文章中,我们将介绍容器以及使用容器的方法(和原因)。

这篇文章假设读者熟悉 docker 和容器的概念。 如果您想了解容器镜像,请查阅 @Luca Ravazzolo 撰写的文章。

优势

使用容器有诸多优势:

  • 可移植性
  • 效率
  • 隔离
  • 轻量
  • 不可变性

下面我们来具体介绍这些优势。

可移植性

容器将应用程序与运行所需的一切(如配置文件和依赖项)打包在一起。 这样一来,您可以在您本地台式机、物理服务器、虚拟服务器、测试、暂存、生产环境以及公共云或私有云等不同环境中轻松、可靠地运行应用程序。

可移植性的另一个优势是,在您构建 Docker 镜像并确认它可以正常运行后,它便可以在任何运行 docker 的位置(目前是 Windows、Linux 和 MacOS 服务器)运行。

效率

实际上,您只需要运行应用程序进程,而不需要运行所有系统软件等。 容器恰好可以满足这一需求 – 容器仅会运行您明确需要的进程,而不运行其他进程。 由于容器不需要单独的操作系统,占用的资源较少。 虚拟机的大小通常为几千兆字节,而容器的大小通常只有几百兆字节,因此在一台服务器上运行的容器数量要比虚拟机多得多。 由于容器对底层硬件的利用率更高,您需要的硬件更少,从而降低了裸机成本和数据中心成本。

隔离

容器会将应用程序与其他一切隔离开,同时多个容器可以在同一台服务器上运行,它们可以完全彼此独立。 容器之间的任何交互都应明确声明。 如果一个容器发生故障,它不会影响其他容器,并且可以快速重新启动。 得益于这种隔离机制,安全性也得到了保障。 例如,利用裸机上的 Web 服务器漏洞可能会让攻击者访问整个服务器,但如果使用的是容器,攻击者只能访问 Web 服务器容器。

轻量

由于容器不需要单独的操作系统,只需几秒钟即可启动、停止或重新启动,从而可以加快所有相关开发流程并缩短生产时间。 您可以更快地开始工作,并且无需花费任何时间进行配置。

不可变性

不可变基础架构由不可变组件组成,每次部署时都会替换这些组件,而不是就地更新。 这些组件通过每次部署构建一次的通用镜像启动,可以进行测试和验证。不可变性减少了不一致情况,并且可以轻松地在应用程序的不同状态之间进行复制和移动。 详细了解不可变性

新可能

利用上文提到的所有优势,我们可以通过全新的方式管理基础架构和工作流。

编排

裸机或虚拟机环境存在一个问题 – 它们具有个体性,这一问题会在使用过程中带来许多意外,而这些意外通常不尽如人意。 解决这一问题的方法是基础架构即代码 – 利用 DevOps 团队为源代码使用的版本控制方法,采用描述性模型管理基础架构。

通过基础架构即代码,无论环境的起始状态如何,部署命令始终会将目标环境设为相同的配置。 要实现这一点,可自动配置现有目标,也可以丢弃现有目标并重新创建全新的环境。

因此,利用基础架构即代码,团队会更改环境描述并对配置模型进行版本控制,而配置模型通常采用 JSON 等归档完好的代码格式。 发布管道会执行该模型,以配置目标环境。 如果团队需要进行更改,则可以编辑源代码,而不是目标环境。

借助容器,这一切都可以实现,并且实施起来简单得多。 关闭容器并启动一个新容器只需几秒钟,而配置新虚拟机则需要几分钟。 我甚至都没有提到将服务器回滚到空白状态。

扩缩

基于之前的描述,您可能认为基础架构即代码本身是静态的。 并不是这样,因为编排工具也可以根据当前工作负载提供横向扩缩(进行更多相同的配置)。 您仅应运行目前需要的容器,并相应地扩缩应用程序。 这样还可以降低成本。

结论

容器可以简化开发流程。 消除了环境之间的不一致,可以更轻松地进行测试和调试。 可以通过编排构建可扩缩应用程序。可以轻松实现部署或回滚到不可变历史的任意点。

组织希望在更高层级上处理任务,其中所有上述问题均已得到解决,并且我们发现调度程序和编排程序以自动方式为我们处理更多的任务。

后续内容

在下一篇文章中,我们将探讨使用容器进行配置,并创建利用 InterSystems IRIS Docker 容器的 CD 配置。

0
0 100
文章 Michael Lei · 九月 26, 2024 7m read

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • 持续交付
  • GitLab 安装和配置
  • GitLab CI/CD

上一篇文章中,我们介绍了 Git 基础知识、深度理解 Git 概念对现代软件开发至关重要的原因,以及如何使用 Git 开发软件。 我们的侧重点仍是软件开发的实现部分,但本部分会介绍:

  • GitLab 工作流 - 从想法到用户反馈的完整软件生命周期流程
  • 持续交付 – 软件工程方式,团队通过这种方式在短周期内制作软件,从而确保软件可以随时实现可靠发布。 它的目的是更快速、更频繁地构建、测试和发布软件。

GitLab 工作流


GitLab 工作流是软件开发流程整个生命周期中可能采取的操作的逻辑序列。

GitLab 工作流会考虑我们在上一篇文章中探讨的 GitLab 流程。 具体如下:

  1. 想法:每个新提议都始于一个想法。
  2. 问题:探讨想法最有效的方法是为它创建问题。 您的团队和协作者可以在问题跟踪器中帮助您完善和改进问题。
  3. 计划:在讨论达成一致意见后,就可以开始编码了。 但首先,我们需要将问题指定至里程碑和问题看板,以此确定工作流的优先级并进行组织。
  4. 编码:现在,一切安排就绪后,我们就可以编写代码了。
  5. 提交:对草稿满意后,我们便可将代码提交到具有版本控制的功能分支。 上一篇文章详细介绍了 GitLab 流程。
  6. 测试:使用 GitLab CI 运行我们的脚本,以构建并测试应用程序。
  7. 审查:在脚本能够正常运行且测试和构建成功后,我们便可以让代码接受审查并获得批准。
  8. 暂存:现在应该将代码部署到暂存环境,以检查一切是否按预期进行,或者我们是否仍需要进行调整。
  9. 生产:如果一切顺利,便可将代码部署到生产环境!
  10. 反馈:现在可以回顾之前的流程,并检查有哪些阶段的工作需要改进。

再次说明,流程本身不是新的(或者 GitLab 独有的),并且可以通过其他工具来实现。

我们来讨论一下其中的几个阶段以及这些阶段涉及的内容。 还提供文档

问题和计划

GitLab 工作流的开始阶段以问题为中心,问题是指一个功能、一个错误或其他在语义上独立的工作。

问题有多个目的,例如:

  • 管理:问题具有截止日期、指定人员、用时和估计等, 可以帮助跟踪问题解决情况。
  • 行政管理:问题是里程碑的一部分,我们可以通过看板跟踪软件从一个版本过渡到另一个版本的进展。
  • 开发:问题具有与之相关的讨论和提交。

在计划阶段,我们可以按问题的优先级、里程碑、看板将问题分组,并获得问题的概览。

开发在前一部分进行了讨论,只需按照您希望使用的任何 git 流程执行操作即可。 我们开发了新功能并将其合并到 master 分支后,接下来应怎样操作?

持续交付

持续交付是一种软件工程方式,团队通过这种方式在短周期内制作软件,从而确保软件可以随时实现可靠发布。 它的目的是更快速、更频繁地构建、测试和发布软件。 这种方式允许对生产中的应用程序进行更多增量更新,从而帮助缩减交付更改的成本、缩短时间,以及降低风险。 简单且可重复的部署过程对于持续交付非常重要。

GitLab 中的持续交付

在 GitLab 中,持续交付配置按仓库以 YAML 配置文件形式定义。

  • 持续交付配置是一系列连续的阶段
  • 每个阶段都有一个或多个并行执行的脚本

脚本定义了一个操作以及执行该操作需要满足的条件:

  • 要执行的操作(运行 OS 命令、运行容器)?
  • 何时运行脚本:
    • 触发脚本的条件(特定分支)?
    • 之前的阶段失败时是否运行?
  • 手动运行还是自动运行?
  • 脚本在什么环境中运行?
  • 执行脚本后保存哪些工件(这些工件会从环境上传到 GitLab,以便轻松访问)?

环境是配置好的服务器或容器,可用于运行脚本。

运行程序用于在特定环境中执行脚本。 运行程序连接到 GitLab,并根据需要执行脚本。

运行程序可以部署在服务器上、容器上,甚至部署在本地机器上。

持续交付是如何实现的?

  1. 新提交推送到仓库中。
  2. GitLab 检查持续交付配置。
  3. 持续交付配置包含适用于所有情况的全部脚本,因此要过滤出应针对这一特定提交运行的一组脚本(例如提交到 master 分支仅会触发与 master 分支相关的操作)。 这组脚本称为管道
  4. 管道是在目标环境中执行的,执行结果会保存并显示在 GitLab 中。

例如,下面是提交到 master 分支后执行的一个管道:

管道包含四个阶段,各阶段连续执行

  1. 加载阶段会将代码加载到服务器中
  2. 测试阶段会运行单元测试
  3. 封装阶段包含两个并行运行的脚本:
    • 构建客户端
    • 导出服务器代码(主要用于提供信息)
  4. 部署阶段会将构建的客户端移动到 Web 服务器目录中。

我们可以看到,每个脚本都成功运行,如果其中一个脚本运行失败,则默认不会运行后面的脚本(但我们可以更改此行为):

如果我们打开脚本,可以查看日志并确定脚本运行失败的原因:

Running with gitlab-runner 10.4.0 (857480b6)
 on test runner (ab34a8c5)
Using Shell executor...
Running on gitlab-test...
Fetching changes...
Removing diff.xml
Removing full.xml
Removing index.html
Removing tests.html
HEAD is now at a5bf3e8 Merge branch '4-versiya-1-0' into 'master'
From http://gitlab.eduard.win/test/testProject
 * [new branch] 5-versiya-1-1 -> origin/5-versiya-1-1
 a5bf3e8..442a4db master -> origin/master
 d28295a..42a10aa preprod -> origin/preprod
 3ac4b21..7edf7f4 prod -> origin/prod
Checking out 442a4db1 as master...Skipping Git submodules setup$ csession ensemble "##class(isc.git.GitLab).loadDiff()"

[2018-03-06 13:58:19.188] Importing dir /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/

[2018-03-06 13:58:19.188] Loading diff between a5bf3e8596d842c5cc3da7819409ed81e62c31e3 and 442a4db170aa58f2129e5889a4bb79261aa0cad0

[2018-03-06 13:58:19.192] Variable modified var=$lb("MyApp/Info.cls")

Load started on 03/06/2018 13:58:19 Loading file /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/MyApp/Info.cls as udl Load finished successfully.

[2018-03-06 13:58:19.241] Variable items var="MyApp.Info.cls" var("MyApp.Info.cls")=""

Compilation started on 03/06/2018 13:58:19 with qualifiers 'cuk /checkuptodate=expandedonly' Compiling class MyApp.Info Compiling routine MyApp.Info.1 ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1] TEXT: quit, "1.0" } Detected 1 errors during compilation in 0.010s.

[2018-03-06 13:58:19.252] ERROR #5475: Error compiling routine: MyApp.Info.1. Errors: ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1] > ERROR #5030: An error occurred while compiling class 'MyApp.Info' ERROR: Job failed: exit status 1

编译错误导致脚本失败。

结论

  • GitLab 支持软件开发的所有主要阶段。
  • 持续交付可以帮助您自动执行软件构建、测试和部署任务。

后续内容

在下一篇文章中,我们将:

  • 安装 GitLab。
  • 将它连接到多个安装了 InterSystems 产品的环境。
  • 编写持续交付配置。

我们来探讨一下持续交付的运作方式。

首先,我们需要多个环境以及与之对应的分支。 代码进入此分支,并交付到目标环境:

环境分支交付有权提交的角色有权合并的角色
测试master自动开发者、所有者开发者、所有者
preprod预生产自动所有者
prod生产半自动(按下按钮进行交付)

所有者

作为示例,我们将使用 GitLab 流程开发一个新功能,并使用 GitLab CD 进行交付。

  1. 在功能分支中开发功能。
  2. 对功能分支进行审查并将其合并到 master 分支中。
  3. 一段时间(合并了多个功能)后,将 master 分支合并到 preprod 分支中
  4. 一段时间(用户测试等)后,将 preprod 分支合并到 prod 分支中

具体如下图所示:

  1. 开发和测试
    • 开发者将新功能的代码提交到单独的功能分支中
    • 功能稳定后,开发者将功能分支合并到 master 分支中
    • 来自 master 分支的代码被交付到测试环境,在其中进行加载和测试
  2. 交付到预生产环境
    • 开发者创建从 master 分支到 preprod 分支的合并请求
    • 仓库所有者在一段时间后批准合并请求
    • 来自 preprod 分支的代码被交付到预生产环境
  3. 交付到生产环境
    • 开发者创建从 preprod 分支到 prod 分支的合并请求
    • 仓库所有者在一段时间后批准合并请求
    • 仓库所有者按下“部署”按钮
    • 来自 prod 分支的代码被交付到生产环境

也可以用示意图形式表示此流程:

 

0
0 98
文章 Michael Lei · 九月 26, 2024 6m read

大家都搭建了测试环境。

有些人很幸运,可以在完全独立的环境中运行生产。

-- 佚名

.

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • GitLab CI/CD
  • 包含容器的 CI/CD

第一部分将介绍现代软件开发的基础 – Git 版本控制系统和各种 Git 流程。

Git 101

虽然我们将主要探讨软件开发的概况以及 GitLab 如何帮助我们实现这一目标,但 Git,或者说 Git 设计中的几个基础的高级概念对于更好地理解后面的概念非常重要。

也就是说,Git 是基于这些概念的版本控制系统(还有更多概念,但这几个概念最为重要):

  • 非线性开发意味着,虽然我们的软件是从版本 1 到版本 2、再到版本 3 相继发布的,但实际上从版本 1 到版本 2 的升级是并行完成的 – 多名开发者会同时开发许多功能/错误修复。
  • 分布式开发意味着开发者独立于一个中央服务器或其他开发者,可以轻松地在自己的环境中进行开发。
  • 合并 – 基于前面提到的两个概念,我们会发现很多不同的版本同时存在,我们需要将它们统一成一个完整的状态。

我的意思不是说 Git 发明了这些概念。 Git 并没有发明这些概念, 而是使这些概念变得简单、流行,并加入了多个相关创新概念,也就是说,架构即代码/容器化改变了软件开发。

核心 git 术语

仓库是存储数据以及关于数据的元信息的项目。

  • “从物理层面来讲”,仓库是磁盘上的目录。
  • 仓库用于存储文件和目录。
  • 仓库还会存储每个文件的完整变更历史。

仓库可以:

  • 存储在您自己的计算机本地
  • 远程存储在远程服务器上

但从 git 的角度来看,本地仓库与远程仓库之间没有特殊的区别。

提交是仓库的固定状态。 很显然,如果每次提交都存储仓库的完整状态,我们的仓库很快就会变得非常大。 因此,提交会存储差异,也就是当前提交与其父提交之间的差异。

不同的提交可以具有不同数量的父提交:

  • 0 个 – 仓库中的第一个提交没有父提交。
  • 1 个 – 一切如常 - 我们的提交改变了仓库中的某些内容,就像在父提交期间一样
  • 2 个 – 当我们有两个不同的仓库状态时,我们可以将它们合并成一个新状态。 该状态和该提交就会有 2 个父提交。
  • >2 个 – 当我们将 2 个以上的不同仓库状态合并为一个新状态时,就会有 2 个以上的父提交。 这一概念与我们的讨论并没有特别大的关系,但它确实存在。

现在,对于父提交,每个与之不同的提交都被称为子提交。 每个父提交可以有任意数量的子提交。

分支是对提交的引用(或指针),如下图所示:

该图像显示的仓库具有两个提交(灰色圆圈),第二个圆圈是 master 分支的头部。 在我们添加更多提交后,仓库开始变成下图所示的状态:

这是最简单的情况。 我们的开发者一次负责处理一个更改。 但通常会有很多开发者同时负责处理不同的功能,我们需要使用提交树显示仓库中的变化。

提交树

我们从相同的起始状态开始。 仓库具有两个提交:

但现在,两名开发者在同时工作,为了避免相互干扰,他们在单独的分支中工作:

一段时间后,他们需要合并所做的更改,为此,他们创建了合并请求(也叫拉取请求), 顾名思义,该请求可将两个不同的仓库状态(本例中,我们要将 develop 分支合并到 master 分支中)合并为一个新状态。 接受相应审查并获得批准后,仓库状态如下图所示:

开发继续进行:

Git 101 - 总结

主要概念:

  • Git 是一个非线性的分布式版本控制系统。
  • 仓库用于存储数据以及关于数据的元信息。
  • 提交是仓库的固定状态。
  • 分支是对提交的引用。
  • 合并请求(也叫拉取请求)是将两个不同的仓库状态合并为一个新状态的请求。

如果您想了解更多关于 Git 的信息,可以阅读相关书籍

Git 流程

现在,读者已熟悉基本的 Git 术语和概念,我们来探讨一下如何使用 Git 管理软件生命周期的开发部分。很多实践(称为流程)介绍了使用 Git 的开发流程,但我们只会探讨其中两个:

  • GitHub 流程
  • GitLab 流程

GitHub 流程

GitHub 流程非常简单。 具体如下:

  1. 从仓库创建一个分支。
  2. 将更改提交到新分支
  3. 从您的分支发送一个拉取请求,其中包含您提议的更改,以发起讨论。
  4. 根据需要在您的分支上提交更多更改。 您的拉取请求将自动更新。
  5. 在分支准备好合并后,立即合并拉取请求。

我们需要遵守几条规则:

  • master 分支始终可部署(并且可正常运行!)
  • 不直接在 master 分支中进行开发
  • 在功能分支中进行开发
  • master 分支 == 生产* 环境**
  • 需要尽可能频繁地部署到生产环境

* 不要与“Ensemble 生产”混淆,这里的“生产”是指正式。

** 环境是配置好的代码运行位置,可以是服务器、虚拟机,甚至可以是容器。

如下图所示:

有关 GitHub 流程的更多信息,请参阅此处。 我们还提供了图解指南

GitHub 流程非常适合小型项目,如果您刚开始使用 Git 流程,可以尝试一下。 不过,GitHub 也会使用 GitHub 流程,因此也可以在大型项目中使用 GitHub 流程。

GitLab 流程

如果您还没有准备好立即部署到生产环境,GitLab 流程提供 GitHub 流程 + 环境。 具体做法是:在功能分支中进行开发(与上例相同),合并到 master 分支中(与上例相同),但这里有一个不同之处: master 分支仅等同于测试环境。 除此之外,还有链接到可能存在的各种其他环境的“环境分支”。

通常存在三个环境(可以根据需要创建更多环境):

  • 测试环境 == master 分支
  • 预生产环境 == preprod 分支
  • 生产环境 == prod 分支

进入其中一个环境分支的代码应立即移至相应的环境中,此流程可通过以下方式完成:

  • 自动(我们将在第 2 部分和第 3 部分探讨)
  • 半自动(与自动方式相同,唯一的区别是应按下按钮授权部署)
  • 手动

完整的流程是:

  1. 在功能分支中开发功能。
  2. 对功能分支进行审查并将其合并到 master 分支中。
  3. 一段时间(合并了多个功能)后,将 master 分支合并到 preprod 分支中
  4. 一段时间(用户测试等)后,将 preprod 分支合并到 prod 分支中
  5. 在我们进行合并和测试时,多个新功能已开发完毕并合并到 master 分支中,因此转到  3。

具体如下图所示:

有关 GitLab 流程的更多信息,请参阅此处

结论

  • Git是一个非线性的分布式版本控制系统。
  • Git 流程可用作软件开发周期的准则,有多种 Git 流程可供选择。

链接

讨论问题

  • 您使用 Git 流程吗? 使用哪一种?
  • 您为普通项目使用多少个环境?

后续内容

在接下来的部分中,我们将:

  • 安装 GitLab。
  • 探讨一些建议的调整。
  • 讨论 GitLab 工作流(不要与 GitLab 流程混淆)。

敬请关注。

0
0 129
文章 Weiwei Gu · 九月 14, 2023 2m read

InterSystems 还发布了容器化部署的IRIS。这篇文章旨在演示 InterSystems IRIS 和依赖 IRIS 后端的应用程序如何打包到镜像中并在容器中的其他计算机中运行,以及这样做有多么简单。

容器运行包含所有必需的可执行文件、二进制代码、库和配置文件的镜像。镜像可以从一台机器移动到另一台机器,像 Docker Hub 这样的镜像存储库可以简化这个过程。

我在本演示中使用了 Open Exchange 的应用程序。

演示视频:https://www.loom.com/share/93f9a760b5f54c0a8811b7a212387b9d

IRIS 数据平台社区版的镜像(image)可以在 InterSystems 容器注册表中找到:

https: //containers.intersystems.com/contents

为了在主机中使用 IRIS 的容器化实例,应在运行时拉取它。

为此,Dockerfile 需要具有以下命令,如下所示:

Dockerfile:

Dockerfile

0
0 208
文章 yaoguai wan · 九月 30, 2022 4m read

前言

本人因技术需要,了解到了IRIS Health产品,在听了产品介绍会之后,感觉该产品是否有趣,并且比较符合自己目前的需求,因此大概了解了下IRIS的架构。以下是本人的浅显理解,如有错误之处欢迎讨论。

本人从产品介绍和社区的文档中,了解到IRIS的大概功能分类

  • InterSystems IRIS是一款数据平台,适用于软甲开发人员
    • 基于FHIR
    • 整合医疗全流程数据,通过机器学习和人工智能分析
    • 业务优化
  • 数据管理
  • Sharding数据分片技术
  • 分布式架构
  • IRIS互操作性
  • 数据分析能力
  • IRIS对FHIR的支持
  • 机器学习与自动化

其中结合到自己想要研究的领域,想要探索是否可以利用该产品并结合其他工具开发一套通用的专病数据库构建及应用方法。

2
0 471
文章 Michael Lei · 九月 12, 2022 1m read

针对InterSystems开发者社区的分析。使用InterSystems IRIS BI (DeepSee)、Power BI和Logi Report Designer制作的项目,可视化并分析InterSystems 开发者社区上的成员、文章、问题、答案、观点和其他内容和活动。

你可以看到自己的活动、文章和问题。跟踪你的贡献如何改变开发者社区。

使用IRIS BI、Adaptive Analytics、InterSystems Reports、Tableau和Power BI分析关于你和你朋友的统计数据。

该项目包含预配置的IRIS和Atscale在Docker容器中的部署以及BI系统的项目文件。

更多细节信息请见相应应用的README。

这个项目也支持在线部署,你可以在这里查看。

0
0 107
公告 Michael Lei · 五月 11, 2022

InterSystems Kubernetes Operation(IKO)3.3版现已通过WRC下载页面和InterSystems容器注册中心提供。
IKO通过提供一个易于使用的irisCluster资源定义,简化了在Kubernetes中使用InterSystems IRIS或InterSystems IRIS for Health的工作。完整的功能清单见IKO文档,包括轻松的分片、镜像和ECP的配置。

IKO 3.3 亮点:

  • 支持InterSystems IRIS和InterSystems IRIS for Health 2021.2 以及 2022.1版本
  • 支持 Kuberentes 1.21
  • 将常见的系统警报和监控(SAM)配置作为irisCluster的一部分进行部署
  • InterSystems API Manager(IAM)现在也可以作为 irisCluster的一部分进行部署和管理
  • 自动标记Mirror对的活跃端,因此服务可以始终指向激活的镜像成员
0
0 108
文章 Michael Lei · 五月 3, 2022 6m read

所有源代码均在: https://github.com/antonum/ha-iris-k8s 

在上一篇文章中,我们讨论了如何在k8s集群上建立具有高可用性的IRIS,基于分布式存储,而不是传统的镜像。作为一个例子,那篇文章使用了Azure AKS集群。在这一篇中,我们将继续探讨k8s上的高可用配置。这一次,基于Amazon EKS(AWS管理的Kubernetes服务),并将包括一个基于Kubernetes 快照进行数据库备份和恢复的选项。

安装

开始干活. 首先需要一个AWS账户,安装 AWS CLI,kubectl 和 eksctl 工具. 要创建新的集群,请运行以下命令:

eksctl create cluster \
--name my-cluster \
--node-type m5.2xlarge \
--nodes 3 \
--node-volume-size 500 \
--region us-east-1

这个命令需要大约15分钟,部署EKS集群并使其成为你的kubectl工具的默认集群。你可以通过运行以下代码来验证你的部署:

0
0 564
公告 Michael Lei · 四月 9, 2022

Docker 20.10.14(2022年3月23日发布)改变了赋予容器的Linux能力,其方式与InterSystems IRIS 2021.1(及以上)容器的Linux能力检查器不兼容。 

在Linux上运行Docker 20.10.14的用户会发现,IRIS 2021.1+容器将无法启动,并且日志会错误地报告缺少所需的Linux能力。  比如说。

[ERROR] Required Linux capability cap_setuid is missing.
[ERROR] Required Linux capability cap_dac_override is missing.
[ERROR] Required Linux capability cap_fowner is missing.
[ERROR] Required Linux capability cap_setgid is missing. 
[ERROR] Required Linux capability cap_kill is missing.
[FATAL] Your IRIS container is missing one or more required Linux capabilities.

解决方案

0
0 243
公告 Michael Lei · 三月 25, 2022

大家好! 对于那些参加了2021年虚拟峰会的体验实验室的人来说,你可能还记得其中一个实验室会议是围绕Kubernetes进行的。我们现在已经将该实验室转换为完全线上按需使用。你可以启动一个小型的虚拟机集群,并按照练习来管理你的Kubernetes集群,将InterSystems IRIS容器部署到其中,并观察它在摧毁一个吊舱时的自我修复性质。

如果你有兴趣,这是一个很好的Kubernetes介绍。请看这里: 用InterSystems IRIS 和 Kubernetes实现高可用

0
0 352
文章 Michael Lei · 十二月 30, 2021 1m read

对于那些在某种程度上需要测试ECP的水平可扩展性(计算能力和/或用户和进程的并发性),但又懒得建立环境、配置服务器节点等的人来说,我刚刚在Open Exchange上发布了OPNEx-ECP部署的应用/示例。 

0
0 156
文章 Hao Ma · 三月 26, 2021 15m read

关键字:IRIS,IntegratedML,Flask,FastAPI,TensorFlow Serving,HAProxy,Docker,Covid-19

目的:

过去几个月里,我们提到了一些深度学习和机器学习的快速演示,包括一个简单的 Covid-19 X 射线图像分类器和一个用于可能的 ICU 入院的 Covid-19 实验室结果分类器。  我们还介绍了 ICU 分类器的 IntegratedML 演示实现。  虽然“数据科学”远足仍在继续,但从“数据工程”的角度来看,或许也是尝试一些 AI 服务部署的好时机 - 我们能否将目前所接触到的一切都封装成一套服务 API?  我们可以利用哪些常用的工具、组件和基础架构,以最简单的方式实现这样的服务堆栈?

0
0 1420
文章 Claire Zheng · 一月 21, 2021 3m read

大家好!

我想跟大家分享一个个人项目,该项目始于工作中的一个简单需求:“能否知道我们使用了多少个Caché许可证?”

在阅读社区的其他文章时,我发现了一篇David Loveluck写的非常棒的文章:APM——使用Caché History Monitor

我根据David的这篇文章,开始使用Caché History Monitor并显示所有这些信息。

在面临“选择哪种很酷的技术”这个问题时,我决定使用简单而强大的CSP,这样我的客户可以认识到Caché不仅仅是MUMPS/终端。

在创建了页面以显示许可、数据库增长和CSP会话的历史记录后,我决定为System Dashboard和进程页面创建一个新设计。

我的Caché实例运行得良好。

但是,如果使用IRIS呢?

0
0 139
文章 Li Yan · 一月 11, 2021 27m read

Amazon Web Services (AWS) 云提供广泛的云基础设施服务,例如计算资源、存储选项和网络,这些都非常实用:按需提供,几秒内就可用,采用即付即用定价的模式。 新服务可得到快速配置,且前期无需支出大量资金。 这使得大企业、初创公司、中小型企业以及公共部门的客户可以访问他们所需的基础设施,从而快速响应不断变化的业务需求。

更新日期:2019 年 10 月 15 日

0
0 317
文章 Jeff Liu · 一月 7, 2021 28m read

Google Cloud Platform (GCP) 为基础架构即服务 (IaaS) 提供功能丰富的环境,其作为云提供完备的功能,支持所有的 InterSystems 产品,包括最新的 InterSystems IRIS 数据平台。 与任何平台或部署模型一样,必须留心以确保考虑到环境的各个方面,例如性能、可用性、操作和管理程序。 本文将详细阐述所有这些方面。

以下概述和详细内容由谷歌提供,可在此处找到。

概述

GCP 资源

GCP 由一系列物理资产(例如计算机和硬盘驱动器)和虚拟资源(例如虚拟机(VM))组成,它们分布于谷歌遍布全球的数据中心。 每个数据中心的位置都是一个泛区域。 每个区域都是地区的集合,这些地区在该区域内彼此分离。 每个地区都通过一个名称标识,名称由字母标识符和相应区域的名称组成。

这种资源分配带来众多优势,包括发生故障时提供冗余,以及通过将资源配置在客户端附近来减少延迟。 这种分配也引入一些有关如何统筹资源的规则。

访问 GCP 资源

在云计算中,物理硬件和软件变成了服务。 这些服务提供对基础资源的访问。 在 GCP 上开发基于 InterSytems IRIS 的应用程序时,您可混合和匹配这些服务,组合它们来提供您所需的基础架构,然后添加您的代码来实现您要构建的方案。 有关可用服务的详细信息, 可在此处找到。

项目

您分配和使用的任何 GCP 资源必须属于一个项目。 项目由设置、权限和其他描述应用程序的元数据组成。 根据区域和地区规则,单个项目中的资源能够轻松协作,例如通过内部网络进行通信。 每个项目包含的资源在项目边界上保持独立;您只能通过外部网络连接来互连它们。

服务交互

GCP 提供 3 种与服务和资源交互的基本方法。

控制台

Google Cloud Platform 控制台提供基于 web 的图形用户界面,供您管理 GCP 项目和资源。 使用 GCP 控制台,您可创建新项目,或选择现有项目,可使用您在项目环境中创建的资源。 您可以创建多个项目,因此您可以使用项目以任何对您有意义的方式分开您的工作。 例如,如果您想确保只有某些团队成员可以访问项目中的资源,而所有团队成员可以继续访问另一个项目中的资源,则可以开始一个新项目。

命令行界面

如果您喜欢在终端窗口中工作,Google Cloud SDK 提供 gcloud 命令行工具,让您可以访问所需的命令。 gcloud 工具可用于管理您的开发工作流程和 GCP 资源。 有关 gcloud 的详细内容可在此处找到。

GCP 也提供 Cloud Shell,一种基于浏览器的 GCP 交互 shell 环境。 可从 GCP 控制台访问 Cloud Shell。 Cloud Shell 提供:

  • 临时计算引擎虚拟机实例。
  • 从 web 浏览器通过命令行访问实例。
  • 内置代码编辑器。
  • 5 GB 持久性磁盘存储。
  • 预安装 Google Cloud SDK 和其他工具。
  • 支持 Java、Go、Python、Node.js、PHP、Ruby 和 .NET 语言。
  • Web 预览功能。
  • 访问 GCP 控制台项目和资源的内置授权。
  • 客户端库

    Cloud SDK 拥有客户端库,让您轻松创建和管理资源。 GCP 客户端库公开 API 有两个主要目的:

    • 应用 API 提供对服务的访问。 应用 API 针对支持的语言(例如 Node.js 和 Python )进行了优化。 客户端库围绕服务隐喻而设计,因此您可以更自然地使用服务,并编写更少的样板代码。 客户端库还提供身份验证和授权助手。 有关详细信息可在此处找到。
    • 管理 API 提供资源管理功能。 例如,如果您想构建自己的自动化工具,可以使用管理 API。

    您还可以使用 Google API 客户端库来访问产品的 API,如 Google Map、Google Drive 和 YouTube。 有关 GCP 客户端库的详细信息可在此处找到。

    InterSystems IRIS 示例体系结构

    本文部分内容阐述了面向 GCP 的 InterSystems IRIS 部署示例,旨在为特定应用程序的部署抛砖引玉。 这些示例可用作很多部署方案的指南。 此参考体系结构拥有非常强大的部署选项,从最小规模的部署,到满足计算和数据需求的大规模可扩展工作负载,不一而足。

    本文还介绍了高可用性和灾难恢复选项以及其他建议的系统操作。 个体可对这些进行相应的修改以支持其组织的标准实践和安全策略。

    针对您的特定应用,就基于 GCP 的 InterSystems IRIS 部署,您可联系 InterSystems 进一步探讨。


    示例参考体系结构

    以下示例体系结构按照容量和功能逐步升级的顺序讲述了几种不同的配置, 分别为小型开发/生产/大型生产/分片集群生产。先从中小型配置讲起,然后讲述具有跨地区高可用性以及多区域灾难恢复的大规模可扩展性解决方案。 此外,还讲述了一个将 InterSystems IRIS 数据平台的新分片功能用于大规模处理并行 SQL 查询的混合工作负载的示例。

     

    小型开发配置

    在本示例中,显示了一个能支持 10 名开发人员和 100GB 数据的小型开发环境,这基本是最小规模的配置。 只要适当地更改虚拟机实例类型并增加持久性磁盘存储,即可轻松支持更多的开发人员和数据。

    这足以支持开发工作,并让您熟悉 InterSystems IRIS 功能以及 Docker 容器的构建和编排(如果需要的话)。 小型配置通常不采用具有高度可用性的数据库镜像,但是如果需要高可用性,则可随时添加。

    小型配置示例图

    示例图 2.1.1-a 显示了图表 2.1.1-b 中的资源。 其中包含的网关只是示例,可做相应地调整以适应您组织的标准网络实践。

    下列 GCP VPC 项目资源是针对最小规模的配置提供的。 可根据需求添加或删除 GCP 资源。

    小型配置 GCP 资源

    下表提供了小型配置 GCP 资源的示例。

    需要考虑适当的网络安全和防火墙规则,以防止对 VPC 的不必要访问。 谷歌提供网络安全最佳做法供您入门使用,可在此处找到。

    注意:VM 实例需要公共 IP 地址才能访问 GCP 服务。 谷歌建议使用防火墙规则来限制这些 VM 实例的传入,尽管这种做法可能会引起一些问题。

    如果您的安全策略确实需要内部 VM 实例,则您需要在网络上手动设置 NAT 代理和相应的路由,以便内部实例可以访问互联网。 务必要明确,您无法使用 SSH 直接完全连接到内部 VM 实例。 要连接到此类内部机器,必须设置具有外部 IP 地址的堡垒实例,然后建立隧道通过它。 可以配置堡垒主机,以提供进入 VPC 的外部入口点。

    有关堡垒主机的详细信息,可在此处找到。

    产品配置

    在本示例中,展示了一个规模较大的产品配置,其采用 InterSystems IRIS 数据库镜像功能来支持高可用性和灾难恢复。

    此配置包括 InterSystems IRIS 数据库服务器同步镜像对,该镜像服务器在区域 1 内分为两个地区,用于自动故障转移,在区域 2 内的第三个 DR 异步镜像成员用于灾难恢复,以防万一整个 GCP 区域脱机 。

    InterSystems Arbiter 和 ICM 服务器部署在单独的第三个地区,以提高弹性。  此示例体系结构还包括一组可选的负载均衡 web 服务器,用于支持启用 Web 的应用程序。 这些使用 InterSystems 网关的 web 服务器可以根据需要进行缩放。

    产品配置示例图

    示例图 2.2.1-a 显示了图表 2.2.1-b 中的资源。 其中包含的网关只是示例,可做相应地调整以适应您组织的标准网络实践。

    建议将以下 GPC VPC 项目中的资源作为分片集群部署的最低配置。 可根据需求添加或删除 GCP 资源。

    产品配置 GCP 资源

    下表提供了产品配置 GCP 资源的示例。

    大型产品配置

    在本示例中,提供了一个大规模可缩放性配置。该配置通过扩展 InterSystems IRIS 功能也引入使用 InterSystems 企业缓存协议 (ECP:EnterpriseCacheProtocol) 的应用程序服务器,实现对用户的大规模横向缩放。 本示例甚至包含了更高级别的可用性,因为即使在数据库实例发生故障转移的情况下,ECP 客户端也会保留会话细节。 多个 GCP 地区与基于 ECP 的应用程序服务器和部署在多个区域中的数据库镜像成员一起使用。 此配置能够支持每秒数千万次的数据库访问和数万亿字节数据。

    大型产品配置示例图

    示例图 2.3.1-a 显示了图表 2.3.1-b 中的资源。  其中包含的网关只是示例,可做相应地调整以适应您组织的标准网络实践。

    此配置中包括一个故障转移镜像对,四个或更多的 ECP 客户端(应用程序服务器),以及每个应用程序服务器对应一个或多个 Web 服务器。 故障转移数据库镜像对在同一区域中的两个不同 GCP 地区之间进行划分,以提供故障域保护,而 InterSystems Arbiter 和 ICM 服务器则部署在单独的第三地区中,以提高弹性。

    灾难恢复扩展至第二个 GCP 区域和地区,与上一示例中的情况类似。 如果需要,可以将多个 DR 区域与多个 DR 异步镜像成员目标一起使用。

    建议将以下 GPC VPC 项目中的资源作为大型生产部署的最低配置。 可根据需求添加或删除 GCP 资源。

    大型产品配置 GCP 资源

    下表提供了大型产品配置 GCP 资源的示例。

    采用 InterSystems IRIS 分片集群的生产配置

    在此示例中,提供了一个针对 SQL 混合工作负载的横向缩放性配置,其包含 InterSystems IRIS 的新分片集群功能,可实现 SQL 查询和表跨多个系统的大规模横向缩放。 本文后面将详细讨论 InterSystems IRIS 分片集群及其功能。

    采用 InterSystems IRIS 分片集群的生产配置

    示例图 2.4.1-a 显示了图表 2.4.1-b 中的资源。  其中包含的网关只是示例,可做相应地调整以适应您组织的标准网络实践。

    此配置中包括四个镜像对,它们为数据节点。 每个故障转移数据库镜像对在同一区域中的两个不同 GCP 地区之间进行划分,以提供故障域保护,而 InterSystems Arbiter 和 ICM 服务器则部署在单独的第三地区中,以提高弹性。

    此配置允许从集群中的任何数据节点使用所有的数据库访问方法。 大型 SQL 表数据在物理上跨所有数据节点进行分区,以实现查询处理和数据卷的大规模并行。 将所有这些功能组合在一起,就可以支持复杂的混合工作负载,比如大规模分析 SQL 查询及引入的新数据,所有这一切均在一个 InterSystems IRIS 数据平台中执行。

    注意,上面图表中以及下表“资源类型”列中的术语“计算[Engine]”是一个表示 GCP(虚拟)服务器实例的 GCP 术语,将在本文的 3.1节中做进一步介绍。 它并不表示或暗示本文后面所描述的集群体系结构中对“计算节点”的使用。

    建议将以下 GPC VPC 项目中的资源作为分片集群部署的最低配置。 可根据需求添加或删除 GCP 资源。

    使用分片集群配置 GCP 资源的产品

    下表提供了分片集群配置 GCP 资源的示例。


    云概念简介

    Google Cloud Platform (GCP) 为基础架构即服务 (IaaS) 提供功能丰富的云环境,使其具备完备的功能,支持所有的 InterSystems 产品,包括支持基于容器的 DevOps 及最新的 InterSystems IRIS 数据平台。 与任何平台或部署模型一样,必须留心以确保考虑到环境的各个方面,例如性能、可用性、系统操作、高可用性、灾难恢复、安全控制和其他管理程序。 本文档将介绍所有云部署涉及的三个主要组件:计算、存储和网络。

    计算引擎(虚拟机)

    GCP 中存在数个针对计算引擎资源的选项,以及众多虚拟 CPU 和内存规范及相关存储选项。 在 GCP 中值得注意的一点是,对给定机器类型中 vCPU 数量的引用等于一个 vCPU,其是虚拟机监控程序层上物理主机中的一个超线程。

    就本文档的目的而言,将使用 n1-standard * 和 n1-highmem * 实例类型,这些实例类型在大多数 GCP 部署区域中广泛可用。 但是,对于将大量数据缓存在内存中的大型工作数据集而言,使用 n1-ultramem * 实例类型是不错的选择。 除非另有说明,否则使用默认实例设置(例如实例可用性策略)或其他高级功能。 有关各种机器类型的详细信息,可在此处找到。

    磁盘存储

    与 InterSystems 产品最直接相关的存储类型是持久性磁盘类型,但是,只要了解并适应数据可用性限制,本地存储可以用于高水平的性能。 还有其他一些选项,例如云存储(存储桶),但是这些选项更特定于单个应用程序的需求,而非支持 InterSystems IRIS 数据平台的操作。

    与大多数其他云提供商一样,GCP 对可与单个计算引擎关联的持久性存储施加了限制。 这些限制包括每个磁盘的最大容量、关联到每个计算引擎的持久性磁盘的数量,以及每个持久性磁盘的 IOPS 数量,对单个计算引擎实例 IOPS 设置上限。 此外,对每 GB 磁盘空间设有 IOPS 限制,因此有时需要调配更多磁盘容量才能达到所需的 IOPS 速率。

    这些限制可能会随着时间而改变,可在适当时与谷歌确认。

    磁盘卷有两种类型的持久性存储类型:“标准持久性”磁盘和“SSD 持久性”磁盘。 SSD 持久性磁盘更适合于那些要求低延迟 IOPS 和高吞吐量的生产工作负载。 标准持久性磁盘对于非生产开发和测试或归档类型的工作负载,是一种更经济的选择。

    有关各种磁盘类型及限制的详细信息,可在此处找到。

    VPC 网络

    强烈建议采用虚拟私有云 (VPC) 网络来支持 InterSystems IRIS 数据平台的各个组件,同时提供正确的网络安全控制、各种网关、路由、内部 IP 地址分配、网络接口隔离和访问控制。 本文档中提供了一个详细的 VPC 示例。

    有关 VPC 网络和防火墙的详细信息,可在此处找到。


    虚拟私有云 (VPC) 概述

    GCP VPC 与其他云提供商略有不同,其更加简单和灵活。 可在此处找到各概念的比较。

    在 GCP 项目中,每个项目允许有数个 VPC(目前每个项目最多允许 5 个),且创建 VPC 网络有两个选项——自动模式和自定义模式。

    此处提供每个类型的详细信息。

    在大多数大型云部署中,采用多个 VPC 将各种网关类型与以应用为中心的 VPC 进行隔离,并利用 VPC 对等进行入站和出站通信。 有关适合您的公司使用的子网和任何组织防火墙规则的详细信息,强烈建议您咨询您的网络管理员。 本文档不阐述 VPC 对等方面的内容。

    在本文档提供的示例中,使用 3 个子网的单一 VPC 用于提供各种组件的网络隔离,以应对各种 InterSystems IRIS 组件的可预测延迟和带宽以及安全性隔离。

    网络网关和子网定义

    本文档的示例中提供了两种网关,以支持互联网和安全 VPN 连接。 要求每个入口访问都具有适当的防火墙和路由规则,从而为应用程序提供足够的安全性。 有关如何使用路由的详细信息,可在此处找到。

    提供的示例体系结构中使用了 3 个子网,它们专与 InterSystems IRIS 数据平台一起使用。 这些单独的网络子网和网络接口的使用为上述 3 个主要组件的每一个提供了安全控制、带宽保护和监视方面的灵活性。 有关各种用例的详细信息,可在此处找到。

    有关创建具有多个网络接口的虚拟机实例的详细信息,可在此处找到。

    这些示例中包含的子网:

  • 用户空间网络用于入站连接用户和查询
  • 分片网络用于分片节点之间的分片间通信
  • 镜像网络通过同步复制和单个数据节点的自动故障转移实现高可用性。
  • 注意:仅在单个 GCP 区域内具有低延迟互连的多个地区之间,才建议进行故障转移同步数据库镜像。 区域之间的延迟通常太高,无法提供积极的用户体验,特别是对于具有高更新率的部署更如此。

    内部负载均衡器

    大多数 IaaS 云提供商缺乏提供虚拟 IP (VIP) 地址的能力,这种地址通常用在自动化数据库故障转移设计中。 为了解决这一问题,InterSystems IRIS 中增强了几种最常用的连接方法,尤其是 ECP 客户端和 Web 网关,从而不再依赖 VIP 功能使它们实现镜像感知和自动化。

    xDBC、直接 TCP/IP 套接字等连接方法,或其他的直接连接协议,均需要使用类 VIP 地址。 为了支持这些入站协议,InterSystems 数据库镜像技术使用称作<span class="Characteritalic" style="font-style:italic">mirror_status.cxw</span>的健康检查状态页面为 GCP 中的这些连接方法提供自动化故障转移,以与负载均衡器进行交互,实现负载均衡器的类 VIP 功能,仅将流量重定向至活动的主镜像成员,从而在 GCP 内实现完整且强大的高可用性设计。

    此处提供了使用负载均衡器实现类 VIP 功能的详细信息。

    示例 VPC 拓扑

    下图 4.3-a 中的 VPC 布局组合了所有组件,具有以下特点:

  • 利用一个区域内的多个地区实现高可用性
  • 提供两个区域进行灾难恢复
  • 利用多个子网进行网络隔离
  • 包括分别用于互联网和 VPN 连接的单独网关
  • 使用云负载均衡器进行镜像成员的 IP 故障转移

  • 持久性存储概述

    如简介中所述,建议使用 GCP 持久性磁盘,尤其 SSD 持久性磁盘类型。 之所以推荐 SSD 持久性磁盘,是由于其拥有更高的读写 IOPS 速率以及低的延迟,适合于事务性和分析性数据库工作负载。 在某些情况下,可使用本地 SSD,但值得注意的是,本地 SSD 的性能提升会在可用性、耐用性和灵活性方面做出一定的权衡。

    可在此处找到本地 SSD 数据持久性方面的详细信息,您可了解何时保存本地 SSD 数据以及何时不保存它们。

    LVM 条带化

    与其他的云提供商一样,GCP 在每个虚拟机实例的 IOPS、空间容量和设备数量方面都施加了众多存储限制。 有关当前的限制,请查阅 GCP 文档,可在此处找到。

    由于这些限制的存在,使用 LVM 条带化实现数据库实例的单个磁盘设备的 IOPS 最大化变得非常必要。 在提供的此示例虚拟机实例中,建议使用以下磁盘布局。 与 SSD 持久性磁盘相关的性能限制可在此处找到。

    注意:目前,每个虚拟机实例最多有 16 个持久性磁盘,但 GCP 近期的方案则增至 128 个(测试),这将是令人欣慰的提高。

    LVM 条带化的优势在于可以将随机的 IO 工作负载分散到更多的磁盘设备并继承磁盘队列。 以下是如何在 Linux 中将 LVM 条带化用于数据库卷组的示例。 本示例在一个 LVM PE 条带中使用 4 个磁盘,物理盘区 (PE) 大小为 4MB。 或者,如果需要,可以使用更大的 PE 容量。

    • 步骤 1:根据需要创建标准性磁盘或 SSD 持久性磁盘
    • 步骤 2:使用“lsblk -do NAME,SCHED”将每个磁盘设备的 IO 调度器设置为 NOOP
    • 步骤 3:使用“lsblk -do KNAME,TYPE,SIZE,MODEL”识别磁盘设备
    • 步骤4:使用新的磁盘设备创建磁盘卷组
      • vgcreate s 4M  
      • 示例vgcreate -s 4M vg_iris_db /dev/sd[h-k]
    • 步骤 4:创建逻辑卷
      • lvcreate n -L -i -I 4MB
      • 示例lvcreate -n lv_irisdb01 -L 1000G -i 4 -I 4M vg_iris_db
    • 步骤 5:创建文件系统
      • mkfs.xfs K
      • 示例mkfs.xfs -K /dev/vg_iris_db/lv_irisdb01
    • 步骤 6:装载文件系统
      • 使用以下装载条目编辑 /etc/fstab
        • /dev/mapper/vg_iris_db-lv_irisdb01    /vol-iris/db    xfs  defaults 0 0
        • 装载 /vol-iris/db

    使用上表,每个 InterSystems IRIS 服务器将具有以下配置:2 个 SYS 磁盘、4 个 DB 磁盘、2 个主日志磁盘、2 个备用日志磁盘。

    为了增长,LVM 允许在需要的情况下不中断地扩展设备和逻辑卷。 有关持续管理和扩展 LVM 卷的最佳做法,请查阅 Linux 文档。

    注意 0>:强烈建议同时为数据库和写入映像日志文件启用异步 IO。 有关在 Linux 上启用的详细信息,请参阅下列社区文章:https://community.intersystems.com/post/lvm-pe-striping-maximize-hyper-converged-storage-throughput

    配置

    InterSystems IRIS 新增了 InterSystems Cloud Manager (ICM)。 ICM 执行众多任务,并提供许多用于配置 InterSystems IRIS 数据平台的选项。 ICM 作为 Docker 映像提供,其拥有配置强大的、基于 GCP 云的解决方案所需的一切。

    ICM 当前支持以下平台上的配置:

    • Google Cloud Platform (GCP)
    • Amazon Web Services,包括 GovCloud (AWS / GovCloud)
    • Microsoft Azure Resource Manager,包括 Government (ARM / MAG)
    • VMware vSphere (ESXi)

    ICM 和 Docker 可以从台式机/笔记本电脑工作站运行,也可以具有中央专用的适度“配置”服务器和中央存储库。  

    ICM 在应用程序生命周期中的作用是“定义->配置->部署->管理”

    有关安装和使用 ICM 及 Docker 的详细信息,可在此处找到。

    注意:任何云部署都非必须使用 ICM。 完全支持传统的 tar-ball 分布式安装和部署方法。 但是,建议使用 ICM,以简化云部署中的配置和管理。

    容器监视

    ICM 包含基本的监视工具,其使用 Weave Scope 进行基于容器的部署。 默认情况下不会部署该工具,需要在默认的文件中使用监视器字段指定它。

    有关使用 ICM 进行监视、编排和调度的详细信息,可在此处找到。

    有关 Weave Scope 的概述和该文档,可在此处找到。


    高可用性

    InterSystems 数据库镜像可在任何云环境中提供最高级别的可用性。  有一些选项可以直接在实例级别提供虚拟机弹性。 有关 GCP 中可用的各种政策的详细信息,可在此处找到。

    上文中已讨论了云负载均衡器如何通过数据库镜像为虚拟 IP(类 VIP)功能提供自动化 IP 地址故障转移。  云负载均衡器使用<span class="Characteritalic" style="font-style:italic">mirror_status.cxw</span>健康检查状态页面,上文内部负载均衡器部分提到过该页面。  数据库镜像有两种模式——自动故障转移同步镜像、异步镜像。 在本示例中,将介绍同步故障转移镜像。 有关镜像的详细信息,可在此处找到。

    最基本的镜像配置是仲裁器控制配置中的一对故障转移镜像成员。 仲裁器放置在同一区域内的第三个地区中,以防止潜在的地区中断影响仲裁器和其中一个镜像成员。

    在网络配置中,有多种方法专供设置镜像。 在本示例中,我们将使用本文档前述网络网关和子网定义部分中定义的网络子网。 下一部分内容将提供 IP 地址方案示例,并且基于本部分内容,将仅描述网络接口和指定的子网。


    灾难恢复

    InterSystems 数据库镜像将支持灾难恢复的高可用性功能扩展到另一个 GCP 地理区域,以在整个 GCP 区域万一脱机的情况下支持操作弹性。 应用程序如何耐受此类中断取决于恢复时间目标 (RTO) 和恢复点目标 (RPO)。 这些将为设计适当的灾难恢复计划进行的分析提供初始框架。 以下链接中的指南提供了您在为自己的应用程序制定灾难恢复计划时要考虑的事项。 https://cloud.google.com/solutions/designing-a-disaster-recovery-planhttps://cloud.google.com/solutions/disaster-recovery-cookbook

    异步数据库镜像

    InterSystems IRIS 数据平台的数据库镜像提供强大的功能,可在 GCP 地区和区域之间异步复制数据,以帮助支持您的灾难恢复计划的 RTO 和 RPO 目标。 有关异步镜像成员的详细信息,可在此处找到。

    与上述高可用性部分中讲述的内容相似,云负载均衡器也使用上文内部负载均衡器部分中提到过的<span class="Characteritalic" style="font-style:italic">mirror_status.cxw</span>健康检查状态页面为虚拟 IP(类 VIP)功能提供自动化 IP 地址故障转移,以进行 DR 异步镜像。

    在本示例中,将介绍 DR 异步故障转移镜像,并介绍 GCP 全局负载均衡服务,以便为上游系统和客户端工作站提供单个任播 IP 地址,不分您的 InterSystems IRIS 部署是否在哪个区域或地区中运行。

    GCP 的其中一个发展就是负载均衡器的诞生,这是一种软件定义的全局资源,并且不受制于特定的区域。 由于其不是基于实例或设备的解决方案,因此它具有跨区域利用单个服务的独特功能。 有关通过单个任播 IP 进行 GCP 全局负载均衡的详细信息,可在此处找到。

    在上述示例中,所有 3 个 InterSystems IRIS 实例的 IP 地址都提供给了 GCP 全局负载均衡器,它会将流量仅定向到承担主要镜像的镜像成员,而不论其位于哪个地区或区域。


    分片集群

    InterSystems IRIS 拥有一系列全面的功能来缩放您的应用程序,您可以根据自己工作负载的性质以及所面临的特定性能挑战来单独或组合应用这些功能。 分片功能是这些功能中的一种,可跨多个服务器对数据及其关联的缓存进行分区,从而为查询和数据引入提供灵活、高性价比的性能扩展,同时通过高效的资源利用最大化基础架构的价值。 InterSystems IRIS 分片群集可以为各种应用提供显著的性能优势,尤其对于工作负载包括以下一项或多项的应用更是如此:

    • 大容量或高速数据引入,或两者的组合。
    • 相对较大的数据集、返回大量数据的查询,或两者。
    • 执行大量数据处理的复杂查询,例如扫描磁盘上大量数据或涉及大量计算工作的查询。

    这些因素分别都会影响分片的潜在优势,但组合起来使用它们可能会增加优势。 例如,这 3 个因素的组合——快速引入大量数据、大型数据集、检索和处理大量数据的复杂查询——使得当今的许多分析性工作负载非常适合进行分片。

    注意,这些特征都与数据有关;InterSystems IRIS 分片的主要功能是缩放数据量。 不过,当涉及某些或所有这些与数据相关的因素的工作负载也经历大量用户的超高查询量时,分片群集也能提供用户量缩放功能。 分片也可以与纵向缩放相结合。

    操作概述

    分片架构的核心是跨多个系统对数据及其关联的缓存进行分区。 分片集群跨多个 InterSystems IRIS 实例以行方式(称为数据节点)对大型数据库表进行物理上的横向分区,同时允许应用通过任何节点透明地访问这些表,但仍将整个数据集看作一个逻辑并集。 该架构具有 3 个优点:

    • 并行处理查询在数据节点上并行运行,然后将结果进行合并和组合后,由节点作为完整查询结果返回给连接的应用。许多情况下,这大大提高了执行速度。
    • 分区缓存:每个数据节点都有自己的缓存,专用于它存储的分片表数据分区,再不是单个实例的缓存服务于整个数据集,这大大降低了缓存溢出的风险,并强制执行性能降低式磁盘读取。
    • 并行加载:数据可以并行加载到数据节点,从而减少了引入工作负载和查询工作负载之间的缓存和磁盘争用,提高了两者的性能。

    有关 InterSystems IRIS 分片集群的详细信息,可在此处找到。

    分片元素和实例类型

    分片集群包含至少一个数据节点,如果特定性能或工作负载有需要,则可添加一定数量的计算节点。 这两种节点类型提供简单的构建块,从而实现简单、透明和高效的调整模型。

    数据节点

    数据节点存储数据。 在物质层面,分片表[1]数据分布在集群中的所有数据节点上,非分片表数据仅物理存储在第一个数据节点上。 这种区分对用户是透明的,唯一可能的例外是,第一个节点的存储消耗可能比其他节点略高,但是由于分片表数据通常会超出非分片表数据至少一个数量级,因此这种差异可以忽略不计。

    需要时,可以跨集群重新均衡分片表数据,这通常发生在添加新的数据节点后。 这将在节点之间移动数据的“存储桶”,以实现数据的近似均匀分布。

    在逻辑层面,未分片的表数据和所有分片的表数据的并集在任何节点上都可见,因此客户端会看到整个数据集,这与其连接哪个节点无关。 元数据和代码也会在所有数据节点之间共享。

    分片集群的基本架构图仅由在集群中看起来统一的数据节点组成。 客户端应用程序可以连接到任何节点,并且可以像在本地一样体验数据。


    [1]为方便起见,术语“分片表数据”在整个文档中用于表示支持分片的任何数据模型的“盘区”数据(标记为已分片)。 术语“未分片表数据”和“未分片数据”用于表示处于可分片盘区但却未这样标记的数据,或表示尚不支持分片的数据模型。

    数据节点

    对于要求低延迟(可能存在不断涌入数据的冲突)的高级方案,可以添加计算节点以提供用于服务查询的透明缓存层。

    计算节点缓存数据。 每个计算节点都与一个数据节点关联,为其缓存相应的分片表数据,此外,它还根据需要缓存非分片表数据,以满足查询的需要。

    由于计算节点物理上并不存储任何数据,其只是支持查询执行,因此可对其硬件配置文件进行调整以满足需求,例如通过强调内存和 CPU 并将存储空间保持在最低限度。 当“裸露”应用程序代码在计算节点上运行时,引入数据会被驱动程序 (xDBC, Spark) 直接或被分片管理器代码间接转发到数据节点。


    分片集群说明

    分片集群部署有多种组合。 下列各图说明了最常见的部署模型。 These diagrams do not include the networking gateways and details and provide to focus only on the sharded cluster components.

    基本分片集群

    下图是在一个区域和一个地区中部署了 4 个数据节点的最简单分片群集。 GCP 云负载均衡器用于将客户端连接分发到任何分片集群节点。

    在此基本模型中,除了 GCP 为单个虚拟机及其连接的 SSD 持久性存储提供的弹性或高可用性外,没有其他弹性或高可用性。 建议使用两个单独的网络接口适配器,一则为入站客户端连接提供网络安全隔离,二则为客户端流量和分片集群通信之间提供带宽隔离。

    具有高可用性的基本分片集群

    下图是在一个区域中部署了 4 个镜像数据节点的最简单分片集群,每个节点的镜像在地区之间进行了划分。 GCP 云负载均衡器用于将客户端连接分发到任何分片集群节点。

    InterSystems 数据库镜像的使用带来了高可用性,其会在该区域内的第二地区中维护一个同步复制的镜像。

    建议使用 3 个单独的网络接口适配器,一方面为入站客户端连接提供网络安全隔离,另一方面为客户端流量、分片集群通信、节点对之间的同步镜像流量之间提供带宽隔离。

    此部署模型也引入了本文前面所述的镜像仲裁器。

    具有单独计算节点的分片集群

    下图采用单独的计算节点和 4 个数据节点扩展了分片集群,以此来应对大量的用户/查询并发。 云负载均衡器服务器池仅包含计算节点的地址。 更新和数据引入将像以前一样继续直接更新到数据节点,以维持超低延迟性能,并避免由于实时数据引入而在查询/分析工作负载之间造成资源的干扰和拥挤。

    使用此模型,可以根据计算/查询和数据引入的规模单独微调资源分配,从而在“适时”需要的地方提供最佳资源,实现经济而简单的解决方案,而非只是进行计算或数据的调整,浪费不必要的资源。

    计算节点非常适合直接使用 GCP 自动缩放分组(亦称自动缩放),允许基于负载的增加或减少自动从托管实例组添加或删除实例。 自动缩放的工作原理为:负载增加时,将更多的实例添加到实例组(扩展);对实例的需求降低时将其删除(缩减)。

    有关 GCP 自动缩放的详细信息,可在此处找到。

    自动缩放可帮助基于云的应用程序轻松应对流量增加的情况,并在资源需求降低时降低成本。 只需简单地定义自动缩放策略,自动缩放器就会根据测得的负载执行自动缩放。


    备份操作

    备份操作有多个选项。 以下 3 个选项可供您通过 InterSystems IRIS 进行 GCP 部署。

    下面的前 2 个选项(下文详细说明)采用快照类型的过程,该过程会在创建快照之前将数据库写入操作挂起到磁盘上,然后在快照成功后恢复更新。

    可采取以下高级别步骤通过任一快照方法来创建洁净的备份:

    • 通过数据库外部冻结 API 调用暂停对数据库的写入。
    • 创建操作系统和数据磁盘的快照。
    • 通过外部解冻 API 调用恢复数据库写入。
    • 将设施存档备份到备份位置

    有关外部冻结/解冻 API 的详细信息,可在此处找到。

    注意:本文档未包含备份示例脚本,但您可定期检查发布到 InterSystems 网站上开发者社区的示例。 请访问 www.community.intersystems.com

    第三个选项是 InterSystems 在线备份。 这是小型部署的入门级方法,具有非常简单的用例和界面。 但是,随着数据库的增大,建议将使用快照技术的外部备份作为最佳做法,因为其具有以下优势:备份外部文件、更快的恢复时间,以及企业范围的数据和管理工具。

    可以定期添加诸如完整性检查之类的其他步骤,以确保洁净且一致的备份。

    决定使用哪种选项取决于您组织的运营要求和策略。 InterSystems 可与您详细讨论各种选项。

    GCP 持久性磁盘快照备份

    可以使用 GCP gcloud 命令行 API 以及 InterSystems 外部冻结/解冻 API 功能实现备份操作。 这允许实现真正的 24x7 全天候操作弹性,并确保洁净常规备份。 有关管理、创建和自动化 GCP 持久性磁盘快照的详细信息,可在此处找到。

    逻辑卷管理器 (LVM) 快照

    或者,可以在 VM 本身中部署单个备份代理,利用文件级备份,并结合逻辑卷管理器 (LVM) 快照,来使用市面上的许多第三方备份工具。

    该模型的主要优点之一是能够对基于 Windows 或 Linux 的 VM 进行文件级恢复。 此解决方案需要注意的几点是,由于 GCP 和大多数其他 IaaS 云提供商都不提供磁带媒体,因此所有的备份存储库对于短期归档均基于磁盘,并能够利用 Blob 或存储桶类型的低成本存储来进行长期保留 (LTR)。 强烈建议您使用此方法来使用支持重复数据删除技术的备份产品,以最有效地利用基于磁盘的备份存储库。

    这些具有云支持的备份产品的示例包括但不限于:Commvault、EMC Networker、HPE Data Protector 和 Veritas Netbackup。

    注意:InterSystems 不会验证或认可一种备份产品是否优于其他产品。 选择备份管理软件的责任由客户个人决定。

    在线备份

    对于小型部署,内置在线备份工具也是可行的选择。 该 InterSystems 数据库在线备份实用工具通过捕获数据库中的所有块来备份数据库文件中的数据,然后将输出写入顺序文件。 这种专有的备份机制旨在使生产系统的用户不停机。 有关在线备份的详细信息,可在此处找到。

    在 GCP 中,在线备份完成后,必须将备份输出文件和系统正在使用的所有其他文件复制到该虚拟机实例之外的其他存储位置。 存储桶/对象存储是对其很好的命名。

    使用 GCP 存储桶有两种选择。

    • 直接使用 gcloud 脚本 API 来复制和操作新创建的在线备份(和其他非数据库)文件。 有关详细信息可在此处找到。
    • 尽管云存储桶属于对象存储,但将存储桶装载为文件系统,并将其用作类似持久性磁盘的功能足以。

    有关装载云存储桶(使用云存储 FUSE )的详细信息,可在此处找到。

    0
    0 1097
    文章 Jeff Liu · 一月 7, 2021 20m read

    假设你想了解 InterSystems 在数据分析方面能提供什么。 你研究了理论,现在想要进行一些实践。 幸运的是,InterSystems 提供了一个项目:Samples BI,其中包含了一些很好的示例。 从 README 文件开始,跳过任何与 Docker 相关的内容,直接进行分步安装。 启动虚拟实例 安装 IRIS,按照说明安装 Samples BI,然后用漂亮的图表和表格让老板眼前一亮。 到目前为止还不错。

    但是不可避免地,你需要进行更改。

    事实证明,自己保留虚拟机存在一些缺点,交给云服务商保管是更好的选择。 Amazon 看起来很可靠,你只需创建一个 AWS 帐户(入门免费),了解到使用 root 用户身份执行日常任务是有害的,然后创建一个常规的具有管理员权限的 IAM 用户

    点击几下鼠标,就可以创建自己的 VPC 网络、子网和虚拟 EC2 实例,还可以添加安全组来为自己开放 IRIS Web端口 (52773) 和 ssh 端口 (22)。 重复 IRIS 和 Samples BI 的安装。 这次使用 Bash 脚本,如果你喜欢,也可以使用 Python。 再一次让老板刮目相看。

    但是无处不在的 DevOps 运动让你开始了解基础架构即代码,并且你想要实现它。 你选择了 Terraform,因为它是众所周知的,而且它的方法非常通用,只需微小调整即可适合各种云提供商。 使用 HCL 语言描述基础架构,并将 IRIS 和 Samples BI 的安装步骤转换到 Ansible。 然后再创建一个 IAM 用户使 Terraform 正常工作。 全部运行一遍。 获得工作奖励。

    渐渐地你会得出结论,在我们这个微服务时代,不使用 Docker 就太可惜了,尤其是 InterSystems 还会告诉你怎么做。 返回到 Samples BI 安装指南并阅读关于 Docker 的几行内容,似乎并不复杂:

    $ docker pull intersystemsdc/iris-community:2019.4.0.383.0-zpm
    $ docker run --name irisce -d --publish 52773:52773 intersystemsdc/iris-community:2019.4.0.383.0-zpm
    $ docker exec -it irisce iris session iris
    USER>zpm
    zpm: USER>install samples-bi

    将浏览器定向到 http://localhost:52773/csp/user/_DeepSee.UserPortal.Home.zen?$NAMESPACE=USER 后,再次去老板那里,因为做得好而获得一天假期。

    然后你开始明白,“docker run”只是开始,至少需要使用 docker-compose。 没问题:

    $ cat docker-compose.yml
    version: "3.7"
    services:
    irisce:
    container_name: irisce
    image: intersystemsdc/iris-community:2019.4.0.383.0-zpm
    ports:
    - 52773:52773
    $ docker rm -f irisce # We don’t need the previous container
    $ docker-compose up -d

    这样你使用 Ansible 安装了 Docker 和 docker-compose,然后运行了容器,如果机器上还没有映像,则会下载一个映像。 最后安装了 Samples BI。

    你一定喜欢 Docker,因为它是各种内核素材的又酷又简单的接口。 你开始在其他地方使用 Docker,并且经常启动多个容器。 还发现容器必须经常互相通信,这就需要了解如何管理多个容器。

    终于,你发现了 Kubernetes

    从 docker-compose 快速切换到 Kubernetes 的一个方法是使用 kompose。 我个人更喜欢简单地从手册中复制 Kubernetes 清单,然后自己编辑,但是 kompose 在完成小任务方面做得很好:

    $ kompose convert -f docker-compose.yml
    INFO Kubernetes file "irisce-service.yaml" created
    INFO Kubernetes file "irisce-deployment.yaml" created

    现在你有了可以发送到某个 Kubernetes 集群的部署和服务文件。 你发现可以安装 minikube,它允许你运行一个单节点 Kubernetes 集群,这正是你现阶段所需要的。 在摆弄一两天 minikube 沙盒之后,你已经准备好在 AWS 云中的某处使用真实的 Kubernetes 部署

    设置

    我们一起来进行吧。 此时,我们做以下几个假设:

    首先,我们假设你有一个 AWS 帐户,你知道其 ID,并且未使用 root 凭据。 你创建了一个具有管理员权限且只能以编程方式访问的 IAM 用户(我们称之为“my-user”),并存储了其凭据。 你还创建了另一个具有相同权限的 IAM 用户,名为“terraform”:

    Terraform 将以它的名义进入你的 AWS 帐户,并创建和删除必要资源。 这两个用户的广泛权限将通过演示来说明。 你在本地保存了这两个 IAM 用户的凭据:

    $ cat ~/.aws/credentials
    [terraform]
    aws_access_key_id = ABCDEFGHIJKLMNOPQRST
    aws_secret_access_key = ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890123
    [my-user]
    aws_access_key_id = TSRQPONMLKJIHGFEDCBA
    aws_secret_access_key = TSRQPONMLKJIHGFEDCBA01234567890123

    注意:不要复制和粘贴上面的凭据。 它们在这里作为示例提供,不再存在。 请编辑 ~/.aws/credentials 文件并引入你自己的记录。

    其次,我们将在文中使用虚拟的 AWS 帐户 ID (01234567890) 和 AWS 区域“eu-west-1”。 可以随意使用其他区域

    第三,我们假设你知道 AWS 不是免费的,你需要为使用的资源付费。

    接下来,您已经安装了 AWS CLI 实用程序,以便与 AWS 进行命令行通信。 你可以尝试使用 aws2,但你需要在 kube 配置文件中特别设置 aws2 的用法,如这里所述。

    你还安装了 kubectl 实用程序来与 AWS Kubernetes 进行命令行通信。

    并且你也针对 docker-compose.yml 安装了 kompose 实用程序,来转换 Kubernetes 清单。

    最后,你创建了一个空的 GitHub 仓库,并将其克隆到主机上。 我们将其根目录引用为 。 在此仓库中,我们将创建并填充三个目录:.github/workflows/、k8s/ 和 terraform/。

    请注意,所有相关代码都在 github-eks-samples-bi 仓库中复制,以简化拷贝和粘贴。

    我们继续。

    AWS EKS 预置

    我们已经在文章使用 Amazon EKS 部署简单的基于 IRIS 的 Web 应用程序中知道了 EKS。 那时,我们以半自动方式创建了一个集群。 即,我们在一个文件中描述集群,然后从本地机器手动启动 eksctl 实用程序,该实用程序根据我们的描述创建集群。

    eksctl 是为创建 EKS 集群而开发的,它非常适合概念验证实现,但对于日常使用来说,最好使用更通用的工具,例如 Terraform。 AWS EKS 简介是一个非常好的资源,其中介绍了创建 EKS 集群所需的 Terraform 配置。 花一两个小时熟悉一下,决不会是浪费时间。

    你可以在本地操作 Terraform。 为此,你需要一个二进制文件(在撰写本文时,我们使用最新的 Linux 版本 0.12.20),并且 IAM 用户“terraform”需要有足够的权限才能让 Terraform 进入 AWS。 创建目录 /terraform/ 以存储 Terraform 代码:

    $ mkdir /terraform
    $ cd /terraform

    你可以创建一个或多个 .tf 文件(它们会在启动时合并)。 只需复制并粘贴 AWS EKS 简介中的代码示例,然后运行如下命令:

    $ export AWS_PROFILE=terraform
    $ export AWS_REGION=eu-west-1
    $ terraform init
    $ terraform plan -out eks.plan

    你可能会遇到一些错误。 如果遇到的话,可以在调试模式下操作,但记得稍后关闭该模式:

    $ export TF_LOG=debug
    $ terraform plan -out eks.plan

    $ unset TF_LOG

    这个经验会很有用,你很可能会启动一个 EKS 集群(使用“terraform apply”进行该操作)。 在 AWS 控制台中查看:

    觉得厌烦时就清理掉:

    $ terraform destroy

    然后进入下一阶段,开始使用 Terraform EKS 模块,尤其它也基于同一 EKS 简介。 在 examples/ 目录中,你将看到如何使用它。 你还会在那里找到其他示例

    我们对示例进行了一定的简化。 以下是主文件,其中调用了 VPC 创建和 EKS 创建模块:

    $ cat /terraform/main.tf
    terraform {
      required_version = ">= 0.12.0"
      backend "s3" {
        bucket         = "eks-github-actions-terraform"
        key            = "terraform-dev.tfstate"
        region         = "eu-west-1"
        dynamodb_table = "eks-github-actions-terraform-lock"
      }
    }

    provider "kubernetes" {
      host                   = data.aws_eks_cluster.cluster.endpoint
      cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
      token                  = data.aws_eks_cluster_auth.cluster.token
      load_config_file       = false
      version                = "1.10.0"
    }

    locals {
      vpc_name             = "dev-vpc"
      vpc_cidr             = "10.42.0.0/16"
      private_subnets      = ["10.42.1.0/24", "10.42.2.0/24"]
      public_subnets       = ["10.42.11.0/24", "10.42.12.0/24"]
      cluster_name         = "dev-cluster"
      cluster_version      = "1.14"
      worker_group_name    = "worker-group-1"
      instance_type        = "t2.medium"
      asg_desired_capacity = 1
    }

    data "aws_eks_cluster" "cluster" {
      name = module.eks.cluster_id
    }

    data "aws_eks_cluster_auth" "cluster" {
      name = module.eks.cluster_id
    }

    data "aws_availability_zones" "available" {
    }

    module "vpc" {
      source               = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc?ref=master"

      name                 = local.vpc_name
      cidr                 = local.vpc_cidr
      azs                  = data.aws_availability_zones.available.names
      private_subnets      = local.private_subnets
      public_subnets       = local.public_subnets
      enable_nat_gateway   = true
      single_nat_gateway   = true
      enable_dns_hostnames = true

      tags = {
        "kubernetes.io/cluster/${local.cluster_name}" = "shared"
      }

      public_subnet_tags = {
        "kubernetes.io/cluster/${local.cluster_name}" = "shared"
        "kubernetes.io/role/elb" = "1"
      }

      private_subnet_tags = {
        "kubernetes.io/cluster/${local.cluster_name}" = "shared"
        "kubernetes.io/role/internal-elb" = "1"
      }
    }

    module "eks" {
      source = "git::https://github.com/terraform-aws-modules/terraform-aws-eks?ref=master"
      cluster_name     = local.cluster_name
      cluster_version  = local.cluster_version
      vpc_id           = module.vpc.vpc_id
      subnets          = module.vpc.private_subnets
      write_kubeconfig = false

      worker_groups = [
        {
          name                 = local.worker_group_name
          instance_type        = local.instance_type
          asg_desired_capacity = local.asg_desired_capacity
        }
      ]

      map_accounts = var.map_accounts
      map_roles    = var.map_roles
      map_users    = var.map_users
    }

    我们再仔细看一下 main.tf 中的“terraform”块:

    terraform {
      required_version = ">= 0.12.0"
      backend "s3" {
        bucket         = "eks-github-actions-terraform"
        key            = "terraform-dev.tfstate"
        region         = "eu-west-1"
        dynamodb_table = "eks-github-actions-terraform-lock"
      }
    }

    这里需要指出,我们将遵守不低于 Terraform 0.12 的语法(与早期版本相比有了很大变化),同时,Terraform 不应该将其状态存储在本地,而是远程存储在 S3 存储桶中。

    不同的人可以从不同的地方更新 terraform 代码确实很方便,这意味着我们需要能够锁定用户的状态,因此我们使用 dynamodb 表添加了一个锁。 有关锁定的更多信息,请参见状态锁定页面。

    由于存储桶的名称在整个 AWS 中应该是唯一的,因此你不能再使用名称“eks-github-actions-terraform”。 请想一个你自己的名称,并确保它没有被占用(应该收到 NoSuchBucket 错误):

    $ aws s3 ls s3://my-bucket
    调用 ListObjectsV2 操作时发生错误 (AllAccessDisabled):对此对象的所有访问均已禁用
    $ aws s3 ls s3://my-bucket-with-name-that-impossible-to-remember
    调用 ListObjectsV2 操作时发生错误 (NoSuchBucket):指定的存储桶不存在

    想好一个名称,创建存储桶(我们这里使用 IAM 用户“terraform”。 它拥有管理员权限,因此可以创建存储桶),并为其启用版本管理(这在配置出错时能让你省心):

    $ aws s3 mb s3://eks-github-actions-terraform --region eu-west-1
    make_bucket: eks-github-actions-terraform
    $ aws s3api put-bucket-versioning --bucket eks-github-actions-terraform --versioning-configuration Status=Enabled
    $ aws s3api get-bucket-versioning --bucket eks-github-actions-terraform
    {
      "Status": "Enabled"
    }

    对于 DynamoDB,不需要唯一性,但你需要先创建一个表:

    $ aws dynamodb create-table                                                                                     \
      --region eu-west-1                                                                                                           \
      --table-name eks-github-actions-terraform-lock                                              \
      --attribute-definitions AttributeName=LockID,AttributeType=S                \
      --key-schema AttributeName=LockID,KeyType=HASH                                   \
      --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5

    注意,如果 Terraform 操作失败,你可能需要从 AWS 控制台手动删除锁。 但这样做时要小心。

    对于 main.tf 中的 eks/vpc 模块,引用 GitHub 上提供的模块很简单:

    git::https://github.com/terraform-aws-modules/terraform-aws-vpc?ref=master

    现在看一下另外两个 Terraform 文件(variables.tf 和 outputs.tf)。 第一个文件保存了 Terraform 变量:

    $ cat /terraform/variables.tf
    variable "region" {
      default = "eu-west-1"
    }

    variable "map_accounts" {
      description = "Additional AWS account numbers to add to the aws-auth configmap. See examples/basic/variables.tf for example format."
      type        = list(string)
      default     = []
    }

    variable "map_roles" {
      description = "Additional IAM roles to add to the aws-auth configmap."
      type = list(object({
        rolearn  = string
        username = string
        groups   = list(string)
      }))
      default = []
    }

    variable "map_users" {
      description = "Additional IAM users to add to the aws-auth configmap."
      type = list(object({
        userarn  = string
        username = string
        groups   = list(string)
      }))
      default = [
        {
          userarn  = "arn:aws:iam::01234567890:user/my-user"
          username = "my-user"
          groups   = ["system:masters"]
        }
      ]
    }

    这里最重要的部分是将 IAM 用户“my-user”添加到 map_users 变量中,但你应该使用自己的帐户 ID 替换 01234567890。

    这有什么用? 当通过本地 kubectl 客户端与 EKS 通信时,它会向 Kubernetes API 服务器发送请求,每个请求都要经过身份验证和授权过程,这样 Kubernetes 就可以知道谁发送了请求,以及它们可以做什么。 因此 Kubernetes 的 EKS 版本会要求 AWS IAM 帮助进行用户身份验证。 如果发送请求的用户列在 AWS IAM 中(这里我们指向其 ARN),请求将进入授权阶段,该阶段将由 EKS 自己处理,但要依据我们的设置。 这里要指出的是,IAM 用户“my-user”非常酷(组“system: masters”)。

    最后,output.tf 文件描述了 Terraform 在完成工作后应该打印的内容:

    $ cat /terraform/outputs.tf
    output "cluster_endpoint" {
      description = "Endpoint for EKS control plane."
      value       = module.eks.cluster_endpoint
    }

    output "cluster_security_group_id" {
      description = "Security group ids attached to the cluster control plane."
      value       = module.eks.cluster_security_group_id
    }

    output "config_map_aws_auth" {
      description = "A kubernetes configuration to authenticate to this EKS cluster."
      value       = module.eks.config_map_aws_auth
    }

    Terraform 部分的描述完成。 我们很快就会回来,看看如何启动这些文件。

    Kubernetes 清单

    到目前为止,我们已经解决了在哪里启动应用程序的问题。 现在我们来看看要运行什么

    回想一下 /k8s/ 目录中的 docker-compose.yml(我们重命名了服务,添加了几个不久就会被 kompose 用到的标签)

    $ cat /k8s/docker-compose.yml
    version: "3.7"
    services:
      samples-bi:
        container_name: samples-bi
        image: intersystemsdc/iris-community:2019.4.0.383.0-zpm
        ports:
        - 52773:52773
        labels:
          kompose.service.type: loadbalancer
          kompose.image-pull-policy: IfNotPresent

    运行 kompose,然后添加下面突出显示的内容。 删除注释(使内容更容易理解):

    $ kompose convert -f docker-compose.yml --replicas=1
    $ cat /k8s/samples-bi-deployment.yaml
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      labels:
        io.kompose.service: samples-bi
      name: samples-bi
    spec:
      replicas: 1
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            io.kompose.service: samples-bi
        spec:
          containers:
          - image: intersystemsdc/iris-community:2019.4.0.383.0-zpm
            imagePullPolicy: IfNotPresent
            name: samples-bi
            ports:
            - containerPort: 52773
            resources: {}
            lifecycle:
              postStart:
                exec:
                  command:
                  - /bin/bash
                  - -c
                  - |
                    echo -e "write\nhalt" > test
                    until iris session iris < test; do sleep 1; done
                    echo -e "zpm\ninstall samples-bi\nquit\nhalt" > samples_bi_install
                    iris session iris < samples_bi_install
                    rm test samples_bi_install

            restartPolicy: Always

    我们使用 Recreate 更新策略,这意味着先删除 pod,然后重新创建。 这对于演示目的是允许的,让我们可以使用更少的资源。
    我们还添加了 postStart 挂钩,该挂钩在 pod 启动后立即触发。 我们等待至 IRIS 启动,然后从默认的 zpm-repository 安装 samples-bi 包。
    现在我们添加 Kubernetes 服务(同样没有注释):

    $ cat /k8s/samples-bi-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        io.kompose.service: samples-bi
      name: samples-bi
    spec:
      ports:
      - name: "52773"
        port: 52773
        targetPort: 52773
      selector:
        io.kompose.service: samples-bi
      type: LoadBalancer

    是的,我们将在“默认”命名空间中部署,该命名空间适合演示。

    好了,现在我们知道了运行_位置_和_内容_。 还剩下_方式_需要了解。

    GitHub Actions 工作流程

    我们不需要每件事都从头开始做,而是创建一个工作流程,类似于使用 GitHub Actions 在 GKE 上部署 InterSystems IRIS 解决方案中所述的工作流程。 这次,我们不必担心构建容器。 GKE 特定的部分已替换为特定于 EKS。 粗体部分与接收提交消息和在条件步骤中使用它有关:

    $ cat /.github/workflows/workflow.yaml
    name: Provision EKS cluster and deploy Samples BI there
    on:
      push:
        branches:
        - master

    # Environment variables.
    # ${{ secrets }} are taken from GitHub -> Settings -> Secrets
    # ${{ github.sha }} is the commit hash
    env:
      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
      AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      AWS_REGION: ${{ secrets.AWS_REGION }}
      CLUSTER_NAME: dev-cluster
      DEPLOYMENT_NAME: samples-bi

    jobs:
      eks-provisioner:
        # Inspired by:
        ## https://www.terraform.io/docs/github-actions/getting-started.html
        ## https://github.com/hashicorp/terraform-github-actions
        name: Provision EKS cluster
        runs-on: ubuntu-18.04
        steps:
        - name: Checkout
          uses: actions/checkout@v2

        - name: Get commit message
          run: |
            echo ::set-env name=commit_msg::$(git log --format=%B -n 1 ${{ github.event.after }})

        - name: Show commit message
          run: echo $commit_msg

        - name: Terraform init
          uses: hashicorp/terraform-github-actions@master
          with:
            tf_actions_version: 0.12.20
            tf_actions_subcommand: 'init'
            tf_actions_working_dir: 'terraform'

        - name: Terraform validate
          uses: hashicorp/terraform-github-actions@master
          with:
            tf_actions_version: 0.12.20
            tf_actions_subcommand: 'validate'
            tf_actions_working_dir: 'terraform'

        - name: Terraform plan
          if: "!contains(env.commit_msg, '[destroy eks]')"
          uses: hashicorp/terraform-github-actions@master
          with:
            tf_actions_version: 0.12.20
            tf_actions_subcommand: 'plan'
            tf_actions_working_dir: 'terraform'

        - name: Terraform plan for destroy
          if: "contains(env.commit_msg, '[destroy eks]')"
          uses: hashicorp/terraform-github-actions@master
          with:
            tf_actions_version: 0.12.20
            tf_actions_subcommand: 'plan'
            args: '-destroy -out=./destroy-plan'
            tf_actions_working_dir: 'terraform'

        - name: Terraform apply
          if: "!contains(env.commit_msg, '[destroy eks]')"
          uses: hashicorp/terraform-github-actions@master
          with:
            tf_actions_version: 0.12.20
            tf_actions_subcommand: 'apply'
            tf_actions_working_dir: 'terraform'

        - name: Terraform apply for destroy
          if: "contains(env.commit_msg, '[destroy eks]')"
          uses: hashicorp/terraform-github-actions@master
          with:
            tf_actions_version: 0.12.20
            tf_actions_subcommand: 'apply'
            args: './destroy-plan'
            tf_actions_working_dir: 'terraform'

      kubernetes-deploy:
        name: Deploy Kubernetes manifests to EKS
        needs:
        - eks-provisioner
        runs-on: ubuntu-18.04
        steps:
        - name: Checkout
          uses: actions/checkout@v2

        - name: Get commit message
          run: |
            echo ::set-env name=commit_msg::$(git log --format=%B -n 1 ${{ github.event.after }})

        - name: Show commit message
          run: echo $commit_msg

        - name: Configure AWS Credentials
          if: "!contains(env.commit_msg, '[destroy eks]')"
          uses: aws-actions/configure-aws-credentials@v1
          with:
            aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
            aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
            aws-region: ${{ secrets.AWS_REGION }}

        - name: Apply Kubernetes manifests
          if: "!contains(env.commit_msg, '[destroy eks]')"
          working-directory: ./k8s/
          run: |
            aws eks update-kubeconfig --name ${CLUSTER_NAME}
            kubectl apply -f samples-bi-service.yaml
            kubectl apply -f samples-bi-deployment.yaml
            kubectl rollout status deployment/${DEPLOYMENT_NAME}

    当然,我们需要设置“terraform”用户的凭据(从 ~/.aws/credentials 文件中获取),让 Github 使用它的机密:

    注意工作流程的突出显示部分。 我们可以通过推送包含短语“[destroy eks]”的提交消息来销毁 EKS 集群。 请注意,我们不会使用这样的提交消息来运行“kubernetes apply”。
    运行管道,但首先要创建一个 .gitignore 文件:

    $ cat /.gitignore
    .DS_Store
    terraform/.terraform/
    terraform/*.plan
    terraform/*.json

    $ cd
    $ git add .github/ k8s/ terraform/ .gitignore
    $ git commit -m "GitHub on EKS"
    $ git push

    在 GitHub 仓库页面的“Actions”选项卡上监视部署过程。 请等待成功完成。

    第一次运行工作流程时,“Terraform apply”步骤需要 15 分钟左右,大约与创建集群的时间一样长。 下次启动时(如果未删除集群),工作流程会快很多。 你可以将此签出:

    $ cd
    $ git commit -m "Trigger" --allow-empty
    $ git push

    当然,最好检查一下我们做了什么。 这次可以在你的笔记本电脑上使用 IAM“my-user”的凭据:

    $ export AWS_PROFILE=my-user
    $ export AWS_REGION=eu-west-1
    $ aws sts get-caller-identity
    $ aws eks update-kubeconfig --region=eu-west-1 --name=dev-cluster --alias=dev-cluster
    $ kubectl config current-context
    dev-cluster

    $ kubectl get nodes
    NAME                                                                               STATUS   ROLES      AGE          VERSION
    ip-10-42-1-125.eu-west-1.compute.internal   Ready          6m20s     v1.14.8-eks-b8860f

    $ kubectl get po
    NAME                                                       READY        STATUS      RESTARTS   AGE
    samples-bi-756dddffdb-zd9nw    1/1               Running    0                      6m16s

    $ kubectl get svc
    NAME                   TYPE                        CLUSTER-IP        EXTERNAL-IP                                                                                                                                                         PORT(S)                    AGE
    kubernetes        ClusterIP               172.20.0.1                                                                                                                                                                                443/TCP                    11m
    samples-bi         LoadBalancer     172.20.33.235    a2c6f6733557511eab3c302618b2fae2-622862917.eu-west-1.elb.amazonaws.com    52773:31047/TCP  6m33s

    访问 _http://a2c6f6733557511eab3c302618b2fae2-622862917.eu-west-1.elb.amazonaws.com:52773/csp/user/_DeepSee.UserPortal.Home.zen?$NAMESPACE=USER _(将链接替换为你的外部 IP),然后输入“_system”、“SYS”并更改默认密码。 您应该看到一系列 BI 仪表板:

    点击每个仪表板的箭头可以深入了解:

    记住,如果重启 samples-bi pod,所有更改都将丢失。 这是有意的行为,因为这是演示。 如果你需要保留更改,我在 github-gke-zpm-registry/k8s/statefulset.tpl 仓库中创建了一个示例。

    完成后,删除你创建的所有内容:

    $ git commit -m "Mr Proper [destroy eks]" --allow-empty
    $ git push

    结论

    在本文中,我们将 eksctl 实用程序替换成 Terraform 来创建 EKS 集群。 这是向“编纂”您的所有 AWS 基础架构迈出的一步。
    我们展示了如何使用 Github Actions 和 Terraform 通过 git push 轻松部署演示应用程序。
    我们还向工具箱中添加了 kompose 和 pod 的 postStart 挂钩。
    这次我们没有展示 TLS 启用。 我们将在不久的将来完成这项任务。

    0
    0 473
    文章 Jeff Liu · 一月 7, 2021 5m read

    非常高兴地宣布,InterSystems 容器注册表现在可以使用了。 这为客户访问基于容器的版本及预览提供了新的渠道。 所有的社区版像都可在公共存储库中找到,且无需登录。 所有完整发布的像(IRIS、IRIS for Health、Health Connect、System Alerting and Monitoring、InterSystems Cloud Manager)和实用程序镜像(例如,仲裁器、Web 网关和 PasswordHash)都需要登录令牌,该令牌从 WRC 帐户生成。WRC 发布网站暂时将继续以 tarball 方式提供已发布像。 不过,您现在可以配置 CI/CD 管道以直接从 InterSystems 容器注册表“docker pull”镜像。
    可通过 https://containers.intersystems.com 访问该注册表。 有关完整的使用说明,请参阅下文或参阅文档(使用 InterSystems 容器注册表)。如果您遇到任何问题或有任何反馈要分享,请在下面的评论中告知我们,或联系 support@intersystems.com。
    --------------------------------------------------------------

    使用 InterSystems 容器注册表

    本文档列出了 InterSystems 容器注册表 (ICR) 中可用的像,并提供了使用说明。该注册表位于 containers.intersystems.com 上。

    可以使用 docker pull 命令下载 ICR 中的像,例如:

    docker pull containers.intersystems.com/intersystems/iris-community:2020.3.0.221.0

    本文档包含以下部分:

    • 公共像
    • 受限访问镜像
    • 对 ICR 进行身份验证
    • 列出 ICR 清单

    公共镜像

    以下 ICR 像是公开可用的,无需身份验证即可拉取:

    InterSystems IRIS

    IntegratedML

    2020.3

    containers.intersystems.com/intersystems/iris-ml-community:2020.3.0.302.0

    Community Edition

    2020.3

    containers.intersystems.com/intersystems/iris-community:2020.3.0.221.0

    2020.3 ARM64

    containers.intersystems.com/intersystems/iris-community-arm64:2020.3.0.221.0

    InterSystems IRIS for Health

    IntegratedML2020.3containers.intersystems.com/intersystems/irishealth-ml-community:2020.3.0.302.0
    Community Edition

    2020.3

    containers.intersystems.com/intersystems/irishealth-community:2020.3.0.221.0

    2020.3 ARM64

    containers.intersystems.com/intersystems/irishealth-community-arm64:2020.3.0.221.0

    System Alerting and Monitoring

     

    1.0

    containers.intersystems.com/intersystems/sam:1.0.0.115

    以下 ICR 镜像仅对经过身份验证的用户可用:受限访问镜像

    以下 ICR 像是公开可用的,无需身份验证即可拉取:

    Arbiter

    2020.1

    containers.intersystems.com/intersystems/arbiter:2020.1.0.215.0

    2020.2

    containers.intersystems.com/intersystems/arbiter:2020.2.0.211.0

    2020.3

    containers.intersystems.com/intersystems/arbiter:2020.3.0.210.0

    Health Connect

    2020.1

    containers.intersystems.com/intersystems/healthconnect:2020.1.0.215.0

    InterSystems Cloud Manager (ICM)

    2020.1

    containers.intersystems.com/intersystems/icm:2020.1.0.215.0

    2020.2

    containers.intersystems.com/intersystems/icm:2020.2.0.211.0

    2020.3

    containers.intersystems.com/intersystems/icm:2020.3.0.221

    InterSystems IRIS

    2020.1

    containers.intersystems.com/intersystems/iris:2020.1.0.215.0

    2020.2

    containers.intersystems.com/intersystems/iris:2020.2.0.211.0

    2020.3

    containers.intersystems.com/intersystems/iris:2020.3.0.221.0

    2020.1 ARM64

    containers.intersystems.com/intersystems/iris-arm64:2020.1.0.215.0

    2020.2 ARM64

    containers.intersystems.com/intersystems/iris-arm64:2020.2.0.211.0

    2020.3 ARM64

    containers.intersystems.com/intersystems/iris-arm64:2020.3.0.221.0

    2020.3 IntegratedMLcontainers.intersystems.com/intersystems/iris-ml:2020.3.0.302.0

    InterSystems IRIS for Health

    2020.1

    containers.intersystems.com/intersystems/irishealth:2020.1.0.217.1

    2020.2

    containers.intersystems.com/intersystems/irishealth:2020.2.0.211.0

    2020.3

    containers.intersystems.com/intersystems/irishealth:2020.3.0.221.0

    2020.1 ARM64

    containers.intersystems.com/intersystems/irishealth-arm64:2020.1.0.217.1

    2020.2 ARM64

    containers.intersystems.com/intersystems/irishealth-arm64:2020.2.0.211.0

    2020.3 ARM64

    containers.intersystems.com/intersystems/irishealth-arm64:2020.3.0.221.0

    2020.3 IntegratedMLcontainers.intersystems.com/intersystems/irishealth-ml:2020.3.0.302.0

    PasswordHash

    1.0

    containers.intersystems.com/intersystems/passwordhash:1.0

    Web Gateway

    2020.2

    containers.intersystems.com/intersystems/webgateway:2020.2.0.211.0

    2020.3

    containers.intersystems.com/intersystems/webgateway:2020.3.0.221.0


    要登录至 ICR,请执行以下步骤:对 ICR 进行身份验证

    • 在您的浏览器中加载 https://containers.intersystems.com/,然后使用您的 InterSystems/WRC 凭据登录。
    • 检索您的 Docker 登录令牌或完整的登录命令。
    • 在 Docker 界面(例如,PowerShell 窗口或 Linux 命令行)中,使用提供的凭据对 ICR 进行身份验证。 您可以通过复制并粘贴显示的完整 docker login 命令来执行此操作,例如:
    docker login -u="bbinstoc" -p="provided_password" containers.intersystems.com

    但是,出于安全原因,您可能想要输入命令 docker login container.intersystems.com,然后在 Username 提示符下输入用户名并将密码粘贴到 Password: 提示符下。

    注意:如果您登录到另一个 Docker 注册表,则 docker login 命令可能会导致错误;登录到 container.intersystems.com 之前,请先注销其他注册表。

    1. 现在,您可以从 ICR 中拉取镜像,例如:
    docker pull containers.intersystems.com/intersystems/iris:2020.3.0.221.0

    列出 ICR 清单

    API 可用于列出 Docker 注册表中的镜像和标签。 可用于列出注册表清单的开源第三方实用程序的一个示例是 docker-ls ,其可从 https://github.com/mayflower/docker-ls 获取。

    获取此实用程序的方法有几种。 你可以:

    • 下载用于各种平台的预编译 docker-ls 二进制文件
    • 直接在某些平台上安装该实用程序,例如,在 Linux 系统上使用以下命令进行安装:
    sudo snap install docker-ls
    • 在 Linux 平台上拉取并运行镜carinadigital/docker-ls:latest 以安装该实用程序,例如:
    docker run --rm carinadigital/docker-ls:latest

    安装 docker-ls 后,您可以使用以下命令列出 ICR 中的存储库:

    docker-ls repositories --registry https://containers.intersystems.com --user username --password password

    注意:使用 --interactive-password 选项提示输入密码,不要在命令行中输入密码。

    要仅列出公开可用的像,请为 -user --password 选项提供空字符串 ("") 作为参数, 例如,以下仅列出了公共 InterSystems IRIS for Health 镜像的标签:

    docker-ls tags --registry https://containers.intersystems.com --user "" --password "" intersystems/irishealth-community

    如果希望看到非公共像的完整列表,则无论是否登录 container.intersystems.com,都需要向该实用程序提供用户名和密码。

    可访问 https://github.com/mayflower/docker-ls 了解其他示例。

    0
    0 178