index.json 388.8 KB
Newer Older
LinuxSuRen's avatar
LinuxSuRen 已提交
1
[
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
3
        "uri": "https://jenkins-zh.cn/about/code-of-conduct/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
4
        "title": "行为规范",
LinuxSuRen's avatar
LinuxSuRen 已提交
5 6
        "type": "about",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
7 8
        "tags": [],
        "description": "行为规范",
LinuxSuRen's avatar
LinuxSuRen 已提交
9 10 11 12 13
        "content": " 留言 留言之前需要使用 GitHub 账号登陆。大家要注意文明用语,严禁攻击、诋毁、灌水、广告等无关的话。对于违反人,一经发现将会被拉入黑名单。\n提问 欢迎每一位朋友在这里提出与 Jenkins 或相关领域的技术问题,但是,在提问之前建议先在搜索引擎和本站中进行搜索。\n问题至少要包含如下部分:\n 场景以及问题是如何发生的,方便阅读的人复现 软件、环境相关版本信息 日志、截图等(建议使用附件的方式)  出于对回答问题者的尊重,请得到解决方案后及时表示感谢,或者从其他地方得到答案后添加相关链接以及说明。\nGitHub 请您使用同一个 GitHub 账号来与大家交流,不欢迎使用所谓的“小号”。\n",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
14
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-28-jenkins-pipeline-shared-lib-unit-test/",
        "title": "如何对 Jenkins 共享库进行单元测试",
        "type": "wechat",
        "date": "2019-05-28 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "包括该单元测试框架的原理介绍",
        "content": " Jenkins 共享库是除了 Jenkins 插件外,另一种扩展 Jenkins 流水线的技术。通过它,可以轻松地自定义步骤,还可以对现有的流水线逻辑进行一定程度的抽象与封装。至于如何写及如何使用它,读者朋友可以移步附录中的官方文档。\n对共享库进行单元测试的原因 但是如何对它进行单元测试呢?共享库越来越大时,你不得不考虑这个问题。因为如果你不在早期就开始单元测试,共享库后期可能就会发展成如下图所示的“艺术品”——能工作,但是脆弱到没有人敢动。\n[图片来自网络,侵权必删]\n这就是代码越写越慢的原因之一。后人要不断地填前人有意无意挖的坑。\n共享库单元测试搭建 共享库官方文档介绍的代码仓库结构 (root) +- src # Groovy source files | +- org | +- foo | +- Bar.groovy # for org.foo.Bar class +- vars | +- foo.groovy # for global 'foo' variable | +- foo.txt # help for 'foo' variable +- resources # resource files (external libraries only) | +- org | +- foo | +- bar.json # static helper data for org.foo.Bar  以上是共享库官方文档介绍的代码仓库结构。整个代码库可以分成两部分:src 目录部分和 vars 目录部分。它们的测试脚手架的搭建方式是不一样的。\nsrc 目录中的代码与普通的 Java 类代码本质上没有太大的区别。只不过换成了 Groovy 类。\n但是 vars 目录中代码本身是严重依赖于 Jenkins 运行时环境的脚本。\n接下来,分别介绍如何搭建它们的测试脚手架。\n测试 src 目录中的 Groovy 代码 在对 src 目录中的 Groovy 代码进行单元测试前,我们需要回答一个问题:使用何种构建工具进行构建?\n我们有两种常规选择:Maven 和 Gradle。本文选择的是前者。\n接下来的第二个问题是,共享库源代码结构并不是 Maven 官方标准结构。下例为标准结构:\n├── pom.xml └── src ├── main │ ├── java │ └── resources └── test ├── java └── resources  因为共享库使用的 Groovy 写的,所以,还必须使 Maven 能对 Groovy 代码进行编译。\n可以通过 Maven 插件:GMavenPlus 解决以上问题,插件的关键配置如下:\n\u0026lt;configuration\u0026gt; \u0026lt;sources\u0026gt; \u0026lt;source\u0026gt; \u0026lt;!-- 指定Groovy类源码所在的目录 --\u0026gt; \u0026lt;directory\u0026gt;${project.basedir}/src\u0026lt;/directory\u0026gt; \u0026lt;includes\u0026gt; \u0026lt;include\u0026gt;**/*.groovy\u0026lt;/include\u0026gt; \u0026lt;/includes\u0026gt; \u0026lt;/source\u0026gt; \u0026lt;/sources\u0026gt; \u0026lt;testSources\u0026gt; \u0026lt;testSource\u0026gt; \u0026lt;!-- 指定单元测试所在的目录 --\u0026gt; \u0026lt;directory\u0026gt;${project.basedir}/test/groovy\u0026lt;/directory\u0026gt; \u0026lt;includes\u0026gt; \u0026lt;include\u0026gt;**/*.groovy\u0026lt;/include\u0026gt; \u0026lt;/includes\u0026gt; \u0026lt;/testSource\u0026gt; \u0026lt;/testSources\u0026gt; \u0026lt;/configuration\u0026gt;  同时,我们还必须加入 Groovy 语言的依赖:\n\u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.codehaus.groovy\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;groovy-all\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${groovy-all.version}\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt;  最终目录结构如下图所示: 然后我们就可以愉快地对 src 目录中的代码进行单元测试了。\n测试 vars 目录中 Groovy 代码 对 vars 目录中的脚本的测试难点在于它强依赖于 Jenkins 的运行时环境。换句话说,你必须启动一个 Jenkins 才能正常运行它。但是这样就变成集成测试了。那么怎么实现单元测试呢?\n经 Google 发现,前人已经写了一个 Jenkins 共享库单元测试的框架。我们拿来用就好。所谓,前人载树,后人乘凉。\n这个框架叫:Jenkins Pipeline Unit testing framework。后文简称“框架”。它的使用方法如下:\n 在 pom.xml 中加入依赖: xml \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;com.lesfurets\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;jenkins-pipeline-unit\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;1.1\u0026lt;/version\u0026gt; \u0026lt;scope\u0026gt;test\u0026lt;/scope\u0026gt; \u0026lt;/dependency\u0026gt;  写单元测试\n// test/groovy/codes/showme/pipeline/lib/SayHelloTest.groovy // 必须继承 BasePipelineTest 类 class SayHelloTest extends BasePipelineTest { @Override @Before public void setUp() throws Exception { // 告诉框架,共享库脚本所在的目录 scriptRoots = [\u0026quot;vars\u0026quot;] // 初始化框架 super.setUp() } @Test void call() { // 加载脚本 def script = loadScript(\u0026quot;sayHello.groovy\u0026quot;) // 运行脚本 script.call() // 断言脚本中运行了 echo 方法 // 同时参数为\u0026quot;hello pipeline\u0026quot; assertThat( helper.callStack .findAll { c -\u0026gt; c.methodName == 'echo' } .any { c -\u0026gt; c.argsToString().contains('hello pipeline') } ).isTrue() // 框架提供的方法,后面会介绍。 printCallStack() } }    创建单元测试时,注意选择 Groovy 语言,同时类名要以 Test 结尾。\n  改进 以上代码是为了让读者对共享库脚本的单元测试有更直观的理解。实际工作中会做一些调整。我们会将 extends BasePipelineTest 和 setUp 方法抽到一个父类中,所有其它测试类继承于它。  此时,我们最简单的共享库的单元测试脚手架就搭建好了。\n但是,实际工作中遇到场景并不会这么简单。面对更复杂的场景,必须了解 Jenkins Pipeline Unit testing framework 的原理。由此可见,写单元测试也是需要成本的。至于收益,仁者见仁,智者见智了。\nJenkins Pipeline Unit testing framework 原理 上文中的单元测试实际上做了三件事情: 1. 加载目标脚本,loadScript 方法由框架提供。 2. 运行脚本,loadScript 方法返回加载好的脚本。 3. 断言脚本中的方法是否有按预期执行,helper 是 BasePipelineTest 的一个字段。\n从第三步的 helper.callStack 中,我们可以猜到第二步中的script.call() 并不是真正的执行,而是将脚本中方法调用被写到 helper 的 callStack 字段中。从 helper 的源码可以确认这一点:\n/** * Stack of method calls of scripts loaded by this helper */ List\u0026lt;MethodCall\u0026gt; callStack = []  那么,script.call() 内部是如何做到将方法调用写入到 callStack 中的呢?\n一定是在 loadScript 运行过程做了什么事情,否则,script 怎么会多出这些行为。我们来看看它的底层源码:\n/** * Load the script with given binding context without running, returning the Script * @param scriptName * @param binding * @return Script object */ Script loadScript(String scriptName, Binding binding) { Objects.requireNonNull(binding, \u0026quot;Binding cannot be null.\u0026quot;) Objects.requireNonNull(gse, \u0026quot;GroovyScriptEngine is not initialized: Initialize the helper by calling init().\u0026quot;) Class scriptClass = gse.loadScriptByName(scriptName) setGlobalVars(binding) Script script = InvokerHelper.createScript(scriptClass, binding) script.metaClass.invokeMethod = getMethodInterceptor() script.metaClass.static.invokeMethod = getMethodInterceptor() script.metaClass.methodMissing = getMethodMissingInterceptor() return script }  gse 是 Groovy 脚本执行引擎 GroovyScriptEngine。它在这里的作用是拿到脚本的 Class 类型,然后使用 Groovy 语言的 InvokerHelper 静态帮助类创建一个脚本对象。\n接下来做的就是核心了:\nscript.metaClass.invokeMethod = getMethodInterceptor() script.metaClass.static.invokeMethod = getMethodInterceptor() script.metaClass.methodMissing = getMethodMissingInterceptor()  它将脚本对象实例的方法调用都委托给了拦截器 methodInterceptor。Groovy 对元编程非常友好。可以直接对方法进行拦截。拦截器源码如下:\n/** * Method interceptor for any method called in executing script. * Calls are logged on the call stack. */ public methodInterceptor = { String name, Object[] args -\u0026gt; // register method call to stack int depth = Thread.currentThread().stackTrace.findAll { it.className == delegate.class.name }.size() this.registerMethodCall(delegate, depth, name, args) // check if it is to be intercepted def intercepted = this.getAllowedMethodEntry(name, args) if (intercepted != null \u0026amp;\u0026amp; intercepted.value) { intercepted.value.delegate = delegate return callClosure(intercepted.value, args) } // if not search for the method declaration MetaMethod m = delegate.metaClass.getMetaMethod(name, args) // ...and call it. If we cannot find it, delegate call to methodMissing def result = (m ? this.callMethod(m, delegate, args) : delegate.metaClass.invokeMissingMethod(delegate, name, args)) return result }  它做了三件事情: 1. 将调用方法名和参数写入到 callStack 中 2. 如果被调用方法名是被注册了的方法,则执行该方法对象的 mock。下文会详细介绍。 3. 如果被调用方法没有被注册,则真正执行它。\n需要解释一个第二点。并不是所有的共享库中的方法都是需要拦截的。我们只需要对我们感兴趣的方法进行拦截,并实现 mock 的效果。\n写到这里,有些读者朋友可能头晕了。笔者在这里进行小结一下。\n 因为我们不希望共享库脚本中的依赖于 Jenkins 运行时的方法(比如拉代码的步骤)真正运行。所以,我们需要对这些方法进行 mock。在 Groovy 中,我们可以通过方法级别的拦截来实现 mock 的效果。 但是我们又不应该对共享库中所有的方法进行拦截,所以就需要我们在执行单元测试前将自己需要 mock 的方法进行注册到 helper 的 allowedMethodCallbacks 字段中。methodInterceptor拦截器会根据它来进行拦截。\n 在 BasePipelineTest 的 setUp 方法中,框架注册了一些默认方法,不至于我们要手工注册太多方法。以下是部分源码:\nhelper.registerAllowedMethod(\u0026quot;sh\u0026quot;, [Map.class], null) helper.registerAllowedMethod(\u0026quot;checkout\u0026quot;, [Map.class], null) helper.registerAllowedMethod(\u0026quot;echo\u0026quot;, [String.class], null)  registerAllowedMethod 各参数的作用: * 第一个参数:要注册的方法。 * 第二参数:该方法的参数列表。 * 第三参数:一个闭包。当该访问被调用时会执行此闭包。\n以上就是框架的基本原理了。接下来,再介绍几种场景。\n几种应用场景 环境变量 当你的共享库脚本使用了 env 变量,可以这样测试:\nbinding.setVariable('env', new HashMap()) def script = loadScript('setEnvStep.groovy') script.invokeMethod(\u0026quot;call\u0026quot;, [k: '123', v: \u0026quot;456\u0026quot;]) assertEquals(\u0026quot;123\u0026quot;, ((HashMap) binding.getVariable(\u0026quot;env\u0026quot;)).get(\u0026quot;k\u0026quot;))  binding 由 BasePipelineTest 的一个字段,用于绑定变量。binding 会被设置到 gse 中。\n调用其它共享库脚本 比如脚本 a 中调用到了 setEnvStep。这时可以在 a 执行前注册 setEnvStep 方法。\nhelper.registerAllowedMethod(\u0026quot;setEnvStep\u0026quot;, [LinkedHashMap.class], null)  希望被 mock 的方法能有返回值 helper.registerAllowedMethod(\u0026quot;getDevOpsMetadata\u0026quot;, [String.class, String.class], { return \u0026quot;data from cloud\u0026quot; })  后记 不得不说 Jenkins Pipeline Unit testing framework 框架的作者非常聪明。另外,此类技术不仅可以用于单元测试。理论上还可以用于 Jenkins pipeline 的零侵入拦截,以实现一些平台级特殊的需求。\n附录  共享库官方文档:https://jenkins.io/zh/doc/book/pipeline/shared-libraries/ 本文示例代码:https://github.com/zacker330/jenkins-pipeline-shared-lib-unittest-demo JenkinsPipelineUnit:https://github.com/jenkinsci/JenkinsPipelineUnit  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": "poster.png"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-27-docs-sig-announcement/",
        "title": "Jenkins 文档特别兴趣小组",
        "type": "wechat",
        "date": "2019-05-27 00:00:00 +0000 UTC",
        "tags": ["documentation", "docs", "community"],
        "description": "Jenkins 宣布成立文档特别兴趣小组",
        "content": " 我们很高兴地宣布 Jenkins 文档特别兴趣小组的成立。 文档特别兴趣小组鼓励贡献者和外部社区创建和 review Jenkins 文档。\n更多详情和计划,请参见:文档特别兴趣小组简介。\n我能帮什么忙呢? Jenkins 文档特别兴趣小组希望从以下方面得到您的帮助:\n review 及修复 打开的 bug 报告 review Jenkins 文档 pull requests review Jenkins X 文档 pull requests  我该如何修复文档 bug? 关于如何为 Jenkins 文档做贡献的说明,请参见站点仓库中的 CONTRIBUTING 文件。 按照说明文件,提交 pull requests 以供 review 。\n关于如何为 Jenkins X 文档做贡献的说明,请参见站点仓库中的 Jenkins X 文档站点。 按照说明文件,提交 pull requests 以供 review 。\n我该如何评估 pull request? Jenkins 项目的 pull requests 会在 Jenkins 文档仓库进行 review 。 使用您的凭据登录到 GitHub,向 pull requests 中添加评论。\nJenkins X 项目的 pull requests 会在 Jenkins X 档仓库进行 review 。 使用您的凭据登录到 GitHub,向 pull requests 中添加评论。\n",
        "auhtor": "markewaite",
        "translator": "donhui",
        "original": "https://jenkins.io/blog/2019/05/11/docs-sig-announcement/",
        "poster": "./2019-05-27-docs-sig-announcement/Jenkins_Needs_You-02.png"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-24-achieve-cicd-with-jenkins-x-kubernetes-and-spring/",
        "title": "使用 Jenkins X、Kubernetes 和 Spring Boot 实现 CI/CD",
        "type": "wechat",
        "date": "2019-05-24 00:00:00 +0000 UTC",
        "tags": ["jenkins-x", "k8s", "kubernetes", "ci", "cd", "spring boot"],
        "description": "通过使用 Jenkins X 和 Kubernetes 来改进 Spring Boot 应用程序,使 Jenkins X 成为 CI/CD 过程的关键部分。",
        "content": " 过去五年中的变化,如迁移到公有云以及从虚拟机向容器的转变,已经彻底改变了构建和部署软件的意义。\n以 Kubernetes 为例。Google 于2014年开源,现在所有主流的公有云供应商都支持它\u0026mdash;它为开发人员提供了一种很好的方式,可以将应用程序打包到 Docker 容器中,并部署到任意 Kubernetes 集群中。\n使用 CI/CD、Kubernetes 和 Jenkins X 进行高性能开发 在技术上,高性能团队几乎总是成功的必要条件,而持续集成、持续部署(CI/CD)、小迭代以及快速反馈是构建模块。为你的云原生应用程序设置 CI/CD 可能比较困难。通过自动化所有内容,开发人员可以花费宝贵的时间来交付实际的业务。\n如何使用容器、持续交付和 Kubernetes 成为高效团队?这就是 Jenkins X 的切入点。 “Jenkins X 的理念是为所有开发人员提供他们自己的海军航海管家,可以帮助你航行持续交付的海洋。” - James Strachan Jenkins X 帮助你自动化你在 Kubernetes 中的 CI/CD - 你甚至不需要学习 Docker 或 Kubernetes!\nJenkins X 能做什么? Jenkins X 在 Kubernetes 上自动安装,配置和升级 Jenkins 和其他应用程序(Helm,Skaffold,Nexus 等)。它使用 Docker 镜像、Helm 图表和流水线来自动化应用程序的 CI/CD。它使用 GitOps 来管理环境之间的升级,并通过在拉取请求和生产时对其进行评论来提供大量反馈。\nJenkins X 入门 要安装 Jenkins X,首先需要在你的机器或云供应商上安装 jx 二进制文件。从 Google Cloud 可以获得300美元的积分,所以我决定从那里开始。\n在 Google Cloud 上安装 Jenkins X 并创建群集 浏览到cloud.google.com并登录。如果你还没有帐户,请注册免费试用。转到控制台(右上角有一个链接)并激活 Google Cloud shell。将以下命令复制并粘贴到 shell 中。\ncurl -L https://github.com/jenkins-x/jx/releases/download/v1.3.79/jx-linux-amd64.tar.gz | tar xzv sudo mv jx /usr/local/bin  注意:Google Cloud Shell 将在一小时后终止在你的主目录之外所做的任何更改,因此你可能必须重新运行这些命令。好消息是它们将在你的历史中,所以你只需要向上箭头并进入。你也可以删除上面的 sudo mv 命令,并将以下内容添加到 .bashrc 中。\nexport PATH=$PATH:.  使用以下命令在 GKE(Google Kubernetes Engine)上创建集群。你可能必须为你的帐户启用 GKE。\njx create cluster gke --skip-login  如果系统提示你下载 helm,请确认你要安装。系统将提示你选择 Google Cloud Zone。我建议选择一个靠近你的位置。我选择 us-west1-a,因为我住在 Denver, Colorado 附近。对于 Google Cloud Machine 类型,我选择了 n1-standard-2 并使用了 min(3)和 max(5)个节点数的默认值。\n对于 GitHub 名称,键入你自己的(例如 mraible)和你在 GitHub 上注册的电子邮件(例如 matt.raible@okta.com)。我试图使用 oktadeveloper(一个 GitHub 组织),但我无法使其工作。\n注意:如果你的帐户启用了两步认证,则 GitHub 集成将失败。如果你希望成功完成该过程,则需要在 GitHub 上禁用它。\n当提示安装 ingress controller 时,按 Enter 键 确定。再次按 Enter 键选择默认 domain。\n系统将提示你创建 GitHub API Token。单击 提供的 URL 并将其命名为 “Jenkins X”。将 token 值复制并粘贴回控制台。\n在安装完成后喝杯咖啡、饮料或做一些俯卧撑。可能需要几分钟。\n下一步是将 API token 从 Jenkins 复制到你的控制台。按照控制台中提供的说明进行操作。\n完成后,运行 jx console 并单击链接以登录到 Jenkins 实例。单击 Administration 并升级 Jenkins 及其所有插件(插件管理器 \u0026gt; 滚动到底部并选择全部)。如果未能执行此步骤,将无法从 GitHub pull request 到 Jenkins X CI 进程。\n创建一个 Spring Boot 应用程序 当我第一次开始使用 Jenkins X 时,我尝试导入现有项目。即使我的应用程序使用了 Spring Boot,但是根目录中没有 pom.xml,所以 Jenkins X 认为它是一个 Node.js 应用程序。出于这个原因,我建议首先创建一个空白的 Spring Boot 应用程序,以保证 Jenkins X 正确创建。\n从 Cloud Shell 创建一个简单的 Spring Boot 应用程序:\njx create spring -d web -d actuator  此命令使用 Spring Initializr,因此系统会提示你进行一些选择。以下是我的选择:\n   QUESTION ANSWER     Language java   Group com.okta.developer   Artifact okta-spring-jx-example    提示:为你的 artifact name 选取一个简洁的名称将减轻你的痛苦。Jenkins X 对于版本名称有53个字符的限制,oktadeveloper/okta-spring-boot-jenkinsx-example 将会使它超过两个字符。\n为 git 用户名、初始化 git 和提交消息都选择默认值。如果你不想使用个人帐户,可以选择要使用的组织。运行以下命令以查看应用程序的 CI/CD 流水线。\njx get activity -f okta-spring-jx-example -w  运行 jx console,单击生成的链接,然后导航到你的项目(如果你想要一个更富视觉效果的视图)。\n此过程将执行一些任务:\n 为你的项目创建一个版本。 为演示环境项目创建 pull request。 将其自动部署到演示环境,以便你可以查看它的运行情况。  Merge status checks all passed so the promotion worked! Application is available at: http://okta-spring-jx-example.jx-staging.35.230.106.169.nip.io   注意:由于 Spring Boot 默认情况下不提供欢迎页面,所以打开上面的 URL 时将返回404。\n使用 Jenkins X 将 Spring Boot 应用程序部署到生产环境中 默认情况下,Jenkins X 只会自动部署到演示环境。你可以手动改进从演示到生产使用:\njx promote okta-spring-jx-example --version 0.0.1 --env production  你可以使用 jx edit environment 更改生产环境,以使用自动部署。\n既然你已经知道如何使用 Jenkins X 和一个简单的 Spring Boot 应用程序,让我们来看看如何通过一个更实际的示例使其工作。\n保护你的 Spring Boot 应用程序并添加 Angular PWA 在过去的几个月里,我写了一系列有关使用 Ionic/Angular 和 Spring Boot 构建 PWA(渐进式 Web 应用程序)的博文。\n 使用 Okta 保护你的加密货币财富跟踪 PWA 使用 Okta(而不是本地存储)安全地存储用户的数据 使用 WireMock、Jest、Protractor 和 Travis CI 测试 Spring Boot API 和 Angular 组件的 Hitchhiker 指南 将你的 Spring Boot + Angular PWA 部署为一个 Artifact 这是该系列的最后一篇博客文章。我相信这是一个真实应用程序的很好的例子,因为它有许多单元和集成测试,包括与 Protractor 的端到端测试。让我们看看如何使用 Jenkins X 和 Kubernetes 自动化生产路径!  克隆刚刚从GitHub创建的Spring Boot项目(确保在URL中更改{yourUsername}):\ngit clone https://github.com/{yourUsername}/okta-spring-jx-example.git okta-jenkinsx  在邻近目录中,将创建的具有 Spring Boot + Angular 的项目克隆为一个 artifact:\ngit clone https://github.com/oktadeveloper/okta-spring-boot-angular-auth-code-flow-example.git spring-boot-angular  在终端中,导航到 okta-jenkinsx 并删除不再需要的文件:\ncd okta-jenkinsx rm -rf .mvn src mvnw* pom.xml  结果应该是包含以下文件的目录结构:\n$ tree . . ├── charts │ ├── okta-spring-jx-example │ │ ├── Chart.yaml │ │ ├── Makefile │ │ ├── README.md │ │ ├── templates │ │ │ ├── deployment.yaml │ │ │ ├── _helpers.tpl │ │ │ ├── NOTES.txt │ │ │ └── service.yaml │ │ └── values.yaml │ └── preview │ ├── Chart.yaml │ ├── Makefile │ ├── requirements.yaml │ └── values.yaml ├── Dockerfile ├── Jenkinsfile └── skaffold.yaml 4 directories, 15 files  将 spring-boot-angular 所有文件复制到 okta-jenkinsx。\ncp -r ../spring-boot-angular/* .  使用 Travis CI 测试此应用程序时,我运行了 npm install 作为该过程的一部分。使用 Jenkins X,使用一个容器(例如 maven 或者 nodejs)保存所有内容更简单,因此在 frontend-maven-plugin(在 holdings-api/pom.xml)中添加执行以运行 npm install (提示:你将需要执行 id==’npm install' 添加到现有的pom.xml中)。\n现在是 okta-jenkinsx 在 IntelliJ IDEA、Eclipse、Netbeans 或 VS Code 等 IDE 中作为项目打开目录的好时机!\n\u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;com.github.eirslett\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;frontend-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${frontend-maven-plugin.version}\u0026lt;/version\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;workingDirectory\u0026gt;../crypto-pwa\u0026lt;/workingDirectory\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;install node and npm\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;install-node-and-npm\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;nodeVersion\u0026gt;${node.version}\u0026lt;/nodeVersion\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;npm install\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;npm\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;phase\u0026gt;generate-resources\u0026lt;/phase\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;arguments\u0026gt;install --unsafe-perm\u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; ... \u0026lt;/executions\u0026gt; \u0026lt;/plugin\u0026gt;  注意:--unsafe-perm 标志是必要的,因为 Jenkins X 以 root 用户身份运行构建。我从 node-sass 的故障排除说明中找到了这个解决方案。\n增加 Actuator 并关闭 HTTPS Jenkins X 依靠 Spring Boot 的 Actuator 进行健康检查。这意味着如果你不将其包含在你的项目中(或有 /actuator/health 防护),Jenkins X 会报告你的应用程序启动失败。\n将 Actuator starter 作为依赖项添加到 holdings-api/pom.xml 中:\n\u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-starter-actuator\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt;  你还需要允许访问其运行健康检查。Jenkins X 将部署你的应用程序在一个 NGINX 服务器中,因此你也需要强制关闭 HTTPS,否则你将无法访问你的应用程序。修改 holdings-api/src/main/java/.../SecurityConfiguration.java 以允许 holdings-api/src/main/java/.../SecurityConfiguration.java 和删除 requiresSecure()。\npublic class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers(\u0026quot;/**/*.{js,html,css}\u0026quot;); } @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .and() .authorizeRequests() .antMatchers(\u0026quot;/\u0026quot;, \u0026quot;/home\u0026quot;, \u0026quot;/api/user\u0026quot;, \u0026quot;/actuator/health\u0026quot;).permitAll() .anyRequest().authenticated(); } }  调整 Dockerfile 和 Jenkinsfile 中的路径 由于此项目构建在子目录而不是根目录中,因此请更新 ./Dockerfile 以查找 holdings-api 文件。\nFROM openjdk:8-jdk-slim ENV PORT 8080 ENV CLASSPATH /opt/lib EXPOSE 8080 # copy pom.xml and wildcards to avoid this command failing if there's no target/lib directory COPY holdings-api/pom.xml holdings-api/target/lib* /opt/lib/ # NOTE we assume there's only 1 jar in the target dir # but at least this means we don't have to guess the name # we could do with a better way to know the name - or to always create an app.jar or something COPY holdings-api/target/*.jar /opt/app.jar WORKDIR /opt CMD [\u0026quot;java\u0026quot;, \u0026quot;-jar\u0026quot;, \u0026quot;app.jar\u0026quot;]  你还需要更新 Jenkinsfile,以便它可以运行 holdings-api 目录中的任何 mvn 命令。也添加 -Pprod 配置文件。例如:\n// in the 'CI Build and push snapshot' stage steps { container('maven') { dir ('./holdings-api') { sh \u0026quot;mvn versions:set -DnewVersion=$PREVIEW_VERSION\u0026quot; sh \u0026quot;mvn install -Pprod\u0026quot; } } ... } // in the 'Build Release' stage dir ('./holdings-api') { sh \u0026quot;mvn versions:set -DnewVersion=\\$(cat ../VERSION)\u0026quot; } ... dir ('./holdings-api') { sh \u0026quot;mvn clean deploy -Pprod\u0026quot; }  这应该足以让这个应用程序与 Jenkins X 一起使用。但是,除非你有一个 Okta 帐户并相应地配置它,否则你将无法登录它。\n为什么使用Okta? 简而言之,我们使标识管理比你可能习惯的更简洁、更安全、更具可扩展性。Okta 是一种云服务,允许开发人员创建、编辑和安全存储用户帐户和用户帐户数据,并将其与一个或多个应用程序相连接。我们的 API 使你能够:\n 对用户进行身份验证和授权 存储关于用户的数据 执行基于密码和社交登录 使用多重身份验证保护应用程序 了解更多!查看我们的产品文档 你心动了吗?注册一个永远免费的开发者帐户,当你完成后,请返回,以便我们可以通过 Spring Boot 和 Jenkins X 了解有关 CI/CD 的更多信息!  在 Okta 中为 Spring Boot 应用程序创建一个 Web 应用程序 完成设置过程后,登录到你的帐户并导航到 Applications \u0026gt; Add Application。单击 Web 和 下一步。在下一页中,输入以下值并单击 Done (必须单击 Done,然后编辑以修改注销重定向 URI)。\n 应用名称: Jenkins X 默认 URI: http://localhost:8080 登录重定向 URI: http://localhost:8080/login 注销重定向 URI: http://localhost:8080 打开 holdings-api/src/main/resources/application.yml 并将你 org/app 中的值粘贴到其中。  okta: client: orgUrl: https://okta.okta.com token: XXX security: oauth2: client: access-token-uri: https://okta.okta.com/oauth2/default/v1/token user-authorization-uri: https://okta.okta.com/oauth2/default/v1/authorize client-id: {clientId} client-secret: {clientSecret} resource: user-info-uri: https://okta.okta.com/oauth2/default/v1/userinfo   你将注意到 token 值是 xxx。这是因为我更喜欢从环境变量中读取它,而不是签入源代码控制。你可能也想为你的客户密钥执行此操作,但我只是为了简洁而做一个属性。要创建 API token:\n 导航到 API \u0026gt; Tokens ,然后单击 Create Token 为令牌命名(例如 “Jenkins X”),然后将其值设置为 OKTA_CLIENT_TOKEN 环境变量。 你需要在组织的用户配置文件中添加一个 holdings 属性,以便将你的加密货币存储在 Okta 中。导航到 Users \u0026gt; Profile Editor。点击 Profile 表格中的第一个配置文件。你可以通过其 Okta 标识来识别它。单击 Add Attribute 并使用以下值:   显示名称: Holdings 变量名: holdings 描述: Cryptocurrency Holdings 执行这些步骤后,你应该能够导航到 http://localhost:8080, 并在运行以下命令后登录:  cd holdings-api ./mvnw -Pprod package java -jar target/*.jar   在 Jenkins X 中存储 Secrets 在本地存储环境变量非常简单。但是你如何在 Jenkins X 中做到这一点?看看它的凭证功能就知道了。下面是使用方法:\n 在 Google Cloud Shell 上运行 jx console,以获取 Jenkins X 网址 单击该链接,登录,然后单击顶部的 Administration 单击 Credentials \u0026gt; (global) \u0026gt; Add Credentials(在左侧) 从下拉列表中选择 Secret text,并为 ID 输入 OKTA_CLIENT_TOKEN 将 Okta API token 复制/粘贴到 Secret 字段中 当你在里面,添加 secrets:OKTA_APP_ID、E2E_USERNAME 和 E2E_PASSWORD。第一个是你创建的 Jenkins X OIDC 应用程序的 ID。您可以通过在 Okta 上导航到您的应用程序并从 URL 复制值来获得它的值。该 E2E-* 密钥应该是要用来运行终端到终端(Protractor)测试的凭证。你可能想为此创建一个新用户。  你可以通过将这些值添加到 environment 顶部附近的部分来访问 Jenkinsfile 中的这些值 。\nenvironment { ORG = 'mraible' APP_NAME = 'okta-spring-jx-example' CHARTMUSEUM_CREDS = credentials('jenkins-x-chartmuseum') OKTA_CLIENT_TOKEN = credentials('OKTA_CLIENT_TOKEN') OKTA_APP_ID = credentials('OKTA_APP_ID') E2E_USERNAME = credentials('E2E_USERNAME') E2E_PASSWORD = credentials('E2E_PASSWORD') }  将环境变量转移到 Docker 容器 要将 OKTA_CLIENT_TOKEN 环境变量转移到 Docker 容器,请查看:\nsh \u0026quot;make preview\u0026quot;  并将其更改为:\nsh \u0026quot;make OKTA_CLIENT_TOKEN=\\$OKTA_CLIENT_TOKEN preview\u0026quot;  此时,你可以创建分支,提交更改,并验证 Jenkins X 中的所有内容是否正常工作。\ncd .. git checkout -b add-secure-app git add . git commit -m \u0026quot;Add Bootiful PWA\u0026quot; git push origin add-secure-app  打开浏览器并导航到 GitHub 上的存储库并创建 pull request。创建后它应该如下所示。\n如果你的 pull request 测试通过,你应该能看到一些绿色标记和 Jenkins X 的评论,说明你的应用程序在预览环境中可用。\n如果你单击此处链接并尝试登录,则可能会从 Okta 得到一个错误,指出重定向 URI 尚未列入白名单。\n在 Okta 中自动添加重定向 URI 当你在 Okta 中创建应用程序并在本地运行它们时,很容易知道应用程序的重定向 URI 将是什么。对于这个特定的应用程序,它们将 http://localhost:8080/login 用于登录,http://localhost:8080 用于注销。当您进入生产环境时,URL通常也是众所周知的。但是,使用 Jenkins X,URL 是动态的,并根据你的 pull request 编号动态创建的。\n要使用 Okta 进行此操作,你可以创建一个 Java 类,该类与 Okta API 进行交互。创建 holdings-api/src/test/java/.../cli/AppRedirectUriManager.java 并使用以下代码完善它。\npackage com.okta.developer.cli; import com.okta.sdk.client.Client; import com.okta.sdk.lang.Collections; import com.okta.sdk.resource.application.OpenIdConnectApplication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @SpringBootApplication public class AppRedirectUriManager implements ApplicationRunner { private static final Logger log = LoggerFactory.getLogger(AppRedirectUriManager.class); private final Client client; @Value(\u0026quot;${appId}\u0026quot;) private String appId; @Value(\u0026quot;${redirectUri}\u0026quot;) private String redirectUri; @Value(\u0026quot;${operation:add}\u0026quot;) private String operation; public AppRedirectUriManager(Client client) { this.client = client; } public static void main(String[] args) { SpringApplication.run(AppRedirectUriManager.class, args); } @Override public void run(ApplicationArguments args) { log.info(\u0026quot;Adjusting Okta settings: {appId: {}, redirectUri: {}, operation: {}}\u0026quot;, appId, redirectUri, operation); OpenIdConnectApplication app = (OpenIdConnectApplication) client.getApplication(appId); String loginRedirectUri = redirectUri + \u0026quot;/login\u0026quot;; // update redirect URIs List\u0026lt;String\u0026gt; redirectUris = app.getSettings().getOAuthClient().getRedirectUris(); // use a set so values are unique Set\u0026lt;String\u0026gt; updatedRedirectUris = new LinkedHashSet\u0026lt;\u0026gt;(redirectUris); if (operation.equalsIgnoreCase(\u0026quot;add\u0026quot;)) { updatedRedirectUris.add(loginRedirectUri); } else if (operation.equalsIgnoreCase(\u0026quot;remove\u0026quot;)) { updatedRedirectUris.remove(loginRedirectUri); } // todo: update logout redirect URIs with redirectUri (not currently available in Java SDK) app.getSettings().getOAuthClient().setRedirectUris(Collections.toList(updatedRedirectUris)); app.update(); System.exit(0); } }  该类使用 Spring Boot 的 CLI(命令行接口)支持,这使得可以使用 Exec Maven 插件调用它。要添加对 Maven 运行它的支持,请在 holdings-api/pom.xml 进行以下修改 。\n\u0026lt;properties\u0026gt; ... \u0026lt;exec-maven-plugin.version\u0026gt;1.6.0\u0026lt;/exec-maven-plugin.version\u0026gt; \u0026lt;appId\u0026gt;default\u0026lt;/appId\u0026gt; \u0026lt;redirectUri\u0026gt;override-me\u0026lt;/redirectUri\u0026gt; \u0026lt;/properties\u0026gt; \u0026lt;!-- dependencies --\u0026gt; \u0026lt;build\u0026gt; \u0026lt;defaultGoal\u0026gt;spring-boot:run\u0026lt;/defaultGoal\u0026gt; \u0026lt;finalName\u0026gt;holdings-app-${project.version}\u0026lt;/finalName\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;!-- existing plugins --\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;org.codehaus.mojo\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;exec-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${exec-maven-plugin.version}\u0026lt;/version\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;add-redirect\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;java\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;/executions\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;mainClass\u0026gt;com.okta.developer.cli.AppRedirectUriManager\u0026lt;/mainClass\u0026gt; \u0026lt;classpathScope\u0026gt;test\u0026lt;/classpathScope\u0026gt; \u0026lt;arguments\u0026gt; \u0026lt;argument\u0026gt;appId ${appId} redirectUri ${redirectUri}\u0026lt;/argument\u0026gt; \u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/build\u0026gt;  然后更新 Jenkinsfile 以在构建镜像之后添加一段 mvn exec:java 供运行。\ndir ('./charts/preview') { container('maven') { sh \u0026quot;make preview\u0026quot; sh \u0026quot;make OKTA_CLIENT_TOKEN=\\$OKTA_CLIENT_TOKEN preview\u0026quot; sh \u0026quot;jx preview --app $APP_NAME --dir ../..\u0026quot; } } // Add redirect URI in Okta dir ('./holdings-api') { container('maven') { sh ''' yum install -y jq previewURL=$(jx get preview -o json|jq -r \u0026quot;.items[].spec | select (.previewGitInfo.name==\\\\\u0026quot;$CHANGE_ID\\\\\u0026quot;) | .previewGitInfo.applicationURL\u0026quot;) mvn exec:java@add-redirect -DappId=$OKTA_APP_ID -DredirectUri=$previewURL ''' } }  提交并推送你的更改,应用程序应该更新为 http://{yourPreviewURL}/login 的重定向 URI。你需要手动为 http://{yourPreviewURL} 添加一个注销重定向 URI, 因为 Okta 的 Java SDK 目前不支持此功能。\n要将你的 pull request 上传到演示环境,请将其合并,并将主分支推送到演示环境。不幸的是,你将无法登录。这是因为没有进程使用你的 Okta 应用程序注册登台站点的重定向 URI。如果手动添加 URI,一切都应该有效。\n在 Jenkins X 中运行 Protractor 测试 对我来说,弄清楚如何在 Jenkins X 中运行端到端测试是最难的。我首先添加了一个新的 Maven 配置文件,它允许我使用 Maven 而不是 npm 运行测试。\n注意:要使此配置文件起作用,你需要将 http://localhost:8000/login 登录重定向 URI 添加到你的应用程序,并将 http://localhost:8000 作为注销重定向URI。\n\u0026lt;profile\u0026gt; \u0026lt;id\u0026gt;e2e\u0026lt;/id\u0026gt; \u0026lt;properties\u0026gt; \u0026lt;!-- Hard-code port instead of using build-helper-maven-plugin. --\u0026gt; \u0026lt;!-- This way, you don't need to add a redirectUri to Okta app. --\u0026gt; \u0026lt;http.port\u0026gt;8000\u0026lt;/http.port\u0026gt; \u0026lt;/properties\u0026gt; \u0026lt;build\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;pre-integration-test\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;start\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;arguments\u0026gt; \u0026lt;argument\u0026gt;--server.port=${http.port}\u0026lt;/argument\u0026gt; \u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;post-integration-test\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;stop\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;/executions\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;com.github.eirslett\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;frontend-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;${frontend-maven-plugin.version}\u0026lt;/version\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;workingDirectory\u0026gt;../crypto-pwa\u0026lt;/workingDirectory\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;executions\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;webdriver update\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;npm\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;phase\u0026gt;pre-integration-test\u0026lt;/phase\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;arguments\u0026gt;run e2e-update\u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;execution\u0026gt; \u0026lt;id\u0026gt;ionic e2e\u0026lt;/id\u0026gt; \u0026lt;goals\u0026gt; \u0026lt;goal\u0026gt;npm\u0026lt;/goal\u0026gt; \u0026lt;/goals\u0026gt; \u0026lt;phase\u0026gt;integration-test\u0026lt;/phase\u0026gt; \u0026lt;configuration\u0026gt; \u0026lt;environmentVariables\u0026gt; \u0026lt;PORT\u0026gt;${http.port}\u0026lt;/PORT\u0026gt; \u0026lt;CI\u0026gt;true\u0026lt;/CI\u0026gt; \u0026lt;/environmentVariables\u0026gt; \u0026lt;arguments\u0026gt;run e2e-test\u0026lt;/arguments\u0026gt; \u0026lt;/configuration\u0026gt; \u0026lt;/execution\u0026gt; \u0026lt;/executions\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/build\u0026gt; \u0026lt;/profile\u0026gt;  提示:你可能会注意到,我必须为 e2e-update 和 e2e-test 分两次不同的执行。我发现运行 npm e2e 与 frontend-maven-plugin 不兼容,因为它只调用其他 npm run 命令。看来你需要在使用 frontend-maven-plugin 时直接调用二进制文件。\n这里使用的不是 TRAVIS 环境变量,而是 CI 变量。此更改需要更新 crypto-pwa/test/protractor.conf.js 来匹配。\nbaseUrl: (process.env.CI) ? 'http://localhost:' + process.env.PORT : 'http://localhost:8100',  进行这些更改,你应该能够运行 ./mvnw verify -Pprod,e2e 以在本地运行端到端测试。请注意,你需要将 E2E_USERNAME 和 E2E_PASSWORD 定义为环境变量。\n当我第一次在 Jenkins X 中尝试这个功能时,我发现 jenkins-maven 代理没有安装 Chrome。我发现很难安装并发现 jenkins-nodejs 预安装了 Chrome 和 Xvfb。当我第一次尝试它时,我遇到以下错误:\n[21:51:08] E/launcher - unknown error: DevToolsActivePort file doesn't exist  此错误是由 Chrome on Linux 问题引起的 。我发现解决办法是在 Protractor 的 chromeOptions 中指定 -disable-dev-shm-usage。我还添加了一些推荐的额外标志。我特别喜欢 --headless,在本地运行时,因此浏览器不会弹出并妨碍我。如果我想实时看到这个过程,我可以快速删除该选项。\n如果你希望在 Jenkins X 上看到项目的 Protractor 测试运行,则需要修改 crypto-pwa/test/protractor.conf.js 以指定以下内容 chromeOptions:\ncapabilities: { 'browserName': 'chrome', 'chromeOptions': { 'args': ['--headless', ''--disable-gpu', '--no-sandbox', '--disable-extensions', '--disable-dev-shm-usage'] } },  然后向 Jenkinsfile 添加一个新的 Run e2e tests 阶段,该阶段位于 “CI 构建”和“构建发布”阶段之间。如果有帮助,你可以看到最终的 Jenkins 文件。\nstage('Run e2e tests') { agent { label \u0026quot;jenkins-nodejs\u0026quot; } steps { container('nodejs') { sh ''' yum install -y jq previewURL=$(jx get preview -o json|jq -r \u0026quot;.items[].spec | select (.previewGitInfo.name==\\\\\u0026quot;$CHANGE_ID\\\\\u0026quot;) | .previewGitInfo.applicationURL\u0026quot;) cd crypto-pwa \u0026amp;\u0026amp; npm install --unsafe-perm \u0026amp;\u0026amp; npm run e2e-update Xvfb :99 \u0026amp; sleep 60s DISPLAY=:99 npm run e2e-test -- --baseUrl=$previewURL ''' } } }  完成所有这些更改后,创建一个新分支,签入你的更改,并在 GitHub 上创建一个 pull request。\ngit checkout -b enable-e2e-tests git add . git commit -m \u0026quot;Add stage for end-to-end tests\u0026quot; git push origin enable-e2e-tests  我确实需要做一些额外的调整才能通过所有的 Protractor 测试:\n 在 crypto-pwa/e2e/spec/login.e2e-spec.ts 中,我无法通过 should show a login button 测试,所以我忽略了它,将 it(…) 改为 xit(…)。 在同一个文件中,我将2000 ms 超时更改为5000 ms,将5000 ms 超时更改为30000 ms。 在 crypto-pwa/test/protractor.conf.js 中,我将 defaultTimeoutInterval 更改为 600000。 第一次运行时测试可能会失败,因为未为新预览环境配置注销重定向URI。更新 Okta 应用程序的注销重定向 URI 以匹配你的 PR 的预览环境 URI,重新 pull request 测试,一切都应该通过!  你可以在 GitHub 上的此示例中找到已完成应用程序的源代码 。\n了解有关 Jenkins X、Kubernetes 和 Spring Boot 的更多信息 要了解有关 Spring Boot、Jenkins X 和 Kubernetes 的更多信息,请查看以下资源:\n Deploy Your Secure Spring Boot + Angular PWA as a Single Artifact Build a Basic CRUD App with Angular 5.0 and Spring Boot 2.0 Introducing Jenkins X: a CI/CD solution for modern cloud applications on Kubernetes Kubernetes The Hard Way by Kelsey Hightower 如果你在 Kubernetes 上运行生产应用程序,我建议你研究 Jenkins X.它提供了一种在相同环境中进行 CI/CD 的方法,快速迭代并为你的客户更快地交付业务价值。  Jenkins X 还包括一个 DevPods 功能,可以在笔记本电脑上进行开发时,可以自动部署保存。我不确定 DevPods 是否适用于需要具有生产转换步骤的 JavaScript 应用程序。我宁愿让 webpack 和 Browsersync 在几秒钟内刷新我的本地浏览器,而不是等待几分钟创建并部署 Docker 镜像到 Kubernetes。\n要获得 Jenkins X 的精彩概述和演示,请观看 James Strachan 在2018年6月的 Virtual JUG 会议上为 Kubernetes 发布的 Jenkins X: Continuous Delivery。\n如果你有任何疑问,请在下面添加评论,在 Twitter 上发帖,或在我们的开发者论坛 上发帖提问。要获得有关未来博客文章和开发人员智慧的通知,你可以在Twitter上关注我的整个团队。\n使用 Jenkins X 和 Kubernetes 将 CI/CD 添加到 Spring Boot 应用程序中,最初于2018年7月11日发布到 Okta 开发人员博客。\n",
        "auhtor": "Matt Raible",
        "translator": "yJunS",
        "original": "https://dzone.com/articles/achieve-cicd-with-jenkins-x-kubernetes-and-spring",
        "poster": "../05/2019-05-24-achieve-cicd-with-jenkins-x-kubernetes-and-spring/cicd.jpg"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-23-chinese-localization/",
        "title": "Jenkins 中文本地化的重大进展",
        "type": "wechat",
        "date": "2019-05-23 00:00:00 +0000 UTC",
        "tags": [],
        "description": "Jenkins 中文社区大事件",
        "content": " 我从2017年开始,参与 Jenkins 社区贡献。作为一名新成员,翻译可能是帮助社区项目最简单的方法。 本地化的优化通常是较小的改动,你无需了解项目完整的上下文, 甚至都不需要在任务跟踪系统中添加任务。 但很快,就遇到了一些问题,那就是并没有以中文为母语的人帮助 review 我的 PR。因此,有时候, 我提交的 PR 过很久才能够被合并到 master 中。\n后来,有贡献者告诉我,可以在邮件列表中发一份邮件来描述当前遇到的问题,然后大家来讨论如何解决。 后来,我才了解到,在邮件列表中公开地讨论社区里的事情, 正是开源社区的做事风格。任何人都可以发表自己的观点, 我们并不受某个公司的限制,大家共同作出一致的决定。下面,我想与各位分享一下我们讨论后得出的一些成果。\nJEP-216 JEP 是 Jenkins Enhancement Proposoals 的缩写,也就是 Jenkins 增强提议。所有针对 Jenkins 社区的增强或者改进的想法都可以通过这样的一种 提议机制来推动,特别兴趣小组(SIG)就是其中的一项提议。JEP-216 是关于 改进本地化的一项提议。\n在之前,所有语言的本地化资源文件都是集中保存在 Jenkins Core 以及各个插件中的。而在 该提议中,每个语言都可以有一个单独的本地化插件,例如:简体中文插件。 终于,经过半年多的时间, 本地化支持插件和 简体中文插件已经可以支持各种类型的本地化资源文件(包括: Messages、属性以及帮助文件等)。从 插件网站上, 你可以看到 简体中文插件已经有超过1.3万的安装量,而且还在持续增长中。到目前为止,我们已经把 Jenkins Core 里所有简体中文的资源文件 迁移到了简体中文插件中,具体可以查看 PR-4008。\n我相信,这对于每一位 Jenkins 的中文用户都是一件意义重大的事情,Jenkins 中文社区也会努力带给大家带来更好的使用体验。当然, 我们欢迎并期待任何一位有志参与开源社区的朋友!\n在享受成果的同时,请与我一起感谢社区里为此作出重要贡献的朋友们。在 Daniel Beck 的帮助下,完成了“本地化支持插件”的发布; 在 Liam Newman 的帮助下完成了 JEP-216, 当然还包括社区中很多参与到中文本地化工作的贡献者。\n中文本地化特别兴趣小组 我们相信,这个特别兴趣小组能够给 Jenkins 的中文用户带来更好的使用体验,并聚集更多来自中国的贡献者。这里的贡献者,并不只是开发者的专利和特权, 实际上开源社区需要很多有不同技能的人加入,包括当不仅限于:测试、运维、文档工程师 甚至是设计师、市场运营等等。不管你是尚未毕业的在校学生, 还是懵懂初入职场,或者已经是具有多年丰富的从业经历,在这里 都是平等、公开的。\n该组会负责维护 Jenkins 官方中文站点,通过微信公众号在国内宣传和推广 Jenkins 社区及其技术。 我们会发布官方博客文章、实际案例、原创文章、Jenkins 版本发布,还有 Jenkins Meetup 或者其他的线上线下活动。 我们的官方公众号自半年前开通以来,已经有超过一千八百多位 Jenkins 的用户关注,并可以从这里及时获取最新的官方咨讯信息。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "“great-wall.jpeg”"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-22-jacoco-coverage-for-functional-test/",
        "title": "基于 Jenkins + JaCoCo 实现功能测试代码覆盖率统计",
        "type": "wechat",
        "date": "2019-05-22 00:00:00 +0000 UTC",
        "tags": ["jenkins", "jacoco", "ci", "coverage"],
        "description": "本文对 JaCoCo 进行简要介绍,并借助 Jenkins 实现功能测试代码覆盖率统计",
        "content": " 使用 JaCoCo 统计功能测试代码覆盖率? 对于 JaCoCo,有所了解但又不是很熟悉。 \u0026ldquo;有所了解\u0026rdquo;指的是在 CI 实践中已经使用 JaCoCo 对单元测试代码覆盖率统计: 当代码 push 到代码仓库后,用 JaCoCo 进行单元测试代码覆盖率统计,并将相应数据推送到 SonarQube。 \u0026ldquo;不是很熟\u0026rdquo;指的是应用场景也仅限于此,并未进行过多研究与实践。\n前不久,有测试同事提出,想要在实际测试时,用 JaCoCo 统计功能测试代码覆盖率。 其主要目的是在经过功能测试后,通过查看代码覆盖率统计的相关指标,增强对软件质量的信心。 经查阅资料,证明这是可行的。\n由于对 JaCoCo 不甚了解,于是查阅官网资料对 JaCoCo 进一步了解。\n进一步了解 JaCoCo JaCoCo,即 Java Code Coverage,是一款开源的 Java 代码覆盖率统计工具。 它由 EclEmma 团队根据多年来使用和集成现有库的经验教训而创建。\nJaCoCo 愿景 JaCoCo 应该为基于 Java VM 的环境中的代码覆盖率分析提供标准技术。 重点是提供一个轻量级的、灵活的、文档良好的库,以便与各种构建和开发工具集成。\nJaCoCo 产品功能  指令(C0)、分支(C1)、行、方法、类型和圈复杂度的覆盖率分析。 基于 Java 字节码,因此也可以在没有源文件的情况下工作。 通过基于 Java agent 的实时检测进行简单集成。其他集成场景(如自定义类加载器)也可以通过 API 实现。 框架无关性:平稳地与基于 Java VM 的应用程序集成,比如普通 Java 程序、OSGi 框架、web 容器或 EJB 服务器。 兼容所有已发布的 Java 类文件版本。 支持不同的 JVM 语言。 支持几种报告格式( HTML、XML、CSV )。 远程协议和 JMX 控件,以便在任何时间点从覆盖率 agent 请求执行数据 dump 。 Ant 任务,用于收集和管理执行数据并创建结构化覆盖报告。 Maven 插件,用于收集覆盖信息并在Maven构建中创建报告。  非功能特性  使用简单和与现有构建脚本和工具集成。 良好的性能和最小的运行时开销,特别是对大型项目。 轻量级实现,对外部库和系统资源的依赖性最小。 全面的文档。 完整文档化的 API ( JavaDoc ) 和用于与其他工具集成的示例。 回归测试基于 JUnit 测试用例,具有完整的功能测试覆盖率。  对 JaCoCo 可以与现有构建脚本和工具进行集成这里做进一步说明: 官方提供了 Java API、Java Agent 、CLI、Ant 、Maven、Eclipse 这几种集成方式; 第三方提供了诸如与 Gradle、IDEA、Jenkins 等其它工具的集成方式。\n抛开理论,开始实践 JaCoCo 不仅支持统计本地服务的代码覆盖率,也支持统计远程服务的代码覆盖率。 单元测试覆盖率统计就是统计本地服务的代码覆盖率,代码和运行的服务在一台机器上,笔者这里通过使用 JaCoCo Maven 插件完成的。 而功能测试代码覆盖率统计则是统计远程服务的代码覆盖率,代码和运行的服务一般不在一台机器上,这里需要借助 JaCoCo Java agent 实现。 \u0026gt; 备注:实际上,JaCoCo Maven 插件也使用了 JaCoCo Java agent,不过用户不需要直接关系 Java agent 及其选项,Maven 插件都透明地处理了。\n1、下载 JaCoCo 分发包 可以从 JaCoCo 官网下载分发包,也可以从 Maven 仓库(中央仓库或私服)下载。 分发包的 lib 目录下,包括以下库:\n2、Java 应用启动脚本添加 jacocoagent 相关 JVM 参数 需要将 jacocoagent.jar 推送到部署应用的服务器上,笔者这里用 Ansible 进行了批量推送。 Java 应用启动脚本需要加入类似下面的 JVM 参数:\nJAVA_OPTS=\u0026quot;$JAVA_OPTS -javaagent:/path/jacocoagent.jar=includes=*,output=tcpserver,append=false,address=$IP,port=$JACOCO_PORT\u0026quot;  这样在应用成功启动后,会暴露一个 TCP 服务,客户端可以连接到这个服务并获取执行数据文件。\n相关属性说明如下: - append:其中 append=false 表示 dump 每次会生成一个新的执行数据文件,如果 append=true,dump 时则会将数据追加到已存在的执行数据文件。 其中 output=tcpserver 表示 agent 监听来自被 adrress 和 port 属性指定的TCP 端口的连接,执行数据被写到这个连接; - output:如果 output=tcpclient 则表示在启动时,agent 连接到被 adrress 和 port 属性指定的TCP 端口,执行数据被写到这个连接; 如果 output=file 则表示在 JVM 终止时,执行数据被写到被 destfile 属性指定的文件。output 默认值为 file 。 - address:当 output 为 tcpserver 时绑定到的 IP 地址或主机名,或者当 output 为 tcpclient 时连接到的 IP 地址或主机名。 在 tcpserver 模式下,值为“*”导致代理只接受本机地址上的连接。address 默认值为 127.0.0.1 。 - port:当 output 方式为 tcpserver 时绑定到该端口,或者当 output 方式为 tcpclient 时连接到该端口。 在 tcpserver 模式下,端口必须可用,这意味着如果多个 JaCoCo agent 在同一台机器上运行,则必须指定不同的端口。port 默认值为 6300 。\n3、创建及配置 Jenkins Pipeline 任务 Jenkins 任务大致有几个步骤:拉取代码,构建,dump 应用执行数据( jacoco.exec ),解析 JaCoCo 产生的 jacoco.exec 文件,然后生成覆盖率报告(HTML 格式)。 拉取代码这里无需多说,配置下从代码仓库(SVN/Git)和分支地址就可以了,比较简单。 构建这里用了 Jenkins Pipeline Maven Integration Plugin ,笔者这里所用的 Maven 命令是 mvn clean package -Dmaven.test.skip=true 。 dump 应用执行数据这里有多种方式:Ant、CLI、Maven,因为Java 应用是用 Maven 构建的,这里选择了 Maven Jacoco Plugin。 解析 JaCoCo 产生的 jacoco.exec 文件,然后生成覆盖率报告(HTML 格式)笔者这里使用了 Jenkins Jacoco Plugin。\nJenkins Pipeline 案例如下:\npipeline { agent any tools { jdk 'JDK1.8' } stages { stage('Checkout'){ steps{ git branch: '${GIT_BRANCH}', credentialsId: 'xxx-xxx-xx-xx-xxx', url: '${GIT_URL}' } } stage('Build') { steps{ withMaven(maven: 'maven'){ sh \u0026quot;mvn clean package -Dmaven.test.skip=true\u0026quot; } } } stage('DumpFromServer'){ steps { withMaven(maven: 'maven'){ sh 'mvn org.jacoco:jacoco-maven-plugin:0.8.4:dump -Djacoco.address=${SERVER_IP} -Djacoco.port=${JACOCO_PORT}' } } } stage('JacocoPublisher') { steps { jacoco() } } } }  JaCoCo 覆盖率报告,部分截图如下:\n总结 笔者所实现的方式并未覆盖任何场景,但是大同小异,相关工具的使用详情可以查看官网文档,因为它是最全面的。 笔者希望这个实践能给有类似诉求的同行一些参考,当然笔者也希望能够和大家互相交流。 同时笔者的 JaCoCo 实践之路并未结束,可能在使用的过程中会有一些问题需要解决, 后续也将考虑使用 Jenkins API 为需要统计功能测试代码覆盖率的 Java 应用实例自动生成一个对应的 Jenkins 任务, 并在 Java 应用实例销毁后,对相应的 Jenkins 任务进行清理等其它功能。\n参考  https://www.eclemma.org/jacoco/index.html https://www.jacoco.org/jacoco/trunk/doc/integrations.html https://www.jacoco.org/jacoco/trunk/doc/agent.html https://www.jacoco.org/jacoco/trunk/doc/counters.html https://www.eclemma.org/jacoco/trunk/doc/mission.html  ",
        "auhtor": "donhui",
        "translator": "",
        "original": "",
        "poster": "“./2019-05-22-jacoco-coverage-for-functional-test/hangzhou.jpg”"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-20-jenkins-ansible-springboot/",
        "title": "使用 Jenkins + Ansible 实现 Spring Boot 自动化部署101",
        "type": "wechat",
        "date": "2019-05-20 00:00:00 +0000 UTC",
        "tags": ["jenkins", "ansible", "springboot"],
        "description": "实现 Spring Boot 最基本的流水线",
        "content": " 本文要点: 1. 设计一条 Spring Boot 最基本的流水线:包括构建、制品上传、部署。 1. 使用 Docker 容器运行构建逻辑。 1. 自动化整个实验环境:包括 Jenkins 的配置,Jenkins agent 的配置等。\n1. 代码仓库安排 本次实验涉及以下多个代码仓库:\n% tree -L 1 ├── 1-cd-platform # 实验环境相关代码 ├── 1-env-conf # 环境配置代码-实现配置独立 └── 1-springboot # Spring Boot 应用的代码及其部署代码  1-springboot 的目录结构如下:\n% cd 1-springboot % tree -L 1 ├── Jenkinsfile # 流水线代码 ├── README.md ├── deploy # 部署代码 ├── pom.xml └── src # 业务代码  所有代码,均放在 GitHub:https://github.com/cd-in-practice\n2. 实验环境准备 笔者使用 Docker Compose + Vagrant 进行实验。环境包括以下几个系统: * Jenkins * 1 Jenkins master,全自动安装插件、默认用户名密码:admin/admin。 * Jenkins agent * 2 Jenkins agent 运行在 Docker 容器中,共启动两个。 * Artifactory * 1 一个商业版的制品库。笔者申请了一个 30 天的商业版。\n使用 Vagrant 是为了启动虚拟机,用于部署 Spring Boot 应用。如果你的开发机器无法使用 Vagrant,使用 VirtualBox 也可以达到同样的效果。但是有一点需要注意,那就是网络。如果在虚拟机中要访问 Docker 容器内提供的服务,需要在 DNS 上或者 hosts 上做相应的调整。所有的虚拟机的镜像使用 Centos7。\n另,接下来笔者的所有教程都将使用 Artifactory 作为制品库。在此申明,笔者没有收 JFrog——研发 Artifactory 产品的公司——任何广告费。 笔者只是想试用商业产品,以便了解商业产品是如何应对制品管理问题的。\n启动 Artifactory 后,需要添加 “Virtual Repository” 及 “Local Repository”。具体请查看 Artifactory 的官方文档。如果你当前使用的是 Nexus,参考本教程,做一些调整,问题也不大。\n如果想使用已有制品库,可以修改 1-cd-platform 仓库中的 settings-docker.xml 文件,指向自己的制品库。\n实验环境近期的总体结构图如下:\n之所以说是“近期的”,是因为上图与本篇介绍的结构有小差异。本篇文章还没有介绍 Nginx 与 Springboot 配置共用,但是总体不影响读者理解。\n3. Springboot 应用流水线介绍 Springboot 流水线有两个阶段: 1. 构建并上传制品 2. 部署应用\n流水线的所有逻辑都写在 Jenkinsfile 文件。接下来,分别介绍这两个阶段。\n3.1 构建并上传制品 此阶段核心代码:\ndocker.image('jenkins-docker-maven:3.6.1-jdk8') .inside(\u0026quot;--network 1-cd-platform_cd-in-practice -v $HOME/.m2:/root/.m2\u0026quot;) { sh \u0026quot;\u0026quot;\u0026quot; mvn versions:set -DnewVersion=${APP_VERSION} mvn clean test package mvn deploy \u0026quot;\u0026quot;\u0026quot; }  它首先启动一个装有 Maven 的容器,然后在容器内执行编译、单元测试、发布制品的操作。\n而 mvn versions:set -DnewVersion=${APP_VERSION} 的作用是更改 pom.xml 文件中的版本。这样就可以实现每次提交对应一个版本的效果。\n3.2 部署应用  注意: 这部分需要一些 Ansible 的知识。\n 首先看部署脚本的入口 1-springboot/deploy/playbook.yaml:\n--- - hosts: \u0026quot;springboot\u0026quot; become: yes roles: - {\u0026quot;role\u0026quot;: \u0026quot;ansible-role-java\u0026quot;, \u0026quot;java_home\u0026quot;: \u0026quot;{{JAVA_HOME}}\u0026quot;} - springboot  先安装 JDK,再安装 Spring Boot。JDK 的安装,使用了现成 Ansible role: https://github.com/geerlingguy/ansible-role-java。\n重点在 Spring Boot 部署的核心逻辑。它主要包含以下几部分:\n 创建应用目录。 从制品库下载指定版本的制品。 生成 Systemd service 文件(实现服务化)。 启动服务。  以上步骤实现在 1-springboot/deploy/roles/springboot 中。\n流水线的部署阶段的核心代码如下:\ndocker.image('williamyeh/ansible:centos7').inside(\u0026quot;--network 1-cd-platform_cd-in-practice\u0026quot;) { checkout([$class: 'GitSCM', branches: [[name: \u0026quot;master\u0026quot;]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: \u0026quot;env-conf\u0026quot;]], submoduleCfg: [], userRemoteConfigs: [[url: \u0026quot;https://github.com/cd-in-practice/1-env-conf.git\u0026quot;]]]) sh \u0026quot;ls -al\u0026quot; sh \u0026quot;\u0026quot;\u0026quot; ansible-playbook --syntax-check deploy/playbook.yaml -i env-conf/dev ansible-playbook deploy/playbook.yaml -i env-conf/dev --extra-vars '{\u0026quot;app_version\u0026quot;: \u0026quot;${APP_VERSION}\u0026quot;}' \u0026quot;\u0026quot;\u0026quot; }  它首先将配置变量仓库的代码 clone 下来,然后对 playbook 进行语法上的检查,最后执行 ansible-playbook 命令进行部署。--extra-vars 参数的 app_version 用于指定将要部署的应用的版本。\n3.3 实现简易指定版本部署 在 1-springboot/Jenkinsfile 中实现了简易的指定版本部署。核心代码如下: 1. 流水线接受参数\nparameters { string(name: 'SPECIFIC_APP_VERSION', defaultValue: '', description: '') }   如果指定了版本,则跳过构建阶段,直接执行部署阶段 groovy stage(\u0026quot;build and upload\u0026quot;){ // 如果不指定部署版本,则执行构建 when { expression{ return params.SPECIFIC_APP_VERSION == \u0026quot;\u0026quot; } } // 构建并上传制品的逻辑 steps{...} }  之所以说是“简易”,是因为部署时只指定了制品的版本,并没有指定的部署逻辑和配置的版本。这三者的版本要同步,部署才真正做到准确。  4. 配置管理 所有的配置项都放在 1-env-conf 仓库中。Ansible 执行部署时会读取此仓库的配置。\n将配置放在 Git 仓库中有两个好处: 1. 配置版本化。 2. 任何配置的更改都可以被审查。\n有好处并不代表没有成本。那就是开发人员必须开始关心软件的配置(笔者发现不少开发者忽视配置项管理的重要性。)。\n本文重点不在配置管理,后面会有文章重点介绍。\n5. 实验环境详细介绍 事实上,整个实验,工作量大的地方有两处:一是 Spring Boot 流水线本身的设计;二是整个实验环境的自动化。读者朋友之所以能一两条简单的命令就能启动整个实验环境,是因为笔者做了很多自动化的工作。笔者认为有必要在本篇介绍这些工作。接下来的文章将不再详细介绍。\n5.1 解决流水线中启动的 Docker 容器无法访问 http://artifactory 流水线中,我们需要将制品上传到 artifactory(settings.xml 配置的仓库地址是 http://artifactory:8081),但是发现无法解析 host。这是因为流水线中的 Docker 容器所在网络与 Docker compose 创建的网络不同。所以,解决办法就是让流水线中的 Docker 容器加入到 Docker compose 的网络。\n具体解决办法就是在启动容器时,加入参数:--network 1-cd-platform_cd-in-practice\n5.2 Jenkins 初次启动初始化 在没有做任何设置的情况启动 Jenkins,会出现一个配置向导。这个过程必须是手工的。笔者希望这一步也是自动化的。Jenkins 启动时会执行 init.groovy.d/目录下的 Groovy 脚本。\n5.3 虚拟机中如何能访问到 http://artifactory ? http://artifactory 部署在 Docker 容器中。Spring Boot 应用的制品要部署到虚拟机中,需要从 http://artifactory 中拉取制品,也就是要在虚拟机里访问容器里提供的服务。虚拟机与容器之间的网络是不通的。那怎么办呢?笔者的解决方案是使用宿主机的 IP 做中转。具体做法就是在虚拟机中加一条 host 记录:\nmachine.vm.provision \u0026quot;shell\u0026quot; do |s| s.inline = \u0026quot;echo '192.168.52.1 artifactory' \u0026gt;\u0026gt; /etc/hosts\u0026quot; end  以上是使用了 Vagrant 的 provision 技术,在执行命令 vagrant up 启动虚拟机时,就自动执行那段内联 shell。192.168.52.1 是虚拟宿主机的 IP。所以,虚拟机里访问 http://artifactory:8081 时,实际上访问的是 http://192.168.52.1:8081。\n网络结构可以总结为下图:\n后记 目前遗留问题: 1. 部署时制品版本、配置版本、部署代码版本没有同步。 2. Springboot 的配置是写死在制品中的,没有实现制品与配置项的分离。\n这些遗留问题在后期会逐个解决。就像现实一样,经常需要面对各种遗留项目的遗留问题。\n附录  使用 Jenkins + Ansible 实现自动化部署 Nginx:https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-25-jenkins-ansible-nginx/ 简单易懂 Ansible 系列 —— 解决了什么:https://showme.codes/2017-06-12/ansible-introduce/  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": "../../../images/articles/2019/05/2019-05-20-jenkins-ansible-springboot/poster.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-20-translation-norms/",
        "title": "转载规范及声明",
        "type": "wechat",
        "date": "2019-05-20 00:00:00 +0000 UTC",
        "tags": ["spec"],
        "description": "为了保护本站文章的原创性,请规范转载,违者必究",
        "content": " 转载声明 首先感谢大家对 Jenkins 中文社区内容的认可。传播有道,我们希望每一篇文章的发声不仅能被看见,也都能得到尊重。因此,若需转载本社区的文章,请先获取本社区授权,未经授权禁止转载。如未经许可私自转载,我们会有专人负责沟通进行整改,对于不听劝解的将会被添加到社区官网的黑名单中以作公示。\n如需转载,请仔细阅读并遵守以下转载须知: 1. 本站发文均于Jenkins 中文社区首发,然后由微信公众号、CSDN、简书、开源中国、掘金等渠道发出 2. 不论通过何种渠道获得本站文章,若想要转载,均可在文章下方留言,获得授权后方可进行在转载 3. 文章转载首行,需添加本文转自 [Jenkins 中文社区],Jenkins 中文社区需加入链接 http://jenkins-zh.cn 4. 转载文章标题不得进行修改 5. 转载文章内容不得做任何修改,如有文章内容问题,请与本社区相关联系人沟通后,再进行下一步处理 6. 为了保护作者权益,作者署名必须保留 7. 如是微信公众号转载,请在获得授权的情况下,使用微信的转载功能进行转载 8. 文章在推送三天后方可进行转载\n",
        "auhtor": "yJunS",
        "translator": "",
        "original": "",
        "poster": "./2019-05-20-translation-norms/banquan.jpg"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-17-from-jenkins-to-jenkins-x/",
        "title": "从 Jenkins 到 Jenkins X",
        "type": "wechat",
        "date": "2019-05-17 00:00:00 +0000 UTC",
        "tags": ["jenkins", "jenkins x", "kubernetes", "devops", "ci", "cd"],
        "description": "这是一个关于 dailymotion 从 Jenkins 到 Jenkins X 的旅程,我们遇到的问题,以及我们是如何解决它们的故事",
        "content": " 这是一个关于 dailymotion 从 Jenkins 到 Jenkins X 的旅程,我们遇到的问题,以及我们是如何解决它们的故事。\n我们的上下文 在 dailymotion ,我们坚信 devops 最佳实践,并且在 Kubernetes 投入了大量投资。 我们的部分产品已经部署在 Kubernetes 上,但并不是全部。 因此,当迁移我们的广告技术平台的时候,我们想要完全采用“ Kubernetes 式”——或者云原生,以追随技术趋势! 这意味着要重新定义整个 CI/CD 流水线,从静态/永久环境迁移,转向动态按需分配环境。 我们的目标是授权给我们的开发人员,缩短我们的上线时间以及降低我们的运营成本。\n对于新的 CI/CD 平台我们的初始需求是: - 尽可能避免从零开始:我们的开发人员已经习惯使用 Jenkins 和声明式流水线,并且它们可以很好地满足我们当前的需求。 - 以公有云基础设施为目标——Google 云平台和 Kubernetes 集群 - 与 gitops 方法论兼容——因为我们喜欢版本控制、同行评审和自动化\n在 CI/CD 生态系统中有相当多的参与者,但是只有一个符合我们的需求,Jenkins X ,它基于 Jenkins 和 Kubernetes ,原生支持预览环境和 gitops\nKubernetes 之上的 Jenkins Jenkins X 的设置相当简单,并且在他们的官方网站上已经有很好的文档(译注:译者曾对 Jenkins X 文档中文本地化做了一些贡献,同时也期待更多的人参与以完善中文文档)。 由于我们已经使用了 Google Kubernetes Engine (GKE),所以 jx 命令行工具自己创建了所有东西,包括 Kubernetes 集群。 这里有一个小小的*哇哦效果*,在几分钟内获得一个完整的工作系统是非常令人印象深刻的。\nJenkins X 提供了很多快速入门和模板来增加*哇哦效果*, 然而,在 dailymotion ,我们已经有了带有 Jenkins 流水线的仓库,我们想要重用它们。 我们决定以\u0026rdquo;艰难的方式\u0026rdquo;做事情,并重构我们的声明式流水线,使它们与 Jenkins X 兼容。\n实际上,这一部分并不针对 Jenkins X ,而是基于 Kubernetes 插件在 Kubernetes 上运行 Jenkins 。 如果您习惯使用“经典的” Jenkins ,即在裸金属或虚拟机上运行静态代理,那么这里的主要更改是,每次构建都将在自己的短暂的 pod 上执行。 流水线的每个步骤都可以指定应该在 pod 的哪个容器上执行。 在插件的源代码中有一些流水线的例子。 在这里,我们的\u0026rdquo;挑战\u0026rdquo;是定义容器的粒度,以及它们将包含哪些工具:需要足够的容器,以便我们可以在不同流水线之间重用它们的镜像,但也不能太多,以控制维护量——我们不想花时间重新构建容器镜像。\n以前,我们通常在 Docker 容器中运行大多数流水线步骤,当我们需要自定义步骤时,我们在运行中的流水线中构建它,就在运行它之前。 虽然它比较慢,但是易于维护,因为所有内容都是在源代码中定义的。 例如,升级 Go 运行时的版本可以在一个 pull-request 中完成。 因此,要预先构建容器镜像听起来像是给现有设置增加了更多的复杂性。 它还有几个优点:仓库之间的重复更少,构建速度更快,并且不会因为某些第三方托管平台宕机而出现更多构建错误。\n在 Kubernetes 上构建镜像 这些天将给我们带来一个有趣的话题:在 Kubernetes 集群中构建容器镜像。\nJenkins X 附带了一组\u0026rdquo;构建打包\u0026rdquo;,使用 \u0026ldquo;Docker in Docker\u0026rdquo; 从容器内部构建镜像。 但是随着新的容器运行时的到来,Kubernetes 推出了它的容器运行时接口( CRI ),我们想要探索其他的选择。 Kaniko 是最成熟的解决方案,符合我们的需求/技术栈。 我们很兴奋……\n……直到我们遇到两个问题: - 第一个问题对我们来说是一个阻塞问题:多阶段构建不起作用。 多亏了谷歌,我们很快发现我们不是唯一受到影响的人,而且目前还没有解决办法。 然而,Kaniko 是用 Go 开发的,而我们是 Go 开发人员,所以……为什么不看看源代码呢? 事实证明,一旦我们理解了问题的根本原因,修复就很容易了。 Kaniko 维护者是很愿意帮忙的,并且快速地合并了修复,所以一天之后一个被修复的 Kaniko 镜像就已经可用了。 - 第二个问题是,我们不能使用同一个 Kaniko 容器构建两个不同的镜像。 这是因为 Jenkins 并没有按照预期的方式使用 Kaniko ——因为我们需要先启动容器,然后再运行构建。 这一次,我们找到了一个针对谷歌的解决方案:声明我们所需要的尽可能多的 Kaniko 容器来构建镜像,但是我们不喜欢它。 所以回到源代码,再一次,一旦我们理解了根本原因,修复就很容易了。\n我们测试了一些解决方案来为 CI 流水线构建定制的\u0026rdquo;工具\u0026rdquo;镜像, 最后,我们选择使用一个单个仓库,每个分支对应一个 Dockerfile 和镜像。 因为我们将源代码托管在 Github 上,并且使用 Jenkins Github 插件来构建我们的仓库, 所以它可以构建我们所有的分支,并为 webhook 事件上的新分支创建新的任务,这使得管理起来很容易。 每个分支都有自己的 Jenkinsfile 声明式流水线,使用 Kaniko 构建镜像,并将其推入我们的容器注册中心。 这对于快速添加新镜像或编辑现有的镜像非常有用,因为我们知道 Jenkins 会处理好所有的事情。\n声明所需资源的重要性 我们在之前的 Jenkins 平台中遇到的一个主要问题来自静态的代理/执行器,在高峰时间有时构建队列很长。 Kubernetes 之上的 Jenkins 使这个问题很容易解决,主要是在 Kubernetes 集群上运行时,它能支持集群自动伸缩。 集群将根据当前负载简单地添加或删除节点。 但这是基于所请求的资源,而不是基于所观察到的使用的资源。 这意味着,作为开发人员,我们的工作是在构建 pod 模板中定义所需的资源( CPU 和内存)。 然后 Kubernetes 调度程序将使用此信息找到一个匹配的节点来运行 pod ——或者它可能决定创建一个新的节点。 这真是太好了,因为我们不再有长构建队列。 但相反,我们需要谨慎地定义我们所需资源的恰当数量,并在更新流水线时更新它们。 由于资源是在容器级别定义的,而不是在 pod 级别定义的,所以处理起来有点复杂。 但是我们不关心限制,只关心请求。 pod 的请求只是所有容器请求的相加。 因此,我们只是将整个 pod 的资源请求写在第一个容器上——或者 jnlp 容器上——它是默认的容器。 下面是我们使用的一个 Jenkinsfile 的例子, 也是我们如何声明请求的资源的例子:\npipeline { agent { kubernetes { label 'xxx-builder' yaml \u0026quot;\u0026quot;\u0026quot; kind: Pod metadata: name: xxx-builder spec: containers: - name: jnlp  Jenkins X 上的预览环境 现在我们已经拥有了所有的工具,并且能够为我们的应用程序构建一个镜像, 我们准备下一步:将它部署到\u0026rdquo;预览环境\u0026rdquo;!\nJenkins X 通过重用现有的工具——主要是 Helm ,使得部署预览环境变得很容易, 只要你遵循一些约定,例如用于镜像标签的值的名称。 最好是从\u0026rdquo;包\u0026rdquo;中提供的 Helm charts 复制/粘贴。 如果你不熟悉 Helm ,它基本上是一个 Kubernetes 应用程序包管理器。 每个应用程序都打包为一个 \u0026ldquo;chart\u0026rdquo; ,然后可以通过使用 helm 命令行工具作为一个 \u0026ldquo;release\u0026rdquo; 被部署。 预览环境是通过使用 jx 命令行工具进行部署的,该工具负责部署 Helm chart ,并以评论的形式,将所公开服务的 URL 添加到 Github pull-request 中。 这一切都非常好,而且对于我们第一个使用纯 http 的 POC 来说很有效。 但现在是2018年(译注:作者是在2018年写的这篇文章),没有人再使用 http 了。 让我们加密吧! 多亏了 cert-manager,当在 kubernetes 中创建 ingress 资源时,我们可以自动为我们的新域名获得一个 SSL 证书。 我们试图在我们的设置中启用 tls-acme 标志——与 cert-manager 进行绑定,但是它不起作用。 这给了我们一个机会来看看 Jenkins X 的源代码——它也是用 Go 开发的。 稍作修复之后都好了, 现在我们可以使用 let\u0026rsquo;s encrypt 提供的自动化证书来享受安全的预览环境。\n我们在预览环境中遇到的另一个问题与上述环境的清理有关。 每个打开一个 pull-request ,就创建一个预览环境,因此在 pull-request 被合并或关闭时应该删除预览环境。 这由 Jenkins X 设置的 Kubernetes 任务来处理,它删除了预览环境所使用的名称空间。 问题是这个任务不会删除 Helm release ——所以,比如如果您运行 helm list,您仍然会看到一个很大的旧的预览环境列表。 对于这个问题,我们决定改变使用 Helm 部署预览环境的方式。 Jenkins X 团队已经写过关于 Helm 和 Tiller ( Helm 的服务器端组件)的这些问题, 因此,我们决定使用 helmTemplate 特性标志,只使用 Helm 作为模板渲染引擎,并使用 kubectl 处理生成的资源。 这样,我们就不会用临时预览环境\u0026rdquo;污染\u0026rdquo; Helm releases 列表。\nGitops 应用到 Jenkins X 在初始化 POC 的某个阶段,我们对我们的设置和流水线感到满意,并希望将我们的 POC 平台转变为准生产的平台。 第一步是安装 SAML 插件以设置 OKTA 集成——以允许内部用户登录。 它运行得很好,几天后,我注意到我们的 OKTA 集成已经不再存在了。 我正忙着做其他事情,所以我只是问我的同事他是否做了一些改变,然后继续做其他事情。 但几天后再次发生时,我开始调查。 我注意到的第一件事是 Jenkins Pod 最近重新启动过。 但是我们有一个持久化的存储,我们的任务仍然在那里,所以是时候仔细看看了! 事实证明,用于安装 Jenkins 的 Helm chart 有一个启动脚本, 它从 Kubernetes configmap 重置了 Jenkins 配置。 当然,我们不能像在虚拟机上管理 Jenkins 那样管理在 Kubernetes 中运行的 Jenkins !\n因此,我们没有手动编辑 configmap ,而是后退一步,查看全局。 这个 configmap 本身由 jenkins-x-platform 管理, 因此升级平台将重置我们的自定义更改。 我们需要将我们的\u0026rdquo;定制\u0026rdquo;存储在安全的地方并跟踪我们的更改。 我们可以用 Jenkins X 的方式,用一个 umbrella chart 来安装/配置一切, 但是这种方法有一些缺点:它不支持 \u0026ldquo;secret\u0026rdquo; —— 我们将一些敏感的值存储在我们的 Git 仓库中—— 它\u0026rdquo;隐藏\u0026rdquo;了所有的 sub-charts 。 所以,如果我们列出所有已安装的 Helm releases ,我们将只看到一个。 但是还有其他基于 Helm 的工具,它们更对 Gitops 更友好。 Helmfile 就是其中之一,它通过 helm secrets 插件和 sops为 secrets 提供了原生支持。 我现在不会详细介绍我们的设置,但别担心,这将是我下一篇博客文章的主题!\n迁移 我们故事的另一个有趣的部分是从 Jenkins 到 Jenkins X 的实际迁移。 以及我们如何使用两个构建系统处理仓库。 首先,我们设置新的 Jenkins 来只构建 \u0026ldquo;jenkinsx\u0026rdquo; 分支, 并且更新了旧的 Jenkins 的配置来构建除 \u0026ldquo;jenkinsx\u0026rdquo; 分支之外的所有分支。 我们计划在 \u0026ldquo;jenkinsx\u0026rdquo; 分支中准备新的流水线,并将其合并以进行迁移。 对于我们的初始化 POC ,它工作得很好,但是当我们开始使用预览环境时, 我们必须创建新的 PR ,而这些 PR 不是基于新的 Jenkins 构建的,因为分支限制。 因此,我们选择在这两个 Jenkins 实例上构建一切, 但对于旧的 Jenkins 使用 Jenkinsfile 文件名,对于新的 Jenkins 使用 Jenkinsxfile 文件名。 迁移之后,我们将更新此配置并重命名文件,但这是值得的, 因为它使我们能够在两个系统之间进行平滑的转换,并且每个项目都可以自己迁移,而不会影响其他项目。\n我们的目的地 所以,Jenkins X 为大家准备好了吗?老实说,我不这么认为。 并非所有功能和所支持的平台—— Git 托管平台或 Kubernetes 托管平台——都足够稳定。 但是,如果您准备投入足够的时间来深入研究,并选择适合您的使用场景的稳定特性和平台, 那么您将能够使用 CI/CD 等所需的一切来改进您的流水线。 这将缩短您的上线时间,降低您的成本,如果您对测试也很认真,那么请对您的软件质量充满信心。\n一开始,我们说这是我们从 Jenkins 到 Jenkins X 的旅程。但我们的旅程并未结束,我们还在旅行中。 部分原因是我们的目标仍在移动:Jenkins X 仍处于大的发展阶段,而且它本身正在朝着 Serverless 的方向前进, 目前正在使用 Knative 构建 的路上。 它的目的地是云原生 Jenkins 。 它还没有准备好,但是您已经可以预览它的外观了。\n我们的旅程还将继续,因为我们不希望它结束。 我们现在的目的地并不是我们的最终目的地,而是我们不断进化的一个步骤。 这就是我们喜欢 Jenkins X 的原因:因为它遵循相同的模式。 那么,你在等待什么来开始你自己的旅程呢?\n 译注:译者曾对 Jenkins X 文档中文本地化做了一些贡献,同时也期待更多的人在 Jenkins X 旅程中, 能够参与到 Jenkins 中文社区以完善 Jenkins X 的中文文档。\n ",
        "auhtor": "Vincent Behar",
        "translator": "donhui",
        "original": "https://medium.com/dailymotion/from-jenkins-to-jenkins-x-604b6cde0ce3",
        "poster": "“./2019-05-20-from-jenkins-to-jenkins-x/journey.jpeg”"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
119
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
120
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-16-cloud-agnostic-automated-cicd-for-k8s/",
LinuxSuRen's avatar
LinuxSuRen 已提交
121 122 123 124 125 126 127 128 129 130 131
        "title": "与云无关的用于 Kubernetes 的自动化 CI/CD ",
        "type": "wechat",
        "date": "2019-05-16 00:00:00 +0000 UTC",
        "tags": ["cd", "ci", "kubernetes"],
        "description": "请看看您可能想要用来设置与云无关的生产和开发环境的一些工具和流程。",
        "content": " 在本文中,我想讨论一种在云环境中为 Kubernetes 工作负载实现自动化端到端 CI/CD 的方法。 这里可能有其它解决方案,而像 AWS、Microsoft Azure 和 GCP 这样的云提供商也提供了自己的一套框架,以实现与 Kubernetes 相同的目标。\n它的部署模型的核心是 Rancher,Rancher 负责为托管在不同云环境和裸机环境中的多个 Kubernetes 集群提供集中管理与运营的能力。 根据应用程序和业务需要,这里提到的工具可以替换为自己选择的工具。\n在详细介绍之前,这里有张部署模型的快照:\n持续集成组件 我们使用 JIRA、BitBucket、Bamboo 和 Nexus 作为自动化持续集成组件。 需求和用户故事来自 JIRA ; 开发人员将他们的代码放进 BitBucket ; 代码被代码评审工具和静态分析工具构建与集成,Bamboo 生成的 Docker 镜像被推送到 Nexus。 这些镜像会经过特定的容器安全检查。\n当你有许多微服务/应用程序需要构建时,那么处理 Kubernetes 集群工作负载的部署、升级和回滚可能会复杂。 版本控制是我们需要考虑的另一个挑战。 Helm 有助于克服这些大多数挑战,并使部署变得简单。\n如果你想知道你是否需要有一个 chart 将所有 deployments 包含在其中, 或者允许每个应用程序和微服务都有一个单独的 chart , 那么我们希望将这些 charts 放到特定的应用程序或微服务的仓库中, 这样我们就不需要有单独的仓库来维护 Helm 制品。 这就省去了为实际的代码和 Helm 模板维护两个独立仓库的工作。 开发人员可以对任何应用程序代码更改所需的模板更改有更多的控制权。\nNexus 作为 Docker 镜像和 Helm chart(使用的是 Helm Nexus 插件)的仓库。 每次成功构建应用程序后,镜像和 chart 都是可用的并被推送到 Nexus 。\n持续部署组件 为了实现与云无关的准备,我们选择了 Terraform ,因为它易于学习并易于部署。 我们发现对于准备后的配置管理/维护活动, Terraform 并不是非常有用,所以我们还放置了一些 Ansible 脚本。 我们也曾考虑 Ansible 用于准备,但是使用 Terraform 可以让我们更好地控制启动实例, 这些实例可以作为 Rancher Server/节点,并且可以被自动的添加到自动伸缩组中。 我们使用启动脚本功能实现了这一点。\n我们认为可以将为 AWS 编写的大多数 Terraform 脚本重用到 Azure 中,但事实并非如此。 我们必须做出相当大的改变。\n我们部署了一个运行在三个不同实例上的高可用的 Rancher Server ,前面有一个 NGINX Server 来为这三个实例做负载均衡。 部署是使用 Terraform 和启动脚本完成的。 脚本使用 RKE ( Rancher Kubenetes 引擎)和 Rancher API 调用来启动集群(高可用的 Rancher Server )。\nRancher 提供了各种选项来在不同的云提供商上添加 Kubernetes 集群。 您可以从选项中进行选择,使用托管的 Kubernetes 提供商,或者使用基础设施提供商的节点或自定义节点。 在这个场景中,我们选择使用 AWS 和 Azure 上的自定义节点,而不是托管的 Kubernetes 提供商。 这帮助我们向自动伸缩组添加一组工作节点,并使用集群自动伸缩器进行节点伸缩。\n所有这些都是通过启动脚本和 Rancher API 调用自动完成的,因此任何通过 ASG (和自动伸缩器)添加的新节点都会自动注册为一个 Rancher/Kubernetes 节点。 通过启动脚本自动执行的一些活动包括: - 安装和配置所需的 Docker 版本 - 在所有实例上安装和配置 Zabbix 代理(稍后将在监控中使用) - 安装所需的 GlusterFS 客户端组件 - 安装所需的 kubectl 客户端 - 后端数据库集群所需的任何其他自定义配置 - 自动挂载额外的 EBS 卷和 GlusterFS 卷 - 为 Rancher 代理/Kubernetes 节点运行 Docker 容器并附加特定的角色( etcd/controlplane/worker ) - 检查以确保 Rancher 代理可用、启动和运行。\nGlusterFS 被考虑可以处理 EBS 和 Azure 中不可用的 ReadWriteMany 磁盘卷类型。 这对于我们部署的许多应用程序都是必需的。\n一个 ELK stack ( ElasticSearch、Logstash 和 Kibana )使用 Helm charts 部署在 Kubernetes 上, 并被配置为通过 logstash 推送容器日志、审计和其他自定义日志。\nHAProxy 和 NGINX 被用于两个不同的目的。 NGINX 是在 Rancher Server HA 设置期间所提供的默认 ingress controller 。 这用于三个 Rancher Server 的负载均衡。 我们在 Kubernetes 集群上部署了一个 HAProxy Ingress Controller, 这样我们就可以通过这些特定的节点(其 IPs 映射到特定的 FQDNs)暴露应用程序的 end points 。 HAProxy ingress controller 被部署为 daemonset ,因此对于任何额外的负载,节点的数量会基于自动伸缩组和自动伸缩器自动增加。\n持续监控组件 我们部署了 Prometheus、Grafana 和 Alertmanager 套件,用于容量规划以及监控 Rancher/Kubernetes 集群的状态。 这再次通过 Rancher Helm Chart Provisioner 部署。 我们也可以通过常规的/稳定的 Helm charts 来部署它。 它确实有助于我们监控和收集开发环境中诸如 CPU、内存利用率和 IO 操作之类的指标,并据此为 staging 环境和生产环境进行容量规划。\n我们还在集群上部署了 Zabbix Server,它用于为部署的所有节点监控各种操作系统级别的和应用程序特定的指标和警告。 这包括任何后端数据库集群节点、Kubernetes 节点、Rancher servers、文件服务器或通过 Terraform 提供的任何其他服务器。 Zabbix Server 被配置为节点/代理自动注册,以便通过自动缩放组或自动缩放器添加到集群中的任何新节点都可用于监控。\n结论 这是我们为 Kubernetes 工作负载构建完整的 CI/CD 工具链所遵循的方法之一。 这个模型帮助我们自动化所有的三个环境的准备。 通过 Rancher ,我们能够提供一个开发环境,每个开发人员都可以使用这个项目概念。 每个开发人员都有一个节点和一个项目,它由 RBAC 控制,这样他们就可以部署和测试他们自己的更改。 没有人可以看到项目/节点的详细信息,也不会妨碍其他开发人员部署的 Kubernetes 工作负载。 由于节点自动注册到 Rancher Server,系统重新启动不会影响节点的可用性。 即使在最坏的情况下,如果节点丢失,也很容易在几分钟内打开一个新节点。 应用程序可以使用 Helm charts 进行部署,也可以使用 Rancher 提供的内置的 Helm charts 进行部署。\n这些是我们部署的来管理整个环境的一些高级组件。 我们考虑的其他方面是高可用性集群环境,用于 Rancher servers、Kubernetes 集群、Gluster 文件服务器集群或任何其他后端集群。 在提出此方法时,需要考虑生产级环境所需的更改和更新。 还考虑了其他方面,例如对集群实例的安全访问、升级、备份和恢复,以及根据行业标准提出的分层体系结构建议。\n希望本文为您提供一些参考,当您计划为多个云提供商提供生产级环境准备时,可以考虑这些参考。\n",
        "auhtor": "Ravi Sarma Kasibhatla",
        "translator": "donhui",
        "original": "https://dzone.com/articles/cloud-agnostic-automated-cicd-for-k8s",
        "poster": "../../../images/articles/2019/04/2019-05-16-cloud-agnostic-automated-cicd-for-k8s/blue.jpg"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
132 133 134 135 136 137 138
    {
        "uri": "https://jenkins-zh.cn/about/plugins/",
        "title": "插件列表",
        "type": "about",
        "date": "2019-05-15 20:30:05 +0800 +0800",
        "tags": [],
        "description": "Jenkins 中文社区维护的插件",
LinuxSuRen's avatar
LinuxSuRen 已提交
139
        "content": "下面的列表是由 Jenkins 中文社区的成员维护的插件:\n   插件 GitHub 仓库 版本 安装量 主要维护者     Simplified Chinese Plugin jenkinsci/localization-zh-cn-plugin    LinuxSuRen    Hugo Plugin jenkinsci/hugo-plugin    LinuxSuRen    Maven SNAPSHOT Check Plugin jenkinsci/maven-snapshot-check-plugin    donhui    Code Coverage API Plugin jenkinsci/code-coverage-api-plugin    cizezsy    WeiBo Plugin jenkinsci/weibo-plugin    LinuxSuRen     同时也期待有更多的贡献者增砖添瓦。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
140 141 142 143 144
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
145
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
146 147
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-15-gsoc-annoncement/",
        "title": "19年 GSoC 中 Jenkins 的七个项目",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
148
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
149 150 151 152 153
        "date": "2019-05-15 00:00:00 +0000 UTC",
        "tags": ["jenkins", "release"],
        "description": "Jenkins 社区在 Google Summer of Code 中的项目",
        "content": "Google Summer of Code (GSoC) 项目是一个年度性的全球化活动,该项目旨在鼓励高校学生在暑假期间参与到开源项目中来。\n通过审核的学生会收到由 Google 提供的带薪工作,参与到设计好的项目中以改进或提升 Jenkins 项目。作为回报,数名 Jenkins 社区成员会志愿作为学生“导师”来帮助他们融入开源社区并成功完成他们的夏令营项目。\nJenkins 社区从2009年开始以开源社区的身份参与到 GSoC 中,并分别在16年有5个项目、18年有3个项目被选中。 而今年的项目、导师的数量是最多的一年,相信在这个夏天里,Jenkins 社区可以给我们的用户带来很多不错的 成果,其中也许正有你或者你们团队所希望有的功能或者改进。\n2019年被选中的七个项目包括:\n 支持制品升级的流水线插件 基于云的外部工作空间管理器插件 多分支流水线对 Gitlab 的支持 插件安装管理器的 CLI 工具以及库 基于 Apache Kafka 以及 Kubernetes 的远程协议 基于角色策略的插件的改进 时间窗口插件——UI 改进  上面的每个项目都有一位学生主导进行,至少两位具有相关经验的导师加以指导,每周会有两次的同步会议来 保证方向与进度。当然,在开源社区里任何人都可以通过 PR 的形式对代码或者文档进行 Review。\n今年负责 GSoC 的管理员为:\n Martin d’Anjou Jeff Pearce Lloyd Chang Oleg Nenashev  我本人是“多分支流水线对 Gitlab 的支持”项目的领队导师,请大家与我一起期待这七位高校学生的精彩表现,后续社区也会及时发布上面项目的介绍以及进展。\n",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
154 155
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
156
        "poster": "“../../../images/gsoc/gsoc-big-logo.jpeg”"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
157 158 159 160 161 162 163 164 165 166 167 168
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-14-devops-jenkins-credential-manage/",
        "title": "基于 Jenkins 的 DevOps 平台应该如何设计凭证管理",
        "type": "wechat",
        "date": "2019-05-14 00:00:00 +0000 UTC",
        "tags": ["jenkins", "devops"],
        "description": "一种基于 Jenkins 的 DevOps 平台建设思路",
        "content": " 背景 了解到行业内有些团队是基于 Jenkins 开发 DevOps 平台。而基于 Jenkins 实现的 DevOps 平台,就不得不考虑凭证的管理问题。\n本文就此问题进行讨论,尝试找出相对合理的管理凭证的方案。\n一开始我们想到的方案可能是这样的:用户在 DevOps 平台增加凭证后,DevOps 再将凭证同步到 Jenkins 上。Jenkins 任务在使用凭证时,使用的是存储在 Jenkins 上的凭证,而不是 DevOps 平台上的。\n但是,仔细想想,这样做会存在以下问题: * Jenkins 与 DevOps 平台之间的凭证数据会存在不一致问题。 * 存在一定的安全隐患。通过 Jenkins 脚本命令行很容易就把所有密码的明文拿到。哪天 Jenkins 被注入了,所有的凭证一下子就被扒走。 * 无法实现 Jenkins 高可用,因为凭证存在 Jenkins master 机器上。\n那么,有没有更好的办法呢?\n期望实现的目标 先定我们觉得更合理的目标,然后讨论如何实现。以下是笔者觉得合理的目标: \u0026gt; 用户还是在 DevOps 管理自己的凭证。但是 DevOps 不需要将自己凭证同步到 Jenkins 上。Jenkins 任务在使用凭证时,从 DevOps 上取。\n实现方式 Jenkins 有一个 Credentials Binding Plugin 插件,在 Jenkins pipeline 中的用法如下:\nwithCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) { sh ''' curl -u \u0026quot;$USERPASS\u0026quot; https://private.server/ \u0026gt; output ''' }  withCredentials 方法做的事情就是从 Jenkins 的凭证列表中取出 id 为 mylogin 的凭证,并将值赋到变量名为 USERPASS 的变量中。接下来,你就可以在闭包中使用该变量了。\n说到这里,不知道读者朋友是否已经有思路了?\n思路就是实现一个和 Credentials Binding Plugin 插件类似功能的方法,比如叫 zWithCredentials(后文还会提到)。与 withCredentials 不同的是,zWithCredentials 根据凭证 id 获取凭证时,不是从 Jenkins 上获取,而是从 DevOps 平台获取。\n会遇到的坑 需要适配只认 Jenkins 凭证的插件 withCredentials 方法是将凭证的内容存到变量中,这可以满足一大部分场景。但是有一种场景是无法满足的。就是某些 Jenkins 插件的步骤接收参数时,参数值必须是 Jenkins 凭证管理系统中的 id。比如 git 步骤中 credentialsId 参数:\ngit branch: 'master', credentialsId: '12345-1234-4696-af25-123455', url: 'ssh://git@bitbucket.org:company/repo.git'  这种情况,我们不可能修改现有的插件。因为那样做的成本太高了。\n那怎么办呢?\n笔者想到的办法是在 zWithCredentials 中做一些 hack 操作。也就是 zWithCredentials 除了从 DevOps 平台获取凭证,还在 Jenkins 中创建一个 Jenkins 凭证。在 Jenkins 任务执行完成后,再将这个临时凭证删除。这样就可以适配那些只认 Jenkins 凭证 id 的插件了。\n对凭证本身的加密 DevOps 平台在存储凭证、传输凭证给 Jenkins 时,都需要对凭证进行加密。至于使用何种加密方式,交给读者思考了。\n小结 以上解决方案对 Jenkins 本身的改造几乎没有,我们只通过一个插件就解耦了 Jenkins 的凭证管理和 DevOps 平台的凭证管理。\n思路已经有了。具体怎么实现,由于一些原因不能开源,虽然实现起来不算难。还请读者见谅。\n最后,希望能和遇到同样问题的同学进行交流。看看是否还可以有更好的设计思路。\n",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
169
        "poster": "../../../images/articles/2019/05/2019-05-14-devops-jenkins-credential-manage/devops-platform-lock-jenkins.png"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
170
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-13-jenkins-book-gift/",
        "title": "Jenkins 公众号送书福利",
        "type": "wechat",
        "date": "2019-05-13 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "赠送 5 本《Jenkins 2.x实践指南》",
        "content": " Jenkins 中文社区是一个开放、包容、活跃的社区,包含大量的 Jenkins 干货。\n当然,它也会为公众号的粉丝们发放福利。\n本次福利是《Jenkins 2.x实践指南》x 5,以下是介绍:\n本次活动书籍均由博文视点(Broadview)提供,特此感谢。\n参与方式:  关注本公众号,并在后台回复【抽奖】,根据二维码进入小程序抽奖。 开奖时间为:5月19日晚上7点自动开奖(记得填自己的手机号,地址以便中奖后邮寄发出)。  中奖的同学,不要忘记发朋友圈分享支持噢~\n等不急的同学,还可以扫二维码直接购买:\n",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": "../../../images/articles/2019/05/2019-05-13-jenkins-book-gift/poster.png"
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-13-cdf-call-for-papers/",
        "title": "持续交付峰会 Call For Papers",
        "type": "wechat",
        "date": "2019-05-13 00:00:00 +0000 UTC",
        "tags": ["cdf", "cfp"],
        "description": "持续交付基金会在上海 KubeCon 的同场活动",
        "content": " 持续交付峰会是一个为期一天的活动,将开源 CI/CD 社区汇集在一起。这一天将包括主题演讲,项目展示和终端用户的故事,以及 BoF 会议。与同行会面并推动未来持续交付的方向。\n重要日期  CFP 开始:4月29日,星期一 CFP 关闭:太平洋标准时间 5月17日,23:59,星期五 CFP 通知:5月29日,星期三 日程通知:5月30日,星期一 幻灯片截止:6月17日,星期四 活动时间:6月24日  建议的话题  CDF 的项目  Jenkins Jenkins X Tekton 和 Spinnaker 讲述你正在使用的这些项目的功能或者集成的功能,分享你为什么要使用以及如何利用这些项目解决了哪些问题  你们团队的持续交付  我们希望能听到真实项目中的使用,以及你们团队所推荐的持续交付实践  安全与合规性最佳实践  分享在持续交付中改善你们的软件供应链中的安全性的案例和技巧  帮助我们的同时也帮助自己 描绘你希望看到的 CI/CD 景象   点击这里提交你的演讲题目\n点击这里查看其他更多的同场活动。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "“../../../images/logos/cdf-logo.png”"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-09-jenkins-release/",
        "title": "Jenkins 版本发布",
        "type": "wechat",
        "date": "2019-05-09 00:00:00 +0000 UTC",
        "tags": ["jenkins", "release"],
        "description": "Jenkins 每周更新版发布",
        "content": " 2.175 (2019-04-28)  当构建完成后,更新状态图标 (issue 16750) 插件管理页面提供了更方便的插件更新选项,包括:“全选”、“兼容的“或”全不选“。 “兼容”的选择(之前为“全选”)已经不再包括含有任何兼容性警告的插件。 (issue 56477) 从连接 Jenkins 节点的界面上移除会误导到 Java Web Start 和 JNLP 的链接等引用。 (pull 3998) 再次启用 Stapler 请求分发 telemetry。 (pull 3999) 确保远程对象仅通过远程通道被序列化。 确定永远不会设计以 XML 形式持久化到磁盘中的类包括: FilePath, [Stream]TaskListener, and ProcessTree. (issue 47896) 修复在 Linux 代理安装器中看到的一些错误。 (issue 57071) 使得 Debian/Ubuntu 启动器脚本对 Java 11 兼容。 (issue 57096) 开发者:使得 mvn -f war hudson-dev:run支持${port}。 (pull 3984)  2.174 (2019-04-21)  重命名一个代理节点,保持旧的配置,导致重启后旧的代理节点再次出现。 (issue 56403) 嵌套的视图现在也可以根据名称搜索了。 (issue 43322)  ",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": "“../../../images/cow.jpg”"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-08-jenkins-plugin-develop-within-two-days-part02/",
        "title": "Jenkins 插件开发之旅:两天内从 idea 到发布(下篇)",
        "type": "wechat",
        "date": "2019-05-08 00:00:00 +0000 UTC",
        "tags": ["jenkins", "maven", "jira"],
        "description": "两天内,从产生 idea 到编写插件,最后发布到 Jenkins 插件更新中心",
        "content": " 本文分上下两篇,上篇介绍了从产生 idea 到插件开发完成的过程; 下篇将介绍将插件托管到 Jenkins 插件更新中心的一系列过程。\n托管插件 托管插件包括一系列流程步骤。 笔者完成了它所有步骤(包括非必须的步骤),其中主要有两个具有标志性的任务: - 插件代码被托管在 jenkinsci GitHub 组织的一个仓库,然后作者拥有它的管理权限。\n笔者插件的代码仓库为:jenkinsci/maven-snapshot-check-plugin 。 - 你可以将插件发布到 Jenkins 项目的 Maven 仓库,它是 Jenkins 项目所使用的更新站点的数据来源。\n准备工作 在请求插件托管之前,需要完成以下几个步骤。\n查找类似的插件 Jenkins 社区欢迎任何人的贡献,但为了让 Jenkins 用户受益, 它要求查找解决相同或类似问题的插件,看看是否可以与现有的维护人员联手。 可以在 https://plugins.jenkins.io 查看所有的插件, 以确认是否已有类似的插件实现了你计划实现的功能。 笔者在之前已进行过查找,并没有找到可以实现笔者计划实现的功能的类似插件。\n命名规约 Jenkins 制定了一些与插件相关的命名规约。 插件开发者要确保遵循这些命名规约。\nartifactId 插件的 artifactId 被用于文件基本名称,是 Jenkins 插件和更新站点的唯一标识。\n它需要遵循一些发布规约: - 使用小写 ID ,并根据需要使用连字符分隔术语。 - 除非名称有任何意义,否则不要在 ID 中包含 jenkins 或 plugin 。\n插件名称 插件的名称在 Jenkins UI 和其它地方(如:插件站点)展示给用户。\n如果可以,建议使用简短的描述性名称,如 Subversion 。\n笔者所写的插件的名称为:Maven SNAPSHOT Check 。\ngroupId 推荐使用 io.jenkins.plugins 或 org.jenkins-ci.plugins 作为 groupId 。 但是不禁止其他组织 ID ,除非它们是恶意的(例如引用与你没有关系的组织)。 笔者所写的插件使用的 groupId 为: org.jenkins-ci.plugins 。\nJava 源代码 Jenkins 项目一般遵循 Oracle Java 代码规约, 但是并没有很好的强制甚至在核心组件中。 个别的插件维护者有时会选择使用不同的风格指南作为插件。 笔者日常使用 IDEA 进行开发,之前安装了「阿里 Java 规约插件」, 因而使用它作为编码规约。\n提交消息 Git 提交消息应该从引用与之相关的 JIRA 问题开始(如果适用), 然后在第一行进行简短的总结,并在随后的行中提供更多详细信息。例如:\n[JENKINS-00000] Frobnicate the widget  如果给定的提交修复了指定的问题, 那么使用以下前缀中的任何一个将会自动化解决相关的 JIRA 问题。\n[FIX JENKINS-00000] Frobnicate the widget [FIXED JENKINS-00000] Frobnicate the widget [FIXES JENKINS-00000] Frobnicate the widget  由于还没过将插件托管,笔者并没有遵循该规约, 等插件发布后,笔者将考虑遵循该规约。\nLicense Jenkins 项目分发的所有插件都需要是免费的开源软件。 这适用于插件源代码及其所有依赖项。 要确保在 pom.xml 文件和仓库中的 LICENSE 文件指定协议。 官方建议使用 MIT license ,它用于 Jenkins 核心和大多数插件和库, 但是任何 OSI 批准的开源 license 都可以。 笔者这里使用了 MIT license 。\n要求注册的账号 通过 Jenkins 项目更新站点分发的插件需要托管在 jenkinsci GitHub 组织中, 因此需要在 GitHub 上有一个账号,并且需要有一个公共仓库来存放插件源代码。\n为了完整地发布你的插件,需要注册一个 Jenkins 社区帐号, 它可以让你访问 JIRA,wiki 和 Maven 仓库 。\n发起托管请求  注意:Jenkins 官方自动化流程使用更容易实现的 fork + 删除的方式(见下文),而不是转移仓库所有者。\n 登录到 JIRA 然后在 HOSTING 项目创建一个问题。 请确保按照描述填写所有字段。 Jenkins 项目成员将在几天内审查你的请求。 如果审查人员要求你更改,那么请按照要求进行更改。\n笔者提交的申请为:HOSTING-750, 比较幸运的是当天凌晨(北京时间)笔者的请求就被审查, 正巧那时笔者未眠,于是随后按要求进行了更改并在不久后该申请被审批通过。\n一旦满足了所有的需求,你的仓库将被 fork 到 jenkinsci 组织中, 并且你将被邀请加入该组织,并且将为你在 JENKINS 项目中创建 JIRA 组件。\n此时,将要求你删除 Jenkins 从中 fork 的仓库。 之后你可以通过再次从 jenkinsci 那里 fork 来重新创建它。 这将确保 jenkinsci 仓库是 Github 上网络图的根。 这意味着: - 不会混淆哪个仓库是权威仓库。 - 即使在 GitHub 上没有大量的关注者,源代码搜索也会成功。 - 其他人更可能在 jenkinsci 仓库中提交 pull request(这是协作的理想选择)。\n创建 wiki 页面 尽管这对发布插件来说这不是严格要求的,但最好为插件创建一个 wiki 页面来存储文档。关于如何执行此操作的详细信息,请参阅插件 wiki 页面指南。\n笔者所写的插件的 wiki 页面为:Maven SNAPSHOT Check Plugin 。 其间除了官方文档,笔者还参考了其它插件 wiki 页面的排版。\n开启 CI 构建 Jenkins 项目托管了一个 Jenkins 实例来执行插件的持续集成构建。 官方推荐通过在插件的 Github 仓库根目录创建一个 Jenkinsfile, 为在 Jenkinsci Github 组织中的插件设置 CI 构建。 典型的插件构建( Maven 或 Gradle )只需在 Jenkinsfile 中包含以下语句即可运行:\nbuildPlugin()  申请上传权限 在源代码被 fork 到 jenkinsci 组织后,需要提交一个上传权限请求。 按照 jenkins-infra/repository-permissions-updater/ 仓库的 README 文件中所说的来做就可以。\nJenkins 项目在 Artifactory 上托管 Maven 制品,例如核心和插件发布。 它的权限系统与 Github 是独立的, 限制了那些用户(由 Jenkins LDAP 帐户标识,与 wiki 和 JIRA 一样)可以上传。 这个仓库包含 YAML 格式的 Artifactory 上传权限定义, 以及将它们同步到 Artifactory 的工具。 \u0026gt; 先决条件:在申请权限之前,需要先用 Jenkins 社区帐号登录一次 Artifactory 。\n要请求对制品(通常是插件)的上传权限,需要提交一个 PR , 该 PR 需要创建与申请上传权限相关的 YAML 文件。 笔者所提交的 PR 为:Plugin: Permission for maven-snapshot-check-plugin 。\n通过查看它可以看出该 PR 增加了一个文件:permissions/plugin-maven-snapshot-check.yml ,其内容如下:\nname: \u0026quot;maven-snapshot-check\u0026quot; github: \u0026quot;jenkinsci/maven-snapshot-check-plugin\u0026quot; paths: - \u0026quot;org/jenkins-ci/plugins/maven-snapshot-check\u0026quot; developers: - \u0026quot;donhui\u0026quot;  在创建 PR 后,会有帮助说明以及 checklist 让提交人对该 PR 进行检查确认。\n等这个 PR 被审批后,插件开发者就会拥有该插件的发布权限。\n发布插件 前提 要先确认拥有发布该插件的权限。\nMaven 要使用的 Artifactory 凭据 需要告诉 Maven 访问 Artifactory 的凭据。 登录 Artifactory ,从用户 profile 中获取加密的密码。 在 ~/.m2/settings.xml 文件配置 server 认证信息,如下所示:\n\u0026lt;settings xmlns=\u0026quot;https://maven.apache.org/SETTINGS/1.0.0\u0026quot; xmlns:xsi=\u0026quot;http://www.w3.org/2001/XMLSchema-instance\u0026quot; xsi:schemaLocation=\u0026quot;https://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd\u0026quot;\u0026gt; \u0026lt;servers\u0026gt; \u0026lt;server\u0026gt; \u0026lt;id\u0026gt;maven.jenkins-ci.org\u0026lt;/id\u0026gt; \u0026lt;username\u0026gt;your_user_name_here\u0026lt;/username\u0026gt; \u0026lt;password\u0026gt;your_encrypted_password_here\u0026lt;/password\u0026gt; \u0026lt;/server\u0026gt; \u0026lt;/servers\u0026gt; \u0026lt;/settings\u0026gt;  配置 GitHub 以接受你的 SSH key 当执行 release 时,Maven Release Plugin 会自动往仓库推送代码, 所以需要配置 GitHub 以接受你的 SSH key 。\n更多信息可以参考:GitHub help on SSH 。\n执行发布 当 GitHub 和 Maven 凭据配置好后, 执行一次发布应该很简单,只需要运行下面的命令:\nmvn release:prepare release:perform  可能在执行发布时会遇到 \u0026ldquo;401 Unauthorized\u0026rdquo; 或 \u0026ldquo;403 Forbidden\u0026rdquo; 之类问题, 这一般是 settings.xml 配置问题或是没有上传权限。 一些公共的问题处理方案可以查看:HostingPlugins-Workingaroundcommonissues。\n插件发布后,8 小时内,将可以在插件更新中心看到它。\n笔者所写的 maven-snapshot-check 插件, 在插件列表页的地址为:https://plugins.jenkins.io/maven-snapshot-check 。\nJenkins 实例的插件管理页面的「可选插件」选项截图如下: 为插件分类 在 Jenkins 插件列表页面,可以对插件进行分类显示。\n要为插件添加一个分类,需要向 jenkins-infra/update-center2 仓库提交一个 PR 。 笔者所提交的 PR 为:add maven-snapshot-check category 。\n通过查看它可以看出该 PR 在 src/main/resources/label-definitions.properties 文件增加了一行,如下所示:\nmaven-snapshot-check=builder  总结 两天的 Jenkins 插件开发之旅(尤其是 04.24 晚上花了很多时间), 让笔者了解了插件开发的基本知识,并在托管插件的过程中学到一些知识。 然后在周末花了几个小时总结回顾,并将它写成文档。 同时也希望此文能给 Jenkins 插件开发者入门带来一点帮助!\n参考  Guide to Plugin Hosting Performing a Plugin Release  ",
        "auhtor": "donhui",
        "translator": "",
        "original": "",
        "poster": "../../../images/articles/2019/05/2019-05-08-jenkins-plugin-develop-within-two-days-part02/sunset.png"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
223
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
224 225 226 227 228 229 230 231 232 233 234 235 236
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-07-jenkins-install-plugins-shell/",
        "title": "Jenkins 自动化安装插件",
        "type": "wechat",
        "date": "2019-05-07 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "Jenkins 批量安装指定版本插件",
        "content": " 手工安装 Jenkins 插件的方法 通常,我们有两种方法安装 Jenkins 插件。第一种方法是到 Jenkins 插件管理页面搜索插件,然后安装。第二种方法是上传 Jenkins 插件的 hpi 文件安装。这两种方法能满足大多数人的需求。\n第一种方法,如下图所示: 第二种方法,如下图所示: 但是对于需要保证 Jenkins 稳定或在 Jenkins 上进行二次开发的同学来说,以上方法是无法满足需求的。\n第一种方法是无法指定插件的版本。第二种方式必须自己找到该插件的依赖树,然后根据依赖关系一个个地安装。是的,手工上传插件的这种方法,Jenkins 是不会自动下载依赖的。\n还有,就是这两种方式都无法实现批量安装。\n自动安装插件的方法 那么,有什么方法能指定插件的版本,又能自动下载它的依赖,还能批量下载呢?\n幸运的是,Jenkins 的 Docker 镜像的代码仓库里的 install-plugins.sh 脚本已经实现。只不过需要我们拿过来小小修改才能使用。笔者修改后创建了相应的代码仓库:jenkins-install-plugins-shell 。链接在文章末尾。\n以下是 jenkins-install-plugins-shell 的使用方法: 1. 将代码 clone 到 JENKINS_HOME 目录中。\ncd $JENKINS_HOME git clone https://github.com/zacker330/jenkins-install-plugins-shell.git cd jenkins-install-plugins-shell   在 plugins.txt 中加入希望安装的插件 在 jenkins-install-plugins-shell 目录中,有一个 plugins.txt 文件,在文件中写入希望安装的插件及版本号。例如:  ansible:1.0 powershell:1.3  执行安装\n# Jenkins War 的路径,用于分析 export JENKINS_WAR_PATH=\u0026lt;Jenkins war文件的路径\u0026gt; chmod +x install-plugins.sh jenkins-support ./install-plugins.sh \u0026lt; plugins.txt  重启 Jenkins install-plugins 本质上做的事情就只是将插件从云端下载到 JENKINS_HOME 下的 plugins 目录中。要使安装的插件生效,还需要重启 Jenkins。\n  关于 Jenkins 插件的名称 Jenkins 插件有两个名称。一个叫 display name,一个叫 short name。比如 Ansible 插件的 disply name 为 Ansible plugin,short name 为 ansible。\n如何知道一个插件的 short name 呢?可以在 Jenkins 插件官网上找到,比如 Ansible 的:\n在 plugins.txt 中使用的是 short name。\n总结 笔者为什么一定要确定 Jenkins 插件的版本?是因为插件的版本会影响 Jenkins 流水线的可靠性。所以,笔者才会这么在意 Jenkins 插件的版本。\n附录  Jenkins 官方 Docker 镜像中的自动化插件安装脚本:https://github.com/jenkinsci/docker/blob/master/install-plugins.sh 笔者修改后的自动化插件安装脚本: https://github.com/zacker330/jenkins-install-plugins-shell  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
        "poster": "../../../images/articles/2019/05/2019-05-07-jenkins-install-plugins-shell/poster.png"
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
237 238 239 240 241 242 243 244 245 246 247 248
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/05/2019-05-06-jenkins-plugin-develop-within-two-days-part01/",
        "title": "Jenkins 插件开发之旅:两天内从 idea 到发布(上篇)",
        "type": "wechat",
        "date": "2019-05-06 00:00:00 +0000 UTC",
        "tags": ["jenkins", "maven", "jira"],
        "description": "两天内,从产生 idea 到编写插件,最后发布到 Jenkins 插件更新中心",
        "content": " 本文介绍了笔者首个 Jenkins 插件开发的旅程, 包括从产生 idea 开始,然后经过插件定制开发, 接着申请将代码托管到 jenkinsci GitHub 组织, 最后将插件发布到 Jenkins 插件更新中心的过程。\n鉴于文章篇幅过长,将分为上下两篇进行介绍。\n从一个 idea 说起 前几天和朋友聊天时,聊到了 Maven 版本管理领域的 SNAPSHOT 版本依赖问题, 这给他带来了一些困扰,消灭掉历史遗留应用的 SNAPSHOT 版本依赖并非易事。\n类似问题也曾经给笔者带来过困扰,在最初没能去规避问题, 等到再想去解决问题时却发现困难重重,牵一发而动全身, 导致这个问题一直被搁置,而这也给笔者留下深刻的印象。\n等到再次制定 Maven 规范时,从一开始就考虑 强制禁止 SNAPSHOT 版本依赖发到生产环境。\n这里是通过在 Jenkins 构建时做校验实现的。 因为没有找到提供类似功能的 Jenkins 插件, 目前这个校验通过 shell 脚本来实现的, 具体的做法是在 Jenkins 任务中 Maven 构建之前增加一个 Execute shell 的步骤, 来判断 pom.xml 中是否包含 SNAPSHOT 关键字,如果包含,该次构建状态将被标记为失败。 脚本内容如下:\n#!/bin/bash if [[ ` grep -R --include=\u0026quot;pom.xml\u0026quot; SNAPSHOT .` =~ \u0026quot;SNAPSHOT\u0026quot; ]]; then echo \u0026quot;SNAPSHOT check failed\u0026quot; \u0026amp;\u0026amp; grep -R --include=\u0026quot;pom.xml\u0026quot; SNAPSHOT . \u0026amp;\u0026amp; exit 1; else echo \u0026quot;SNAPSHOT check success\u0026quot;; fi  恰好前不久在看 Jenkins 插件开发文档, 那何不通过 Jenkins 插件的方式实现它呢?\n于是笔者开始了首个 Jenkins 插件开发之旅。\n插件开发过程 Jenkins 是由 Java 语言开发的最流行的 CI/CD 引擎。\n说起 Jenkins 强大的开源生态,自然就会说到 Jenkins 插件。 Jenkins 插件主要用来对 Jenkins 的功能进行扩展。 目前 Jenkins 社区有上千个插件, 用户可以根据自己的需求选择合适的插件来定制 Jenkins 。\n插件开发准备 插件开发需要首先安装 JDK 和 Maven,这里不做进一步说明。\n创建一个插件 Jenkins 为插件开发提供了 Maven 原型。 打开一个命令行终端,切换到你想存放 Jenins 插件源代码的目录,运行如下命令:\nmvn -U archetype:generate -Dfilter=io.jenkins.archetypes:  这个命令允许你使用其中一个与 Jenkins 相关的原型生成项目。\n$ mvn -U archetype:generate -Dfilter=io.jenkins.archetypes: ...... Choose archetype: 1: remote -\u0026gt; io.jenkins.archetypes:empty-plugin (Skeleton of a Jenkins plugin with a POM and an empty source tree.) 2: remote -\u0026gt; io.jenkins.archetypes:global-configuration-plugin (Skeleton of a Jenkins plugin with a POM and an example piece of global configuration.) 3: remote -\u0026gt; io.jenkins.archetypes:hello-world-plugin (Skeleton of a Jenkins plugin with a POM and an example build step.) Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 3 Choose io.jenkins.archetypes:hello-world-plugin version: 1: 1.1 2: 1.2 3: 1.3 4: 1.4 Choose a number: 4: 4 ...... [INFO] Using property: groupId = unused Define value for property 'artifactId': maven-snapshot-check Define value for property 'version' 1.0-SNAPSHOT: : [INFO] Using property: package = io.jenkins.plugins.sample Confirm properties configuration: groupId: unused artifactId: maven-snapshot-check version: 1.0-SNAPSHOT package: io.jenkins.plugins.sample Y: : Y  笔者选择了 hello-world-plugin 这个原型, 并在填写了一些参数,如artifactId、version 后生成了项目。\n可以使用 mvn verify 命令验证是否可以构建成功。\n构建及运行插件 Maven HPI Plugin 用于构建和打包 Jenkins 插件。 它提供了一种便利的方式来运行一个已经包含了当前插件的 Jenkins 实例:\nmvn hpi:run  这将安装一个 Jenkins 实例,可以通过 http://localhost:8080/jenkins/ 来访问。 等待控制台输出如下内容,然后打开 Web 浏览器并查看插件的功能。\nINFO: Jenkins is fully up and running  在 Jenkins 中创建一个自由风格的任务,然后给它取个名字。 然后添加 \u0026ldquo;Say hello world\u0026rdquo; 构建步骤,如下图所示:\n输入一个名字,如:Jenkins ,然后保存该任务, 点击构建,查看构建日志,输出如下所示:\nStarted by user anonymous Building in workspace /Users/mrjenkins/demo/work/workspace/testjob Hello, Jenkins! Finished: SUCCESS  定制开发插件 Jenkins 插件开发归功于有一系列扩展点。 开发人员可以对其进行扩展自定义实现一些功能。\n这里有几个重要的概念需要做下说明:\n扩展点( ExtensitonPoint ) 扩展点是 Jenkins 系统某个方面的接口或抽象类。 这些接口定义了需要实现的方法,而 Jenkins 插件需要实现这些方法。\n笔者所写的插件需要实现 Builder 这个扩展点。 代码片段如下:\npublic class MavenCheck extends Builder {}  Descriptor 静态内部类 Descriptor 静态内部类是一个类的描述者,用于指明这是一个扩展点的实现, Jenkins 通过这个描述者才能知道我们写的插件。 每一个描述者静态类都需要被 @Extension 注解, Jenkins 内部会扫描 @Extenstion 注解来获取注册了哪些插件。\n代码片段如下:\n@Extension public static final class DescriptorImpl extends BuildStepDescriptor\u0026lt;Builder\u0026gt; { public DescriptorImpl() { load(); } @Override public boolean isApplicable(Class\u0026lt;? extends AbstractProject\u0026gt; aClass) { return true; } @Override public String getDisplayName() { return \u0026quot;Maven SNAPSHOT Check\u0026quot;; } }  在 DesciptorImpl 实现类中有两个方法需要我们必须要进行重写: isApplicable() 和 getDisplayName() 。 isApplicable() 这个方法的返回值代表这个 Builder 在 Jenkins Project 中是否可用, 我们可以将我们的逻辑写在其中,例如做一些参数校验, 最后返回 true 或 false 来决定这个 Builder 是否可用。\ngetDisplayName() 这个方法返回的是一个 String 类型的值, 这个名称被用来在 web 界面上显示。\n数据绑定 前端页面的数据要和后台服务端进行交互,需要进行数据绑定。 前端 config.jelly 页面代码片段如下:\n\u0026lt;?jelly escape-by-default='true'?\u0026gt; \u0026lt;j:jelly xmlns:j=\u0026quot;jelly:core\u0026quot; xmlns:st=\u0026quot;jelly:stapler\u0026quot; xmlns:d=\u0026quot;jelly:define\u0026quot; xmlns:l=\u0026quot;/lib/layout\u0026quot; xmlns:t=\u0026quot;/lib/hudson\u0026quot; xmlns:f=\u0026quot;/lib/form\u0026quot;\u0026gt; \u0026lt;f:entry title=\u0026quot;check\u0026quot; field=\u0026quot;check\u0026quot;\u0026gt; \u0026lt;f:checkbox /\u0026gt; \u0026lt;/f:entry\u0026gt; \u0026lt;/j:jelly\u0026gt;  如上所示,需要在 config.jelly 中包含需要传入的参数配置信息的选择框,field 为 check ,这样可以在 Jenkins 进行配置,然后通过 DataBoundConstructor 数据绑定的方式,将参数传递到 Java 代码中。 服务端 Java 代码片段如下:\n@DataBoundConstructor public MavenCheck(boolean check) { this.check = check; }  核心逻辑 笔者所写的插件的核心逻辑是检查 Maven pom.xml 文件是否包含 SNAPSHOT 版本依赖。\nJenkins 是 Master/Agent 架构, 这就需要读取 Agent 节点的 workspace 的文件, 这是笔者在写插件时遇到的一个难点。\nJenkins 强大之处在于它的生态,目前有上千个插件, 笔者参考了 Text-finder Plugin 的源码, 并在参考处添加了相关注释,最终实现了插件要实现的功能。\n详细代码可以查看 jenkinsci/maven-snapshot-check-plugin 代码仓库。\n分发插件 使用 mvn package 命令可以打包出后缀为 hpi 的二进制包, 这样就可以分发插件,将其安装到 Jenkins 实例。\n插件使用说明 以下是对插件的使用简要描述。\n如果勾选了下面截图中的选择框, Jenkins 任务在构建时将会检查 pom.xml 中是否包含 SNAPSHOT 。 如果检查到的话,则会将该次构建状态标记为失败。 总结 文章上篇主要介绍了从产生 idea 到插件开发完成的过程。\n那么插件在开发完成后是如何将它托管到 Jenkins 插件更新中心让所有用户都可以看到的呢?\n两天后的文章下篇将对这个过程进行介绍,敬请期待!\n参考  Plugin tutorial Preparing for Plugin Development Create a Plugin Build and Run the Plugin  ",
        "auhtor": "donhui",
        "translator": "",
        "original": "",
        "poster": "../../../images/articles/2019/05/2019-05-06-jenkins-plugin-develop-within-two-days-part01/huashan.png"
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
249
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-30-what-cicd-tool-should-i-use/",
        "title": "应该使用什么 CI/CD 工具?",
        "type": "wechat",
        "date": "2019-04-30 00:00:00 +0000 UTC",
        "tags": ["ci", "cd", "pipeline"],
        "description": "了解典型自动化 CI/CD 部署流水线的组件以及您需要的组件。",
        "content": " 在我们正在进行的 Kubernetes FAQ 系列中,我们回答了社区中一些常见的问题,本周我们将讨论在选择 CI/CD 工具时需要考虑什么。\n目前已经有大量的 CI/CD 工具可供选择-开源解决方案和商业解决方案。在这里,我们重点介绍在设置持续交付流水线时要考虑的一些最重要的注意事项。\n在这篇文章中你将学到: - 为什么需要自动化流水线 - 部署典型流水线的组件 - CD 流水线功能需要考虑 - 如何合并 GitOps\n为什么要创建自动化 CI/CD 流水线? 自动化 CI/CD 流水线有许多好处: - 将您的上线时间从数周或数月减少到数天或数小时。通过自动化流水线,开发团队可以提高发布的速度以及代码的质量。以小增量连续添加的新功能和修复可以使产品具有更少的缺陷。 - 一个强大的开发团队。由于交付流水线的所有阶段都可供团队中的任何人检查、改进和验证,因此可以创建对构建的所有权,从而鼓励整个组织的强大团队合作和协作能力。 - 降低软件开发的风险和成本。自动化鼓励开发人员在继续前进之前分阶段验证代码更改,从而减少了缺陷最终出现在生产中的机会。 - 减少进展中的工作量。CD 流水线提供从开发到客户的快速反馈循环。这个迭代周期不仅可以帮助您构建正确的产品,而且还允许开发人员更快地进行产品改进,从而减少正在进行的工作。 典型的部署流水线 CD 流水线由几个不同的阶段组成; 一个工具不能满足所有这些步骤。\n以下是构成大多数自动化流水线的步骤: 1. 在笔记本电脑上编写代码,将其推入源代码仓库(如 Git)。 2. 代码通过单元、集成和其他自动化测试。如果测试通过,将构建成新的 Docker 镜像。 3. 将镜像推送到镜像仓库。 4. 将新镜像推送到集群中。 思考 CD 流水线的特性 创建流水线的困难之一是成功地将您想要使用的工具粘合在一起。这些是为流水线选择工具时要考虑的主要功能: - 端到端的安全性 - 能够使用完全可重现的审计跟踪进行回滚 - 内置可观察性和警报功能 - 平均快速部署时间以及平均快速恢复时间 - 简单的开发人员经验和工作流程\n流水线端到端的安全性 在市场上的 CI/CD 工具中,有些工具将 CI 和 CD 部分合并为一个工具。或者更糟糕的是,那些负责创建 CI/CD 流水线的人将组装一系列手工锻造的脚本,这些脚本可以在一个方向上通过流水线推送代码,或执行被称为CIOP 流水线。\n出于多种原因,您不希望这样做。这是一种反模式,因为集群安全和其他凭据不在集群之外,这可能是不安全的。建议的方法是使用实​​现 Kubernetes Operator 的工具。\n部署到集群的 Kubernetes Operator 可以监视仓库中的新镜像。更进一步,如果您的整个集群状态(通过声明性清单)都保存在 Git 中,那么“diff alert”可以成为从仓库中“提取”新镜像并将其部署到集群的动力。这不仅是一种更安全的部署方法,而且还为开发人员提供了一种更简单的方法来应用和回滚生产环境的更改。\n具备完整审计跟踪回滚 跟踪差异历史记录,以及在团队中处理大型应用程序时管理新旧部署的回滚可能具有挑战性。您需要一个可以轻松处理此类方案的工具。如果您拥有一个完全可审计的路径,它可以帮助您了解何时何时执行了哪些操作,这也有助于 SOC 2合规性规定的增加。\n可观察性和警报 将可观察性纳入您的流水线意味着什么?\n为了提高你的速度,你的流水线需要结合可观察性来回答这些问题:\n如果自动发布更改,我怎么知道它是否有效? 在复杂的分布式系统中,我如何理解问题、诊断问题并管理事件 - 尤其是当您需要回滚时? 将持续交付与实时可观察性相结合,使您的开发团队能够在部署新功能之前做出更好的决策。\n新功能和补丁被推送到 Git 并触发部署流水线,当它们准备好发布时,理想情况下应该对正在运行的集群实时监控。这允许开发人员根据反馈做出决策。可以将它们返回到流水线的起点,或将更新后的镜像部署到生产集群中。 更快的平均部署和恢复时间 除了能够频繁可靠地部署之外,还需要考虑考虑一个重要场景,是在集群宕机时的恢复。这需要快速、平滑,并且可能由可能不是由 Kubernetes 专业的开发人员来执行。\n简单的开发人员经验和 Git 工作流程 为了在当今的云原生世界中快速发展,开发人员必须从端到端控制流水线。提交凭据等待人来回复的时期已经没有了。从开发人员一直使用的工具构建流水线是有意义的。像 Git 这样的工具。\n使用 GitOps,有三个基本原则:\n#1.所有可以描述的内容都必须存储在 Git 中 通过使用 Git 作为事实源,可以观察集群并将其与所需的状态进行比较。目标是描述所有内容:策略、代码、配置,甚至监控事件和版本控制。将所有内容保持在版本控制之下,可以增强收敛性,如果最初它们没有成功,则可以重新应用更改。\n#2.不要直接使用 kubectl 一般来说,使用命令行工具 kubectl 直接部署到集群不是一个好主意。许多人让他们的 CI 工具推动部署,但是这样做可能会对生产环境遭受更容易被攻击的风险。\n#3.使用遵循操作符模式的 Kubernetes Operator 使用遵循操作符模式的 Kubernetes Operator,您的集群始终通过其签入 Git 的配置文件与“事实源”保持同步。由于集群的所需状态保存在 Git 中,因此还可以观察到与正在运行的集群的差异。\n将 GitOps 工作流程应用于流水线 通过采用 GitOps,开发人员可以通过提取请求管理基础架构配置和软件部署以及回滚。当真实来源与集群中运行的不同时,集群会自动与 Git 中保存的内容同步。 Weave Cloud 的部署代理在集群内部运行。这意味着容器映像注册表和集群 API 的凭据永远不会离开集群的域。通过使用 Git 作为事实源,可以比较和警告所需的状态和当前状态。这不仅可以确保集群保持最新,而且还可以在集群崩溃时提供从灾难中快速恢复的方法。\n",
        "auhtor": "Anita Buehrle",
        "translator": "yJunS",
        "original": "https://dzone.com/articles/what-cicd-tool-should-i-use",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-29-progressive-delivery-with-jenkins-x-automatic-cana/",
LinuxSuRen's avatar
LinuxSuRen 已提交
264
        "title": "使用 Jenkins X 渐进式交付:自动化金丝雀部署",
LinuxSuRen's avatar
LinuxSuRen 已提交
265 266
        "type": "wechat",
        "date": "2019-04-29 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
267 268
        "tags": ["jenkins"],
        "description": "为了避免渐进式交付可能带来的麻烦,学习使用 Jenkins X 为金丝雀发布自动部署。",
LinuxSuRen's avatar
LinuxSuRen 已提交
269
        "content": " 这是渐进式交付系列的第三篇文章,前两篇请参见: - Kubernetes 中的渐进式交付:蓝绿部署和金丝雀部署 - 使用 Jenkins X 渐进式交付\n渐进式交付被 Netflix, Facebook 以及其它公司使用用来减轻部署的风险。 但是现在你可以在使用Jenkins X时采用它。\n渐进式交付是持续交付的下一步,它将新版本部署到用户的一个子集,并在将其滚动到全部用户之前对其正确性和性能进行评估,如果不匹配某些关键指标,则进行回滚。\n尤其是,我们聚焦金丝雀发布,并让它在你的 Jenkins X 应用中变得易于采用。 金丝雀发布包括向应用程序的新版本发送一小部分流量,并在向其他用户发布之前验证这里没有错误。 Facebook 就是这样做的,首先向内部员工提供新版本,然后是一小部分用户,然后是其他所有用户,但是你要采用它并不需要成为 Facebook !\n你可以在 Martin Fowler 的网站阅读更多与金丝雀发布相关信息。\nJenkins X 如果在 Jenkins X 中你已经有一个应用,那么你知道的你可以 通过 jx promote myapp --version 1.0 --env production 命令 promote 它到\u0026rdquo;生产\u0026rdquo;环境。 但是,在检查新版本是否失败的同时,它也可以自动并逐步地向一定比例的用户推出。 如果发生失败,应用程序将自动回滚。 整个过程中完全没有人为干预。\n注意:这个新功能是非常新的,在将来这些步骤将不再需要,因为它们也将由 Jenkins X 自动化了。\n作为第一步,三个 Jenkins X 插件需要被安装: - Istio : 一种服务网格容许我们管理我们服务的流量。 - Prometheus :Kubernetes 中最流行的监控系统。 - Flagger :一个使用 Istio 的项目,该项目使用 Prometheus 的指标自动化进行金丝雀发布和回滚。\n插件可以使用如下命令安装(使用一个最近版本的 jx CLI ): 1. jx create addon istio 2. jx create addon prometheus 3. jx create addon flagger\n这将在 jx-production 命名空间启动 Istio 来进行指标收集。\n现在获取 Istio ingress 的 IP ,并将一个通配符域名(如: *.example.com )指向它,以便我们可以使用它根据主机名路由多个服务。 Istio ingress 提供了金丝雀发布需要的路由能力(流量转移),传统的 Kubernetes ingress 对象不支持该功能。\n集群被配置后,是时候配置我们的应用了。 在 charts/myapp/templates 目录下向你的 helm chart 添加一个 canary.yaml。\n然后往 charts/myapp/values.yaml 追加如下内容,将 myapp.example.com 修改为你的主机名或域名:\n不久,当你从 Jenkins X 快速开始创建你的应用,将不再需要修改 canary.yaml 和 values.yaml 这两个文件,因为它们默认启用金丝雀部署。\n就这样!现在当使用 jx promote myapp --version 1.0 --env production 将你的应用 promote 到生产环境,它将执行一次金丝雀部署。 请注意,第一次被 promote 时,它不会执行金丝雀部署,因为它需要与以前的版本数据进行比较,但从第二次 promotion 开始,它将起作用。\n根据上面 values.yaml 文件中的配置,它看起来像: - 第 1 分钟:将 10% 的流量发送到新版本 - 第 2 分钟:将 20% 的流量发送到新版本 - 第 3 分钟:将 30% 的流量发送到新版本 - 第 4 分钟:将 40% 的流量发送到新版本 - 第 5 分钟:将 100% 的流量发送到新版本\n如果我们配置的指标(请求持续时间超过 500 毫秒或超过 1% 的响应返回 500 错误)失败,Flagger 将注意到失败,并且如果重复 5 次,它将回滚这次发布,将 100% 的流量发送到旧版本。\n获得金丝雀事件输出,执行如下命令: 1. $ kubectl -n jx-production get events \u0026ndash;watch\n2. \u0026ndash;field-selector involvedObject.kind=Canary 3. 23m \u0026hellip; New revision detected! Scaling up jx-production-myapp.jx-production 4. 22m \u0026hellip; Starting canary analysis forjx-production-myapp.jx-production 5. 22m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 10 6. 21m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 20 7. 20m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 30 8. 19m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 40 9. 18m \u0026hellip; Advance jx-production-myapp.jx-production canary weight 50 10. 18m \u0026hellip; Copying jx-production-myapp.jx-production template spec to jx-production-myapp-primary.jx-production 11. 17m \u0026hellip; Promotion completed! Scaling down jx-production-myapp.jx-production\n仪表盘 为了可视化的目的,Flagger 包含一个 Grafana 面板,尽管它在金丝雀发布中不需要。 可以在本地通过 Kubernetes 端口转发访问它。\n然后使用 admin/admin 访问 http://localhost:3000/,选择 canary-analysis 面板以及 - namespace 选择 jx-production - primary 选择 jx-production-myapp-primary - canary 选择 jx-production-myapp\n它将为我们提供当前版本和新版本的对比视图,视图中包含不同指标(CPU,内存,请求持续时间,响应错误……)。\n附加说明 请注意 Istio 默认地将阻止从你的 Pod 访问外部集群(一种预计将在 Istio 1.1 中发生变化的行为)。 学习如何控制 Istio ingress 流量。\n如果因为指标失败出现自动回滚,生产环境的 Jenkins X GitOps 仓库会过时,仍然使用新版本而不是旧版本。 这是计划在即将发布的版本中修复的内容。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
270 271 272 273
        "auhtor": "Carlos Sanchez",
        "translator": "donhui",
        "original": "https://dzone.com/articles/progressive-delivery-with-jenkins-x-automatic-cana",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
274
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
275
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
276
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-28-devsecops/",
LinuxSuRen's avatar
LinuxSuRen 已提交
277
        "title": "我们为什么需要 DevSecOps 和制品仓库?",
LinuxSuRen's avatar
LinuxSuRen 已提交
278 279
        "type": "wechat",
        "date": "2019-04-28 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
280 281
        "tags": ["security", "devops"],
        "description": "Helen Beal 在 Nexus 用户大会上发表的关于构建 DevSecOps 的建议",
LinuxSuRen's avatar
LinuxSuRen 已提交
282 283 284 285 286
        "content": "Helen Beal 曾经在一次讨论什么是 DevSecOps 工程师的会议上发言。令她惊讶的是,在与会人员中,许多人都没有将安全机制引入 DevOps。在与人们讨论之后,她将大家的问题总结为三类:安全机制会制造额外的隔阂;组织中的人很难理解 DevOps,因此安全机制可能会造成更多困惑;可能没有为安全机制预留空间。\n当然,Helen 不同意这些观点。她在技术领域从业近20年,专注于软件开发生命周期,对于 DevOps 和DevSecOps 有一些自己的理解。她自称为 Ranger4 的 「DevOpsologist」,因为她帮助那里的组织实现 DevOps。她在世界各地分享知识,并且她将参加我们在 2018 年的 Nexus User Conference ,讨论工具仓库及其在 DevSecOps 工具链中的角色。\n从高层次来看,Helen 为 DevSecOps 提出了一些重要建议:\n 确保安全是每一个人的职责 认识到安全人员的匹配限制。平均而言,人员比例为 100 名开发人员 : 10 名运维人员 : 1名安全人员 尽早移交产品进行测试和验证。缺乏足够的安全人员会造成一定的约束,移交并自动执行任务可以减少瓶颈并提前解决问题。 积极主动地降低风险 培养安全文化  Helen 花了一些时间阐述如何培养安全文化,组织在维护系统和人员行为安全时可以采用的一些关键原则和行动。\n行为安全使个人和团队能够以安全的方式行事。为了培养行为安全,她建议:\n 让人们意识到,失败是一个学习机会 确保团队之间有共同的责任和目标 不要吝啬花时间做实验 使用可协作的平台来分享学习经验和最佳实践 对实验的过程进行回顾,并确保有后续  她提到了几个真实的例子,例如 Esty,LEGO 还有 P\u0026amp;G 的「失败奖励」以及 Spotify 用来展示和追踪失败的「失败墙」。\n系统安全能够保障你的基础设施安全,她关于培养系统安全的建议包括:\n 用持续集成进行构建 使用部署自动化来驱动一致性和可审计性,并允许即时重新部署上一个已知的可用版本 用 ChatOps 来归类问题和事件 使用应用程序性能管理以提早发现问题并警告 降低出现问题波及范围,例如使用功能开关,金丝雀测试,蓝/绿环境和微服务 将产品需求与服务台相结合 养成使用混沌工程来找到失败原因的习惯  在讲述 DevSecOps 案例并说明如何灌输安全文化后,她将话题转向如何使用制品仓库。 毕竟,这是一个 Nexus 会议,制品仓库是 Nexus 的特色。\n她引用了 Manfred Moser 的话:「开发软件中没有制品仓库和制造业中没有仓库是一样的。」你不会奢望在没有仓库的情况下开办工厂,软件开发也一样。制品仓库保存了你每次构建的结果,并且确保你拥有可用的构建。\n制品仓库位于 DevOps 工具链的集成阶段,尽管其在构思阶段可被用来表示你想使用的工具是可用状态。\n如果没有开源策略,你就不应该使用制品仓库。制品仓库会自动执行你的开源策略,这样就不会像 35% 的组织一样有开源策略但忽略它。\nHelen 利用 Nexus Lifecycle 来告诉开发人员如何更好地使用制品,降低风险,并协助运维和安全部门确保使用了正确的软件。\n最重要的是,如果你还没有用上 DevSecOps ,那你应该尽早启用。这是未来的趋势,它已经渡过了发展期成为了一个成熟的概念,也有成熟的工具来帮助你。这会花一些时间,但一定是值得的。\n如果对 Helen 的整篇演讲感兴趣,可以在 此处 免费观看。\n",
        "auhtor": "Derek Weeks",
        "translator": "p01son6415",
        "original": "https://dzone.com/articles/why-you-need-devsecops-and-artifact-repositories",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
287
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
288
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
289 290 291
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-26-progressive-delivery-with-jenkins-x/",
        "title": "使用 Jenkins X 渐进式交付",
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
292
        "date": "2019-04-26 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
293 294 295 296 297 298
        "tags": ["progressive delivery", "kubernetes", "k8s", "jenkins", "jenkins x", "shipper", "istio", "flagger"],
        "description": "使用 Jenkins X 渐进式交付",
        "content": " 这是渐进式交付系列的第二篇文章,第一篇请看:Kubernetes 中的渐进式交付:蓝绿部署和金丝雀部署。\n我使用的我的 Croc Hunter 示例项目评估了 Jenkins X 中金丝雀部署和蓝绿色部署的三种渐进式交付方案。 - Shipper 为 Jenkins X 构建的 Helm 图表启用了蓝绿部署和多集群部署,但是对图表的内容有限制。 你可以在 staging 和生产环境之间做蓝绿部署。 - Istio 允许通过创建一个虚拟服务将一定比例的流量发送到 staging 或预览环境。 - Flagger 构建在 Istio 之上,并添加了金丝雀部署,可以根据指标自动进行滚动部署和回滚。 Jenkins X 可以通过创建一个 Canary 对象自动启用金丝雀功能,从而实现优雅的滚动部署,以升级到生产环境。\n这里可以查看 Shipper、Isito 和 Flager 的示例代码。\nShipper 由于 Shipper 对创建的 Helm 图表有多个限制,因此我必须对应用做一些更改。 而且 Jenkins X 只从 master 分支构建 Helm 包,所以我们不能做 PRs 的滚动部署,只能对 master 分支做滚动部署。\n应用标签不能包含发布名称,例如: app: {{ template “fullname” . }} 不起作用, 需要一些类似这样的标签: app: {{ .Values.appLabel }}。\n由 Jenkins X 生成的图表导致应用滚动失败,归因于生成的 templates/release.yaml 可能和 jenkins.io/releases CRD 冲突。\nChart croc-hunter-jenkinsx-0.0.58 failed to render: could not decode manifest: no kind \u0026quot;Release\u0026quot; is registered for version \u0026quot;jenkins.io/v1\u0026quot;  我们只需要将 jx step changelog 更改为 jx step changelog -generate-yaml =false ,这样就不会生成文件。\n在多集群环境,需要在 shipper 应用 yaml 中为 chartmuseum 和 docker registry 使用公开的 url,以便其他集群可以发现管理集群服务来下载图表。\nIstio 我们可以创建这个虚拟服务, 将所有进入 Ingress 网关的主机为 croc-hunter.istio.example.org 的请求的 1% 的流量发送到 Jenkins X 预览环境( PR 号为 35 )。\napiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: croc-hunter-jenkinsx namespace: jx-production spec: gateways: - public-gateway.istio-system.svc.cluster.local - mesh hosts: - croc-hunter.istio.example.com http: - route: - destination: host: croc-hunter-jenkinsx.jx-production.svc.cluster.local port: number: 80 weight: 99 - destination: host: croc-hunter-jenkinsx.jx-carlossg-croc-hunter-jenkinsx-serverless-pr-35.svc.cluster.local port: number: 80  Flagger 我们可以为 Jenkins X 在 jx-production 命名空间中部署的图表创建一个 Canary 对象, 所有新的 Jenkins X 对 jx-production 的 promotions 每次将自动滚动 10% , 如果出现任何失败,将自动回滚。\napiVersion: flagger.app/v1alpha2 kind: Canary metadata: # canary name must match deployment name name: jx-production-croc-hunter-jenkinsx namespace: jx-production spec: # deployment reference targetRef: apiVersion: apps/v1 kind: Deployment name: jx-production-croc-hunter-jenkinsx # HPA reference (optional) # autoscalerRef: # apiVersion: autoscaling/v2beta1 # kind: HorizontalPodAutoscaler # name: jx-production-croc-hunter-jenkinsx # the maximum time in seconds for the canary deployment # to make progress before it is rollback (default 600s) progressDeadlineSeconds: 60 service: # container port port: 8080 # Istio gateways (optional) gateways: - public-gateway.istio-system.svc.cluster.local # Istio virtual service host names (optional) hosts: - croc-hunter.istio.example.com canaryAnalysis: # schedule interval (default 60s) interval: 15s # max number of failed metric checks before rollback threshold: 5 # max traffic percentage routed to canary # percentage (0-100) maxWeight: 50 # canary increment step # percentage (0-100) stepWeight: 10 metrics: - name: istio_requests_total # minimum req success rate (non 5xx responses) # percentage (0-100) threshold: 99 interval: 1m - name: istio_request_duration_seconds_bucket # maximum req duration P99 # milliseconds threshold: 500 interval: 30s  ",
        "auhtor": "Carlos Sanchez",
        "translator": "donhui",
        "original": "https://blog.csanchez.org/2019/01/24/progressive-delivery-with-jenkins-x/",
LinuxSuRen's avatar
LinuxSuRen 已提交
299
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
300
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
301
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
302 303 304 305 306 307 308 309
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-25-jenkins-ansible-nginx/",
        "title": "使用 Jenkins + Ansible 实现自动化部署 Nginx",
        "type": "wechat",
        "date": "2019-04-25 00:00:00 +0000 UTC",
        "tags": ["jenkins", "ansible", "nginx"],
        "description": "使用 Jenkins + Ansible 实现自动化部署 Nginx",
        "content": " 本文介绍如何使用 Jenkins + Ansible 实现对 Nginx 的自动化部署。最终达到的效果有如下几点: 1. 只要你将 Nginx 的配置推送到 GitHub 中,Jenkins 就会自动执行部署,然后目标服务器的 Nginx 配置自动生效。这个过程是幂等(idempotent)的,只要代码不变,执行多少遍,最终效果不变。 2. 如果目标机器没有安装 Nginx,则会自动安装 Nginx。 3. 自动设置服务器防火墙规则。\n1. 实验环境介绍 本次实验使用 Docker Compose 搭建 Jenkins 及 Jenkins agent。使用 Vagrant 启动一台虚拟机,用于部署 Nginx。使用 Vagrant 是可选的,读者可以使用 VirtualBox 启动一个虚拟机。使用 Vagrant 完全是为了自动化搭建实验环境。\n以下是整个实验环境的架构图: 注意,图中的 5123 \u0026lt;-\u0026gt; 80 代表将宿主机的 5123 端口请求转发到虚拟机中的 80 端口。\n Vagrant:虚拟机管理工具,通过它,我们可以使用文本来定义、管理虚拟机。 Ansible:自动化运维工具 Docker Compose:它是一个用于定义和运行多容器 Docker 应用程序的工具。可以使用 YAML 文件来配置应用程序的服务。  2. 启动实验环境  克隆代码并进入文件夹 bash git clone https://github.com/zacker330/jenkins-ansible-nginx.git cd jenkins-ansible-nginx  构建 Jenkins agent 的镜像 需要自定义 Jenkins agent 镜像有两个原因:  本次实验,使用 Swarm 插件实现 Jenkins master 与 agent 之间的通信,所以 Jenkins agent 需要启动 swarm 客户端。 Jenkins agent 必须支持 Ansible。 bash docker build -f JenkinsSlaveAnsibleDockerfile -t jenkins-swarm-ansible .   启动 Jenkins master 及 Jenkins agent bash docker-compose up -d  通过 http://localhost:8080 访问 Jenkins master,如果出现“解锁密码”页面,如下图,则执行命令 docker-compose logs jenkins 查看 Jenkins master 启动日志。将日志中的解锁密码输入到表单中。然后就一步步按提示安装即可。  安装 Jenkins 插件 本次实验需要安装以下插件:  Pipeline 2.6:https://plugins.jenkins.io/workflow-aggregator Swarm 3.15:https://plugins.jenkins.io/swarm 用于 实现 Jenkins master 与 Jenkins agent 自动连接 Git 3.9.3:https://plugins.jenkins.io/git  配置 Jenkins master 不执行任务 进入页面:http://localhost:8080/computer/(master)/configure,如下图所示设置:  确认 Jenkins 安全配置有打开端口,以供 Jenkins agent 连接。 我们设置 Jenkins master 开放的端口,端口可以是固定的 50000 ,也可以设置为随机。设置链接:http://localhost:8080/configureSecurity/。  启动目标机器,用于部署 Nginx 在命令行中执行以下命令:\nvagrant up  注意,Vagrantfile 文件中的 config.vm.box 值必须改成你的 vagrant box 。\n  至此,实验环境已经搭建好了。接下来就可以新建 Jenkins 任务了。\n3. 在 Jenkins 上创建部署任务  新建流水线任务  配置流水线 配置 Jenkins 任务从远程仓库拉取 Jenkinsfile,如下图所示: 除此之外,不需要其它配置了,是不是很简单?\n4. 手工触发一次自动化构建 点击“立即构建”: 最终执行日志如下:   至此,部署已经完成。以后修改 Nginx 的配置,只需要修改代码,然后推送到远程仓库,就会自动化部署。不需要手工登录到目标机器手工修改了。\n最后,我们可以通过访问 http://localhost:5123,如果出现如下页面说明部署成功:\n5. 代码讲解 以上步骤并不能看出自动化部署真正做了什么。那是因为我们所有的逻辑都写在代码中。是的,可以说是 everything is code。\n接下来我们介绍代码仓库。\n% tree -L 2 ├── JenkinsSlaveAnsibleDockerfile # Jenkins agent 镜像 Dockerfile ├── Jenkinsfile # 流水线逻辑 ├── README.md ├── Vagrantfile # Vagrant 虚拟机定义文件 ├── docker-compose.yml # Jenkins 实现环境 ├── env-conf # 所有应用配置 │ └── dev # dev 环境的配置 ├── deploy # Ansible 部署脚本所在文件夹 │ ├── playbook.yaml │ └── roles └── swarm-client.sh # Jenkins swarm 插件的客户端  5.1流水线逻辑 Jenkinsfile 文件用于描述整条流水线的逻辑。代码如下:\npipeline{ // 任务执行在具有 ansible 标签的 agent 上 agent { label \u0026quot;ansible\u0026quot;} environment{ // 设置 Ansible 不检查 HOST_KEY ANSIBLE_HOST_KEY_CHECKING = false } triggers { pollSCM('H/1 * * * *') } stages{ stage(\u0026quot;deploy nginx\u0026quot;){ steps{ sh \u0026quot;ansible-playbook -i env-conf/dev deploy/playbook.yaml\u0026quot; } }}}   environment 部分:用于定义流水线执行过程中的环境变量。 triggers 部分:用于定义流水线的触发机制。pollSCM 定义了每分钟判断一次代码是否有变化,如果有变化则自动执行流水线。 agent 部分:用于定义整条流水线的执行环境。 stages 部分:流水线的所有阶段,都被定义在这部分。  以上只是定义流水线是如何执行的,目前整条流水线只有一个 deploy nginx 阶段,并且只执行了一条 ansible-playbook 命令。但是它并没有告诉我们部署逻辑是怎么样的。\n5.2 部署逻辑 所有的部署逻辑,包括 Nginx 的安装启动、配置的更新以及加载,都放在 Ansible 脚本中。对 Ansible 不熟的同学,可以在本文末尾找到介绍 Ansible 的文章。\n整个部署逻辑的入口在 deploy/playbook.yaml,代码如下:\n--- - hosts: \u0026quot;nginx\u0026quot; become: true roles: # Nginx 的部署 - ansible-role-nginx # 对防火墙的设置 - ansible-role-firewall   hosts:定义了 playbook 部署的目标主机分组名为 nginx。 roles:包含了两个执行具体部署动作的 role,至于 role 内部逻辑,不在本文讨论范围,有兴趣的同学阅读源码。  5.3 配置管理 谈到部署,就不得不谈配置管理。\n回顾前文中流水线中执行的 shell 命令:ansible-playbook -i env-conf/dev deploy/playbook.yaml 我们通过 -i 参数指定部署时所使用的环境配置。通过这种方式实现环境配置与执行脚本的分离。这样带来以下几个好处: 1. 新增环境时,只需要复制现有的环境,然后将里面的变量的值改成新环境的即可。比如,要对测试环境进行部署,只需要将 -i 参数值改成:env-conf/test。 2. 对配置版本化控制。\n本次实验中,各个环境的配置放在 env-conf 目录中,目前只有 dev 环境,以下是 env-conf/ 目录结构:\n% cd env-conf/ % tree └── dev ├── group_vars │ └── nginx.yaml ├── host_vars │ └── 192.168.52.10 └── hosts   hosts文件:Ansible 中通过“分组”来实现对主机的管理。hosts 文件内容如下:  [nginx] 192.168.52.10  host_vars 目录:用于存放主机级别的配置变量,本例中 192.168.52.10 是一个 YAML 格式文件。注意文件名是该主机的 IP。我们在文件中放主机相关的配置,比如 Ansible 连接主机时使用到的用户名和密码。 group_vars 目录:用于存放组级别的配置变量。比如 nginx.yaml 对应的就是 nginx 这个组的的配置变量。文件名与 hosts 中的组名对应。  总结 到此,我们完整的自动化部署已经讲解完成。但是还遗留下一些问题: 1. 本文只是安装了一个“空”的 Nginx,但是没有介绍 Nginx 真正配置。 2. 目前主机的连接信息(SSH 密码)是明文写在 host_vars/192.168.52.10 文件中的,存在安全风险。 3. 没有介绍如何当 Java 应用部署时,如何自动更新 Nginx 的配置。\n本文属于使用 Jenkins + Ansible 实现自动化部署的入门文章,笔者将根据读者的反馈决定是否写续集。\n如果觉得本文讲的 Jenkins 流水线逻辑部分不够过瘾,可以考虑入手一本最近才出版的《Jenkins 2.x实践指南》。长按下图进行扫码购买。\n附录  本次实验环境代码:https://github.com/zacker330/jenkins-ansible-nginx 简单易懂 Ansible 系列 —— 解决了什么:https://showme.codes/2017-06-12/ansible-introduce/ Puppet,Chef,Ansible 的共性:https://showme.codes/2016-01-02/the-nature-of-ansible-puppet-chef/  ",
        "auhtor": "zacker330",
LinuxSuRen's avatar
LinuxSuRen 已提交
310 311 312
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
313
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
314
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
315 316 317 318 319 320 321 322 323 324
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-24-progressive-delivery-in-kubernetes-blue-green-and-canary-deployments/",
        "title": "Kubernetes 中的渐进式交付:蓝绿部署和金丝雀部署",
        "type": "wechat",
        "date": "2019-04-24 00:00:00 +0000 UTC",
        "tags": ["progressive delivery", "kubernetes", "k8s", "shipper", "istio", "flagger"],
        "description": "本文介绍 Kubernetes 中与渐进式交付相关的三个有趣的项目:Shipper、Istio 以及 Flagger ",
        "content": " 渐进式交付是持续交付的下一步, 它将新版本部署到用户的一个子集,并在将其滚动到全部用户之前对其正确性和性能进行评估, 如果不匹配某些关键指标,则进行回滚。\n这里有一些有趣的项目,使得渐进式交付在 Kubernetes 中变得更简单。 我将使用一个 Jenkins X 示例项目 对它们之中的三个进行讨论:Shipper、Istio 以及 Flagger。\nShipper shipper 是来自 booking.com 的一个项目, 它对 Kubernetes 进行了扩展,添加了复杂的部署策略和多集群编排(文档)。 它支持从一个集群到多个集群的部署,允许多区域部署。\nShipper 通过一个 shipperctl 命令行进行安装。 它增加不同集群的配置文件来进行管理。 请注意这个与 GKE 上下文相关的问题。\nShipper 使用 Helm 包来部署,但是它们没有随着 Helm 一起安装,它们不会在 helm list 的输出显示。 同样地,deployments 的版本必须是 apps/v1 , 否则 shipper 将不能编辑 deployment 来添加正确的标签和副本数量。\n使用 shipper 部署都是与从旧版本(现有版本)过渡到新版本(竞争版本)相关。 这是通过创建一个新的应用对象实现的, 它定义了部署需要通过的多个阶段。例如下面 3 个步骤过程: 1. Staging:部署新版本到一个 pod ,没有流量 2. 50 / 50:部署新版本到 50% 的 pods,50% 的流量 3. Full on:部署新版本到全部的 pods,全部的流量\nstrategy: steps: - name: staging capacity: contender: 1 incumbent: 100 traffic: contender: 0 incumbent: 100 - name: 50/50 capacity: contender: 50 incumbent: 50 traffic: contender: 50 incumbent: 50 - name: full on capacity: contender: 100 incumbent: 0 traffic: contender: 100 incumbent: 0  如果发布的某个步骤没有将流量发送到 pods , 则可以使用 kubectl port-forward 访问它们,如:kubectl port-forward mypod 8080:8080, 这对于在用户看到新版本之前进行测试非常有用。\nShipper 支持多集群的概念,但是以相同的方式对待所有集群,仅使用区域并通过 capabilities (配置在集群对象中)进行筛选, 所有对一个应用对象来说,这里没有一个 dev, staging, prod 集群的选项。 但是我们可以有两个应用对象: - myapp-staging 部署到 \u0026ldquo;staging\u0026rdquo; 区域 - myapp 部署到其它区域\n在 GKE 中,你可以轻松地配置多集群 ingress , 该入口将公开在多个集群中运行的服务,并从离你所在位置最近的集群提供服务。\n局限性 Shipper 中的主要的局限性有: - Chart 限制:Chart 必须有一个部署对象。 Deployment 的名称必须使用 {{.Release.Name}} 模板化。 Deployment 对象应该有 apiVersion:apps/v1 。 - 基于 Pod 的流量切换:这里没有细粒度的流量路由,例如:发送 1% 的流量到新版本,它基于正在运行的 Pod 数量。 - 如果 Shipper 不工作了,新的 Pod 将获取不到流量。\nIstio Istio 不是一个部署工具,而是一个服务网格。 然而,它很令人感兴趣,因为它已经变得非常流行,并且允许流量管理,例如,将一定比例的流量发送到不同的服务和其他高级网络。\n在 GKE 中,只需在集群配置中选中复选框即可启用 Istio 。 在其它集群中,可以通过 Helm 手动安装。\n有了 Istio ,我们可以创建一个网关,通过 Ingress 网关处理所有外部流量,并创建虚拟服务来管理到我们服务的路由。 为此,只需找到 ingress 网关的 ip 地址并为其配置通配符 DNS 。 然后创建一个网关,通过 Ingress 网关路由所有外部流量。\napiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: public-gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - \u0026quot;*\u0026quot;  Isito 不管理应用的生命周期,只管理网络。 我们可以创建一个虚拟服务,为所有进入 ingress 网关的请求 向 pull request 或 master 分支中部署的服务发送 1% 的流量。\napiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: croc-hunter-jenkinsx namespace: jx-production spec: gateways: - public-gateway.istio-system.svc.cluster.local - mesh hosts: - croc-hunter.istio.example.org http: - route: - destination: host: croc-hunter-jenkinsx.jx-production.svc.cluster.local port: number: 80 weight: 99 - destination: host: croc-hunter-jenkinsx.jx-staging.svc.cluster.local port: number: 80 weight: 1  Flagger Flagger 是一个由 Weaveworks 赞助的使用了 Istio 的项目, 该项目使用 Prometheus 的指标进行自动化金丝雀发布和回滚。 它超越了 Isito 提供了基于指标的自动化渐进式发布和回滚。\nFlager 需要将 Istio与 Prometheus、Servicegraph 和某些系统的配置一起安装, 另外还要安装 Flager 控制器本身。 它也提供了一个 Grfana 面板来监控部署进度。\n部署 rollout 通过 Canary 对象定义, 它会生成主要的和金丝雀 Deployment 对象。 编辑 Deployment 时,例如要使用新的镜像版本, Flagger 控制器将负载从 0% 切换到 50% ,每分钟增加 10% ,然后它将切换到新的 deployment 或者如果响应错误和请求持续时间等指标失败则进行回滚。\n比较 此表总结了 Shipper 和 Flagger 在几个渐进式交付特性方面的优势和劣势。\n    Shipper Flagger     流量路由 k8s 原生的按 Pods 的百分比进行均衡 基于 Istio 的高级流量路由(请求的百分比)   部署进度 UI 无 Grafana 面板   支持的 Deployments 具有较强限制的 Helm charts 任何 Deployment   多集群部署 是 否   在不同命名空间(如 jx-staging 和 jx-production )的金丝雀部署或蓝绿部署 否 否,但是要做到它可以手动编辑虚拟服务   在不同集群的金丝雀部署或蓝绿部署 是,但是有点极客,使用一个新应用并将它链接到新区域 也许可以使用 Istio 多集群?   自动部署 否,操作者必须手动完成这些步骤 是,每分钟增加 10% 的流量,可配置的   自动回滚 否,操作者必须发现错误并手动完成这些步骤 是,基于 Prometheus 指标   必需品 无 Istio,Prometheus   告警  Slack    综上所述,我看到了 Shipper 在多集群管理和简单性方面的价值,它不需要 Kubernetes 以外的任何东西,但是它有一些严重的局限性。\nFlager 确实在自动部署和回滚以及对流量进行细粒度控制的过程中付出了额外的努力,它以更高的复杂性成本提供了所需的所有额外服务( Isito、Prometheus )。\n这里可以查看 Shipper、Isito 和 Flager 的示例代码。\n",
        "auhtor": "Carlos Sanchez",
        "translator": "donhui",
        "original": "https://blog.csanchez.org/2019/01/22/progressive-delivery-in-kubernetes-blue-green-and-canary-deployments/",
LinuxSuRen's avatar
LinuxSuRen 已提交
325
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
326
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
327
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
328 329 330 331 332 333 334 335
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-23-jenkins-master-shared-home/",
        "title": "关于 Jenkins master 共享 JENKINS_HOME 目录的实验",
        "type": "wechat",
        "date": "2019-04-23 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "你觉得能通过共享 JENKINS_HOME 目录实现 Jenkins master 的高可用吗?",
        "content": "  审校:王冬辉,linuxsuren\n Jenkins master 的高可用是个老大难的问题。和很多人一样,笔者也想过两个 Jenkins master 共享同一个 JENKINS_HOME 的方案。了解 Jenkins 原理的人,都会觉得这个方案不可行。但是真的不可行吗?\n由于工作原因,笔者需要亲自验证以上猜想。\nJENKINS_HOME 介绍 Jenkins 所有状态数据都存放文件系统的目录中,这个目录被称为 JENKINS_HOME 目录。\n实验环境介绍 笔者通过 Docker compose 启动两个独立的 Jenkins master,分别为 jenkins-a 和 jenkins-b。它们共用同一个 JENKINS_HOME 目录。相应的代码仓库的链接放在文章底部。\n将代码克隆到本地后,进入仓库,执行 docker-compose up -d 即可启动实验环境。启动完成,在浏览器中输入 http://localhost:7088 可访问 jenkins-a,jenkins-b 的地址是 http://localhost:7089 。但是你会发现它们启动后的界面显示是不一样的。\njenkins-b 的界面如下图所示:\n而 jenkins-a 的界面如下图所示:\n这时,将 jenkins-a 日志中的解锁密码(Unlock password)输入到 jenkins-b 的页面中,会得到报错信息:\nERROR: The password entered is incorrect, please check the file for the correct password  这时,再次 jenkins-b 日志中的解锁密码(Unlock password)输入到表单中即可进入下一步。接下来就是按照提示一步步完成了。在 jenkins-b 安装步骤的最后一步,我们设置了管理员的用户名密码:admin/admin。然后就算完成任务了。\n然后我们再在 jenkins-a 使用 admin/admin 进行登录,登录是报错的:用户密码不正确。\n接下来,执行 docker-compose restart jenkins-a 命令重启 jenkins-a。再次使用 admin/admin 就可以登录成功了。\n当两个 Jenkins 启动完成后,接下来开始做实验。\n实验1:创建任务 在 jenkins-a 创建任务 x,刷新 jenkins-b 的页面,jenkins-b 上会不会显示出任务 x ?\n结果:jenkins-b 不会出现任务 x。重启 jenkins-b 后,任务 x 出现在任务列表中。\n实验2:任务结果可见性 jenkins-a 上任务执行,jenkins-b 上能否看到任务执行结果?\njenkins-a 执行任务 x,并且执行成功。刷新 jenkins-b 看不到任何执行记录。重启 jenkins-b 后,可看到执行记录。\n实验3:两 master 同时执行同一任务 分别在两个 Jenkins master 上(几乎)开始同一个任务 x。其中一个任务的 build number 会更新,但是另一个不会。\n其中 jenkins-a 任务 x 的 build number 会升到 2,而 jenkins-b 保持的是 1。这时,单独执行 jenkins-b 的任务 x,日志会出现错误:\njenkins-b_1 | WARNING: A new build could not be created in job x jenkins-b_1 | java.lang.IllegalStateException: JENKINS-23152: /var/jenkins_home/jobs/x/builds/2 already existed; will not overwrite with x #2  实验4:编辑任务 jenkins-a 上设置任务 x 定时执行,刷新 jenkins-b 页面,任务 x 中并没有定时执行的设置。重启 jenkins-b 后,任务 x 更新。\n实验5:定时任务的结果是什么? 如果 jenkins-a 和 jenkins-b 两个任务均为定时任务,而且都生效了。它们运行结果是什么的呢?\n看到的现象是,两个任务都会按时执行,但是只有一个任务能将运行结果写入到磁盘中。界面如下图:\n另,从日志中,可以确认 jenkins-a 和 jenkins-b 确实按时执行了。如下图日志中,看出 jenkins-a 定时执行 #6 次构建时报错,因为 jenkins-b 已经执行过 #6 次构建了:\n小结 可以确认的是,当两个 Jenkins 进程共用同一个 JENKINS_HOME 目录时,其中一个 Jenkins 进程更新了 JENKINS_HOME 的内容,另一个是不会实时更新的。所以,同时启动两个 Jenkins master 共用同一个 JENKINS_HOME 的方案是不可行的。我们不能在 jenkins-a 挂了后,直接将流量切到 jenkins-b。因为 jenkins-b 必须重启。\n最后结论:多个 Jenkins master 共享同一个 JENKINS_HOME 的方案是无法使用 Jenkins master 的高可用。\n附录  Jenkins standby 实验环境:https://github.com/zacker330/jenkins-standby-experiment  ",
        "auhtor": "zacker330",
LinuxSuRen's avatar
LinuxSuRen 已提交
336 337 338
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
339 340
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
341 342 343 344 345 346 347 348
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-22-jenkins-weekly-2.173/",
        "title": "Jenkins 2.173 发布通知",
        "type": "wechat",
        "date": "2019-04-22 00:00:00 +0000 UTC",
        "tags": ["devops", "ai"],
        "description": "Jenkins 更新通知",
        "content": "本次更新移除了一些不太推荐的功能,请管理员及时关注,如果希望能恢复的旧的形态,可以按照下面的提示操作。\n另外,有一项重要的更新,使得我们可以把所有的中文本地化资源文件从 Jenkins 核心中移除。因此, 请关注 Jenkins 简体中文插件后续的动态,我们会及时完成所有的迁移。\n 移除对 CCtray 文件的内置支持。\n如果要继续使用该功能的话,请安装CCtray XML Plugin (issue 40750) 调整代码在远程计算节点上运行时的流刷新行为,使得具有更好的性能。\n这可能导致插件在节点集群上输出日志,但是没有刷新时,丢失消息。\n使用 -Dhudson.util.StreamTaskListener.AUTO_FLUSH=true 恢复自由风格构建之前的行为。注意,流水线的构建总是需要远程刷新。 (pull 3961) 增加用于将新创建的 API token 拷贝到粘贴板的按钮。 (issue 56733) 使得 Jenkins 经典界面上的表单提交按钮,对 Firefox 的 bug 修复是兼容的。 (issue 53462, Firefox bug 1370630) 如果一个工作空间已经被跨节点重连的流水线正在使用,那么,不会提供给新的构建。 (issue 50504) 从核心中移除 Mailer 相关的本地化字符串。确保你使用 Mailer Plugin 1.23。 (issue 55292) 从 Maven 控制台装饰器中适当地刷新输出。 (issue 56995) 开发者:更新 Stapler 1.256 到 1.257,增加对从任意插件中加载本地化 webapp 资源的支持。\n增加接口 jenkins.PluginLocaleDrivenResourceProvider 使得插件可以参与本地化资源的查找。 (JEP-216, 完整的变更日志) 开发者:SystemProperties 可以在计算节点中使用。 参考 SystemProperties#allowOnAgent。 (pull 3961) 开发者:增加 LineTransformationOutputStream#Delegating 使得更加方便。 (pull 3959) 开发者:hudson.util.ssh.SFTPClient 被移除。\n使用库 Trilead SSH 中的 com.trilead.ssh2.jenkins.SFTPClient 作为代替。 (issue 56166) 内部:更新 commons-beanutils 1.8.3 到 1.9.3。 (pull 3948)  ",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
349 350 351
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
352 353
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
354 355 356 357 358 359 360 361 362 363
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-19-the-business-value-of-cd/",
        "title": "持续交付的商业价值",
        "type": "wechat",
        "date": "2019-04-19 00:00:00 +0000 UTC",
        "tags": ["cd", "devops", "jenkins"],
        "description": "了解整体的持续交付如何帮助你的组织以更低的风险更快地交付和更新软件",
        "content": "持续交付使你能够以更低地风险、更快低交付新软件或是更新已有软件。\n降低风险很重要,但是,支持持续交付的流程将转化为对业务更重要的价值: - 加速价值时间。 一个小企业不需要一个 MBA 就可以认识到持续交付可以帮助他们完成工作。 一家大型企业已经规划了其价值流, 并且在整个大型组织中拥有复杂的投资和合约, 将发现持续交付有助于加速实现价值的时间。 - 数据驱动决策。 部署、度量和调整。 你仍然可以推动更大规模的发布,但你的流程将更适合于持续的数据收集。 这将缩短与客户的反馈循环。 它提高了你的反应能力,计划你的下一步行动,并保持领先的竞争力。 - 质量。 你持续发布的行为使你必须提高你的质量标准以及完全的自动化测试实践。 更好的质量意味着更快乐的客户、更低的成本、更少的消防演习和更少的计划外工作。 - 试验 = 创新。 开发人员和业务线可以自由地以较低的成本尝试新的想法, 从而释放出长期高投资发布周期背后的创新想法。 - 降低成本。 大的发布会有巨大的成本,如果出现错误会有严重的后果。 保持可交付成果处于可发布状态会降低交付成本。\n对企业来说,这些价值一起使持续交付成为真正的游戏变革者。 尽管可以在团队或项目级别开始采用和验证,但持续交付的本质是它以需要真正投资和自上而下承诺的方式跨越了组织边界。 选择与现有投资互补并共存的持续交付工具链是走向成功的关键一步, 特别是因为 CD 可以引导你的组织采用 DevOps 文化。\n持续交付为创建更好的软件开辟了全新的道路。 CD 是商业层面的热门话题,这有很多的原因: - 早期的采用者已经证明了它的价值。 主流采用者都观察到了它的优势,并感觉到竞争的刺痛,因为他们更灵活的竞争对手超过了他们。 - DevOps 作为一种运动获得了关注。 业务人员理解,在开发和运营之间有一个共同的理解,打破孤立的行为,并在整个组织内发展一种责任文化,是提高效率和上市时间的关键步骤。 在许多方面,持续交付等同于 DevOps 。 - 随着软件“吞噬世界”,商业领袖们越来越清楚 IT 必须被用作战略资产。 在正确处理安全性、可用性和合规性的同时,能够缩短交付时间、提高质量并快速适应变化是一项挑战。 持续交付,强调自动化和尽早的、直接的反馈,是实现这些目标的方法。 - 当你通过持续交付实现廉价的、低风险的试验时,你可以用更多的信息指导业务投资,并发现你可能完全错过的机会。\n持续交付正在改变企业使用其 IT 资产与客户和合作伙伴联系的方式。 CD 建立在多年来之不易的敏捷过程和持续集成经验的基础上, 将这些好处提升到业务级别,而不是简单地成为开发团队使用的技术, 并最终导致 DevOps 。 随着开发和运营人员学习如何协作和分担责任时,许多成功的关键都植根于组织和文化的变革。 无论是在组织范围内还是在本地,实现这种变革的技术工具链可能包括 Jenkins 。 CloudBees Jenkins 企业版,通过扩展开源 Jenkins 的使用范围, 提供了一个支持 Jenkins 混合模型(本地部署、云上部署或混合部署)的平台, 是组织在今天转向持续交付和在不久的将来实施 DevOps 的必要工具。\n更多内容请参见白皮书:持续交付的商业价值\n",
        "auhtor": "Brian Dawson",
        "translator": "donhui",
        "original": "https://dzone.com/articles/the-business-value-of-cd",
LinuxSuRen's avatar
LinuxSuRen 已提交
364
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
365 366
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
367 368 369 370 371 372 373 374 375 376
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-17-aiops/",
        "title": "AIOps:DevOps 的未来",
        "type": "wechat",
        "date": "2019-04-17 00:00:00 +0000 UTC",
        "tags": ["devops", "ai"],
        "description": "DevOps 将结合人工智能变得更加强大",
        "content": " DevOps 和云技术正在逼近极限 范式转变往往会产生意想不到的后果,这些后果可能需要数年才能被完全消化。 云计算就是一个很好的例子。 云计算迎来了灵活的基础设施和低资本要求的时代,由于资源只是一个API调用,工程师们无需等待部署。 然而,这一切只是开始。\n敏捷的公司利用云来打破开发和运维之间的隔阂,并采用敏捷方法以缩短开发周期,从而创造战略优势。 他们将应用程序生命周期中的工程师团队分工从之前的开发和测试变为部署和运维, 并创建了需要一系列新技能的职位。这些公司使用 CI/CD 和 DevOps 进一步推动自动化流水线, 以实现更快的交付。\n这样有隐患吗?去问你的 DevOps 团队 DevOps 团队的任务是维护一个工具链,以便自动交付新代码,按需扩展,以及五个 9 的正常运行时间。 在空闲时间,他们致力于提高性能和控制成本。 对于大的应用程序,可以有数千个虚拟机或容器,每个虚拟机或容器都有一堆软件, 还有负载平衡器和自动扩容等云服务,所有这些都必须进行配置和维护。 这一切都在不断发展中。\n我之前了解过的一个大型独角兽公司拥有数百名开发人员,每天更新代码超过 100 次, 云上有超过 4000 台虚拟机,每月收集数 PB 的数据。 而他们的 DevOps 团队只有十几个人手,直到去年才有 VP。 对他们来说,这是一个艰巨且繁重的任务。\n应付这无数的挑战已经超出了人类的能力范围。\n幸好,AIOps 正在成为一种解决方案。\nAIOps 一词是由 Gartner 创造的, 他将其解释为:\nAIOps 结合了大数据,机器学习和可视化技术,通过更强的洞察力来优化 IT 运维。 IT 的领导者应该开始部署 AIOps,以优化当前的性能分析,\n并在未来两到五年内将使用范围扩展到 IT 服务管理和自动化。 虽然 Gartner 创造了这个术语,但以我拙见,这还没达到标准。 他的定义以循环中的人为中心,以他的描述 AIOps 基本上是一种高级的大数据分析。 要解决 DevOps 困境,我们要定一个更高的目标。\n那么,AIOps 应该是什么? 我们先从它不应该是什么开始:一个对现有的运维系统的修饰,软件供应商将\u0026rdquo;以 AI 驱动\u0026rdquo;作为卖点。 这种情况已经发生了,当新的技术威胁到现有利益时,往往会发生这种情况。 仅仅向已有工具添加一个 API 是不够的,如果决策需要人为干预,那就不能算是 AIOps。\n这是一些 AIOps 的关键要求: - AIOps 系统从你的数据中学习并适应应用程序的工作模式 + 这意味着它不会每次都做同样的事情 - AIOps 系统无需人工干预即可制定和实施决策 + 你可以让人参与循环,直到你完全信任这个系统 - AIOps 系统能持续运行 + 它能成为你的交付中的标准单元\n向 AIOps 的过渡正处于起步阶段,但它的热度正在上升,而且已经有了成功案例。 风险投资正在下注,大小软件供应商都正在为市场带来新的解决方案。 从几年前的日志分析系统开始,自动化根本原因分析再到故障预测的出现。 入侵检测系统现在可以从异常流量中学习,有些甚至可以跨公司。 最近,预测自动扩容系统首次亮相。 Optune 和 Opsani 的 AI 系统能够判断虚拟机类型、实例和应用程序参数, 并使用客户现有的 DevOps 工具链和监控系统将它们部署到测试或生产环境中。\nDevOps 正在取代传统的 IT 部门,它的名称被改变,角色职能也发生了变化, 但 IT 部门要解决的挑战并没有消失,它们的规模被乘以了微服务架构的固有规模。 因此,我们需要为这些挑战设计新的系统,AIOps 必须在未来几年内发展, 超越 Gartner 的愿景,使 DevOps 能够应对发展的规模和速度。\n",
        "auhtor": "Bert Armijo",
        "translator": "p01son6415",
        "original": "https://dzone.com/articles/aiops-the-future-of-devops-is-here",
LinuxSuRen's avatar
LinuxSuRen 已提交
377
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
378 379
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
380 381
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-15-zabbix-monitor-jenkins/",
        "title": "使用 Zabbix 监控 Jenkins",
LinuxSuRen's avatar
LinuxSuRen 已提交
382
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
383 384 385 386 387 388 389
        "date": "2019-04-15 00:00:00 +0000 UTC",
        "tags": ["jenkins", "zabbix"],
        "description": "介绍了如何使用 Zabbix 监控 Jenkins",
        "content": "  本文假设读者已经了解 Jenkins 基本概念及插件安装,Zabbix 基础概念。基于 Zabbix 3.4,Jenkins 2.8 做实验\n 笔者最近的工作涉及到使用 Zabbix 监控 Jenkins。在谷歌上搜索到的文章非常少,能操作的就更少了。所以决定写一篇文章介绍如何使用 Zabbix 监控 Jenkins。\n下图为整体架构图:\n整体并不复杂,大体步骤如下:\n 在 Jenkins 上安装 Metrics 插件,使 Jenkins 暴露 metrics api。 配置 Zabbix server 及 agent 以实现监控及告警  为方便读者实验,笔者将自己做实验的代码上传到了 GitHub,链接在文章末尾。使用的是 Docker Compose 技术(方便一次性启动所有的系统)。\n接下来,我们详细介绍 Metrics插件及如何实现 Zabbix 监控 Jenkins。\n1. 使 Jenkins 暴露 metrics api 安装 Metrics 插件,在系统配置中,会多出“Metrics”的配置,如下图: 配置项不复杂。我们需要点击“Generate\u0026hellip;”生成一个 Access Key(生成后,记得要保存)。这个 Key 用于身份校验,后面我们会用到。\n保存后,我们在浏览器中输入URL:http://localhost:8080/metrics/\u0026lt;刚生成的 Access Key\u0026gt; 验证 Jenkins 是否已经暴露 metrics。如果看到如下图,就说明可以进行下一步了。\n1.1 Metrics 插件介绍 Metrics 插件是基于 dropwizard/metrics 实现。它通过4个接口暴露指标数据:/metrics,/ping,/threads,/healthcheck。\n1.2 Metrics 插件:/metrics 接口介绍 点击上图中的metric链接(http://localhost:8080/metrics/\u0026lt;Access Key\u0026gt;/metrics),它暴露了以下指标数据:\n{ version: \u0026quot;3.0.0\u0026quot;, gauges: {...}, counters: {...}, histograms: {...}, meters: {...}, timers: {...} }  从数据结构中可以看出它将指标分成 5 种数据类型: * Gauges:某项指标的瞬时值,例如:当前 Jenkins executor 的总个数(jenkins.executor.count.value) * Counters:某项指标的总数值,例如:http 请求活动连接数(http.activeRequests) * Meters:一段时间内,某事件的发生概率,例如:Jenkins成功执行的任务每分钟的执行次数(jenkins.runs.success.m1_rate) * Histogram:统计指标的分布情况。例如:Jenkins executor 数量的分布(jenkins.executor.count.history) * Timer:某项指标的持续时间。例如:Jenkins 任务等待时间(jenkins.job.waiting.duration)\n由于指标非常之多,我们就不分别介绍了。具体有哪些指标,读者朋友可以从代码仓库中的 metrics.json 文件了解。\n1.2 Metrics 插件其它接口介绍  /ping:接口返回 pong 代表 Jenkins 存活,如下图:  /threads:返回 Jenkins 的线程信息 /healthcheck:返回以下指标:  { disk-space: { healthy: true }, plugins: { healthy: true, message: \u0026quot;No failed plugins\u0026quot; }, temporary-space: { healthy: true }, thread-deadlock: { healthy: true } }  2. 配置 Zabbix server 与 agent 实现监控及告警 Zabbix server 通过与 Zabbix agent 进行通信实现数据的采集。而 Zabbix agent 又分为被动和主动两种模式。我们使用的是被动模式,也就是Zabbix server 向 agent 索要数据。\n所以,我们需要在 Zabbix agent 所在机器放一个获取 Jenkins 指标数据的脚本。再配置 Zabbix server 定时从该 agent 获取数据,最后配置触发器(trigger)实现告警。\n接下来的关于 Zabbix 的配置,基于我的 jenkins-zabbix 实验环境,读者朋友需要根据自己的实际情况变更。\n2.1 配置 Zabbix server 如何从 agent 获取指标数据 首先,我们需要告诉 Zabbix server 要与哪些 Zabbix agent 通信。所以,第一步是创建主机,如下图: 第二步,在主机列表中点击“Iterms”进行该主机的监控项设置: 第三步,进入创建监控项页面: 第四步,创建监控项: 这里需要解释其中几个选项为什么要那样填: * Type:是 Zabbix server 采集指标的类型,我们选择的是 Zabbix agent,如上文所说。 * Key:由于我们要监控的指标并不是 Zabbix 预定义的。所以,需要使用用户自定义参数来实现监控 Jenkins 指标。Key 填的值为:jenkins.metrics[gauges.jenkins.node.count.value.value]。jenkins.metrics是需要执行的真正的 Key 名称。而 [] 内是传给该 Key 对应的命令的参数。对于初学者,Zabbix 这部分概念非常不好理解。也许这样会更好理解:在使用用户自定义参数来实现监控的情况下,Zabbix server 会将这个 Key 发送给 agent,然后 agent 根据这个 Key 执行指定的 逻辑 以获取指标数据。这个 逻辑 通常是一段脚本(shell命令或Python脚本等)。而脚本也是可以传参的,[]中的值就是传给脚本的参数。具体更多细节,下文会继续介绍。 * Type of information:监控数据的数据类型,由于我们监控的是 Jenkins node 节点的个数,所以,使用数字整型。 * Update interval:指 Zabbix server 多长时间向 agent 获取一次数据,为方便实验,我们设置为 2s。\n到此,Zabbix server 端已经配置完成。\n2.2 配置 Zabbix agent 使其有能力从 Jenkins 获取指标数据 当 Zabbix agent 接收到 server 端的请求,如 jenkins.metrics[gauges.jenkins.node.count.value.value]。Zabbix agent 会读取自己的配置(agent 启动时会配置),配置内容如下:\n## Zabbix Agent Configuration File for Jenkins Master UserParameter=jenkins.metrics[*], python /usr/lib/zabbix/externalscripts/jenkins.metrics.py $1  根据 Key 名称(jenkins.metrics)找到相应的命令,即:python /usr/lib/zabbix/externalscripts/jenkins.metrics.py $1。并执行它,同时将参数 gauges.jenkins.node.count.value.value 传入到脚本 jenkins.metrics.py 中。jenkins.metrics.py 需要我们在 Jenkins agent 启动前放到 /usr/lib/zabbix/externalscripts/ 目录下。\njenkins.metrics.py 的源码在 jenkins-zabbix 实验环境中可以找到,篇幅有限,这里就简单介绍一下其中的逻辑。\njenkins.metrics.py 所做的事情,无非就是从 Jenkins master 的 metrics api 获取指标数据。但是由于 api 返回的是 JSON 结构,并不是 Zabbix server 所需要的格式。所以,jenkins.metrics.py 还做了一件事情,就是将 JSON 数据进行扁平化,比如原来的数据为:{\u0026quot;gauges\u0026quot;:{\u0026quot;jenkins.node.count.value\u0026quot;: { \u0026quot;value\u0026quot;: 1 }}} 扁平化后变成: gauges.jenkins.node.count.value.value=1。\n如果 jenkins.metrics.py 脚本没有接收参数的执行,它将一次性返回所有的指标如:\n...... histograms.vm.memory.pools.Metaspace.used.window.15m.stddev=0.0 histograms.vm.file.descriptor.ratio.x100.window.5m.p75=0.0 histograms.vm.memory.pools.PS-Old-Gen.used.window.5m.count=4165 gauges.vm.runnable.count.value=10 timers.jenkins.task.waiting.duration.mean=0.0 histograms.vm.memory.non-heap.committed.history.p99=123797504.0 gauges.vm.memory.pools.PS-Eden-Space.used.value=19010928 gauges.jenkins.node.count.value.value=1 histograms.vm.memory.pools.Code-Cache.used.window.15m.mean=44375961.6 ......  但是,如果接收到具体参数,如 gauges.jenkins.node.count.value.value ,脚本只返回该参数的值。本例中,它将只返回 1。\njenkins.metrics.py 脚本之所以对 JSON 数据进行扁平化,是因为 Zabbix server 一次只拿一个指标的值(这点需要向熟悉 Zabbix 的人求证,笔者从文档中没有找到明确的说明)。\n注意:在 2.1 节中,如果 Key 值设置为:jenkins.metrics,Zabbix server 不会拿 jenkins.metrics.py 返回的所有的指标值自动创建对应的监控项。所以,Key 值必须设置为类似于 jenkins.metrics[gauges.jenkins.node.count.value.value] 这样的值。\n3. 配置 Zabbix server 监控指标,并告警 在经过 2.2 节的配置后,如果 Zabbix server 采集到数据,可通过_Monitoring -\u0026gt; Latest data -\u0026gt; Graph_菜单(如下图),看到图形化的报表:\n图形化的报表: 有了指标数据就可以根据它进行告警了。告警在 Zabbix 中称为触发器(trigger)。如下图,我们创建了一个当 Jenkins node 小于 2 时,就触发告警的触发器:\n至于最终触发器的后续行为是发邮件,还是发短信,属于细节部分,读者朋友可根据自己的情况进行设置。\n小结 在理解了 Zabbix server 与 agent 之间的通信原理的前提下,使用 Zabbix 监控 Jenkins 是不难的。笔者认为难点在于自动化整个过程。上文中,我们创建主机和添加监控项的过程,是手工操作的。虽然 Zabbix 能通过自动发现主机,自动关联模板来自动化上述过程,但是创建”自动化发现主机“和”自动关联动作“依然是手工操作。这不符合”自动化一切“的”追求“。\n最后,如果读者朋友不是历史包袱原因而选择 Zabbix,笔者在这里推荐 Prometheus,一款《Google 运维解密》推荐的开源监控系统。\n附录  Metrics 插件:https://wiki.jenkins.io/display/JENKINS/Metrics+Plugin dropwizard/metrics:https://metrics.dropwizard.io/4.0.0/ Zabbix 监控项类型:https://www.zabbix.com/documentation/3.4/zh/manual/config/items/itemtypes metrics.json: https://github.com/zacker330/jenkins-zabbix/blob/master/metrics.json jenkins-zabbix 实验环境:https://github.com/zacker330/jenkins-zabbix Prometheus:https://prometheus.io/  ",
        "auhtor": "zacker330",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
390
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
391 392
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
393 394 395 396
        "uri": "https://jenkins-zh.cn/about/social-media/",
        "title": "社交媒体",
        "type": "about",
        "date": "2019-04-12 14:26:05 +0800 +0800",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
397
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
398 399
        "description": "Jenkins 中文社区的社交媒体",
        "content": "社区所有的技术、活动类的文章都会同步发布到下面的社交媒体平台上。\n   媒体 方式 负责人     微信公众号 人工  LinuxSuRen    开源中国 人工  donhui    CSDN 人工  P01son6415    简书 人工  yJunS    掘金 人工  zacker330    腾讯 云+社区 自动同步  LinuxSuRen    企鹅号 自动同步  LinuxSuRen    百家号 自动同步  LinuxSuRen     ",
LinuxSuRen's avatar
LinuxSuRen 已提交
400 401 402 403
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
404 405
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
406 407 408 409 410 411 412 413
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-12-brief-analysis-the-encryption-algorithm-of-the-built-in-jenkins-user-database/",
        "title": "简析 Jenkins 专有用户数据库加密算法",
        "type": "wechat",
        "date": "2019-04-12 00:00:00 +0000 UTC",
        "tags": ["jenkins"],
        "description": "本文对 Jenkins 专有用户数据库加密算法进行简要分析",
        "content": " 认识Jenkins专有用户数据库 Jenkins 访问控制分为:安全域(即认证)与授权策略。\n其中,安全域可以采用三种形式,分别为:Jenkins 专有用户数据库、LDAP、Servlet 容器代理。 在哪里看到加密后的用户密码信息? Jenkins 专有用户的数据信息存放位置:$JENKINS_HOME/users/\n每个用户的相关信息存放在各自的 config.xml 文件中: $JENKINS_HOME/users/$user/config.xml\n在 config.xml 文件中的 passwordHash 节点可以看到用户密码加密后的密文哈希值: 用户密码是用什么算法加密的呢? 那么问题来了,用户密码是用何种加密方式加密的呢?可否通过解密密文得到明文呢?\n在 GitHub 上查看其源码,通过关键字 #jbcrypt 搜索定位到 HudsonPrivateSecurityRealm.java 这个文件。 HudsonPrivateSecurityRealm.java 具体路径是:jenkins/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java\n源码片段如下:\n/** * {@link PasswordEncoder} that uses jBCrypt. */ private static final PasswordEncoder JBCRYPT_ENCODER = new PasswordEncoder() { public String encodePassword(String rawPass, Object _) throws DataAccessException { return BCrypt.hashpw(rawPass,BCrypt.gensalt()); } public boolean isPasswordValid(String encPass, String rawPass, Object _) throws DataAccessException { return BCrypt.checkpw(rawPass,encPass); } }; /** * Combines {@link #JBCRYPT_ENCODER} and {@link #CLASSIC} into one so that we can continue * to accept {@link #CLASSIC} format but new encoding will always done via {@link #JBCRYPT_ENCODER}. */ public static final PasswordEncoder PASSWORD_ENCODER = new PasswordEncoder() { /* CLASSIC encoder outputs \u0026quot;salt:hash\u0026quot; where salt is [a-z]+, so we use unique prefix '#jbcyrpt\u0026quot; to designate JBCRYPT-format hash. '#' is neither in base64 nor hex, which makes it a good choice. */ public String encodePassword(String rawPass, Object salt) throws DataAccessException { return JBCRYPT_HEADER+JBCRYPT_ENCODER.encodePassword(rawPass,salt); } public boolean isPasswordValid(String encPass, String rawPass, Object salt) throws DataAccessException { if (encPass.startsWith(JBCRYPT_HEADER)) return JBCRYPT_ENCODER.isPasswordValid(encPass.substring(JBCRYPT_HEADER.length()),rawPass,salt); else return CLASSIC.isPasswordValid(encPass,rawPass,salt); } private static final String JBCRYPT_HEADER = \u0026quot;#jbcrypt:\u0026quot;; };  通过分析该源码得知: 1. 明文通过 jbcrypt 算法得到密文 encPass 2. 密文的格式为:salt: encPass,其中以 #jbcrypt 表示 salt 作为数据头\njbcrypt 是什么? jbcrypt 是 bcrypt 加密工具的 java 实现。 它的 API 非常简单,DEMO 如下,在 HudsonPrivateSecurityRealm.java 中可以看到加密和校验时使用了如下 API:\n// Hash a password for the first time String hashed = BCrypt.hashpw(password, BCrypt.gensalt()); // gensalt's log_rounds parameter determines the complexity the work factor is 2**log_rounds, and the default is 10 String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12)); // Check that an unencrypted password matches one that has previously been hashed if (BCrypt.checkpw(candidate, hashed)) System.out.println(\u0026quot;It matches\u0026quot;); else System.out.println(\u0026quot;It does not match\u0026quot;);  经验证,用 jbcrypt 对同一个明文加密后因为 salt 一般不同,加密后的密文一般不同。\nbcrypt 精要概况  bcrypt 是不可逆的加密算法,无法通过解密密文得到明文。 bcrypt 和其他对称或非对称加密方式不同的是,不是直接解密得到明文,也不是二次加密比较密文,而是把明文和存储的密文一块运算得到另一个密文,如果这两个密文相同则验证成功。  总结 综上, Jenkins 专有用户数据库使用了 jbcrypt 加密, jbcrypt 加密是不可逆的,而且对于同一个明文的加密结果一般不同。\n",
        "auhtor": "donhui",
LinuxSuRen's avatar
LinuxSuRen 已提交
414 415 416
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
417 418
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
419 420
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-10-getting-started-with-docker-for-java-applications/",
        "title": "Java 应用使用 Docker 的入门指南:建立一个 CI/CD 流水线",
LinuxSuRen's avatar
LinuxSuRen 已提交
421
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
422 423 424 425 426 427 428
        "date": "2019-04-10 00:00:00 +0000 UTC",
        "tags": ["cd", "ci", "docker", "jenkins", "pipeline"],
        "description": "本文是容器化现有 Java 应用以及使用 Jenkins 建立一个端到端部署流水线的指南",
        "content": " Docker 已经非常出名并且更多的组织正在转向基于 Docker 的应用开发和部署。这里有一个关于如何容器化现有 Java Web 应用以及使用 Jenkins 为它建立一个端到端部署流水线的快速指南。\n为此我使用了非常著名的基于 Spring 的宠物商店应用,它代表了一个很好的示例,因为大多数应用都遵循类似的体系结构。\n步骤  构建宠物商店应用。 运行一次 Sonar 质量检查。 使用该 Web 应用准备 Docker 镜像。 运行容器以及执行集成测试。 如果所有测试成功,推送该镜像到一个 dockerhub 账户。  所有的代码都在这里。\n这里是可用于以上步骤的 Jenkins 流水线代码:\nnode { stage 'checkout' git 'https://gitlab.com/RavisankarCts/hello-world.git' stage 'build' sh 'mvn clean install' stage('Results - 1') { junit '**/target/surefire-reports/TEST-*.xml' archive 'target/*.jar' } stage 'bake image' docker.withRegistry('https://registry.hub.docker.com','docker-hub-credentials') { def image = docker.build(\u0026quot;ravisankar/ravisankardevops:${env.BUILD_TAG}\u0026quot;,'.') stage 'test image' image.withRun('-p 8888:8888') {springboot -\u0026gt; sh 'while ! httping -qc1 http://localhost:8888/info; do sleep 1; done' git 'https://github.com/RavisankarCts/petclinicacceptance.git' sh 'mvn clean verify' } stage('Results') { junit '**/target/surefire-reports/TEST-*.xml' archive 'target/*.jar' } stage 'push image' image.push() } }  最初的步骤只是检出代码并运行构建。有趣的部分从这个步骤开始,它使用 dockerhub 凭证在 Docker 上下文中运行。\nstep 3 'bake image' docker.withRegistry('https://registry.hub.docker.com','docker-hub-credentials')  这个步骤构建 Docker 镜像。Docker build 命令将 dockerhub 仓库名称和 tag 名称作为一个参数,而构建位置作为另一个参数。\ndef image = docker.build(\u0026quot;dockerhub registry name\u0026quot;:\u0026quot;tag name\u0026quot;,'location of docker file') def image = docker.build(\u0026quot;ravisankar/ravisankardevops:${env.BUILD_TAG}\u0026quot;,'.')  这里使用 Dockerfile 来构建 Docker 镜像。 Dockerfile 的内容如下:\nFROM tomcat:8 ADD target/*.war /usr/local/tomcat/webapps  下一步是运行镜像并执行测试:\nstage 'test image' image.withRun('-p 8888:8888') { springboot -\u0026gt; sh 'while ! httping -qc1 http://localhost:8888/info; do sleep 1; done' git 'https://github.com/RavisankarCts/petclinicacceptance.git' sh 'mvn clean verify' }  withRun 步骤用来帮你运行你刚才构建的 Docker 镜像并暴露应用可以暴露的端口。我有另一个测试代码库,它被构建和执行,将对正在运行的镜像运行测试。\n最后一步是推送该镜像到一个 dockerhub registry 或者你的组织建立的任何内部 registry 。\nstage('Results') { junit '**/target/surefire-reports/TEST-*.xml' archive 'target/*.jar' } stage 'push image' image.push()  ",
        "auhtor": "Ravi Sankar",
        "translator": "donhui",
        "original": "https://dzone.com/articles/getting-started-with-docker-for-java-applications",
LinuxSuRen's avatar
LinuxSuRen 已提交
429
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
430 431
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
432 433
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-08-becoming-contributor-intro/",
        "title": "介绍:成为一名 Jenkins 贡献者的旅程",
LinuxSuRen's avatar
LinuxSuRen 已提交
434
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
        "date": "2019-04-08 00:00:00 +0000 UTC",
        "tags": ["jenkins", "community", "developer", "contributing", "newcomer"],
        "description": "如何从零开始成为开源社区贡献者",
        "content": " 作为一名软件工程师,这些年来在我工作过的不同公司里用到过许多开源软件(包括框架、库、工具等)。 然而,在此之前我从没有以一名贡献者的身份参与过开源项目。\n自从我向 Jenkins 提交第一个简单又滑稽的 commit 已经过去六个月(2018 年 9 月)了, 我也尝试过作出更多贡献。然而总的来说,向开源项目贡献代码是具有挑战的, 特别是像 Jenkins 这样有着很长生命周期的项目,项目中不乏遗留代码和系统知识。 它通常难以入手,也很难想到一个计划来持续贡献使你的付出从长远看来是有意义的。\n对于 Jenkins 社区来说,我在尝试加入社区时所遇到的困难是其它人也有可能会面临的, 因此我决定分享我成为 Jenkins 活跃贡献者的心路历程。\n我计划大概每月发布一篇博文来描述我的这段旅程,我将从简单容易入手的项目开始, 随着时间推移再介绍更加复杂的项目。\n从哪开始 jenkins.io 要成为 Jenkins 的贡献者,首先会看到的就是 jenkins.io, 在顶部导航中\u0026rdquo;社区\u0026rdquo;下拉列表里第一个\u0026rdquo;参与\u0026rdquo;的链接就能将我们带到\u0026rdquo;参与和贡献\u0026rdquo;这个页面。\n在这个页面中列举了我们能够参与 Jenkins 项目和社区的许多方式。尽管它展示了所有可能的选项供读者选择,但一下子看上去令人有些无所适从。\n这个页面被分成了左右两个部分,左边提供了参与社区的方法,右边是向社区贡献的方法。\n参与社区的建议 在“参与和贡献”页面的左侧是有关参与社区的建议,其中包括结交他人、审阅修改或者提供反馈信息。\n这里面最让我困惑的是沟通渠道,里面列出的沟通渠道有 几个邮件列表 还有 IRC 和 Gitter 频道。\n当我第一次尝试参与时,我订阅了许多邮件列表和几个 IRC 和 Gitter 频道,但我很快发现里面有重要的讨论正在进行, 并且活跃的讨论中多数是关于特定的用户或开发者的问题。因此,我不建议你一开始在这上面花太多时间, 除非你是要为其他用户提供帮助(当你是经验丰富的 Jenkins 用户时可能会有这种情况)或者你已经有一个明确的问题需要提问。\n看一看社区成员如何互相帮助是好事,但是对新人来说它的信息量过于庞大。如果你的兴趣在于向 Jenkins 项目作贡献(不管是翻译、文档还是代码), 这些对话不会对你有太大的帮助。\n向社区贡献的建议 在“参与和贡献”页面的右侧有一些关于如何贡献的建议,主要分为:编写代码,翻译,文档和测试。\n在之后的博客中,我将介绍所有的这些贡献类型,以及如何参与的建议包括如何审阅 Pull Requests(PRs)或提供反馈 (反馈问题或者复现其它用户反映过的问题,提供额外信息来帮助维护者复现和修复它们。)\n开源之旅的第一次贡献 当看到「参与和贡献」页面时,我发现我可以帮助改进这个页面的一些内容。本来我打算选择其中一个作为这篇文章的第一个例子,但当我阅读贡献指南时, 我发现了一个更简单的贡献。我认为它可以更好的说明开始贡献社区是多么的简单,于是我决定就用它来当例子。\n网站代码仓库 在「文档」菜单中有一个链接 jenkins.io 的贡献指南, 这个 CONTRIBUTING 文件是大多数开源项目代码仓库的根目录中都会有的常见文件。\n点击链接跳转到 jenkins.io 代码仓库,这个仓库包含了网站的源代码其中也包括这篇文章。 事实上,我首先查看的是贡献指南,以便了解如何为网站做出贡献的相关信息。\n找到一个失效链接 通过阅读贡献指南,我了解了 Awestruct 静态站点生成器,它是用于将代码仓库中的 AsciiDoc 源文件转换为网页的工具。 然而,当我点击链接想查看更多信息时,我发现这个链接失效了——域名已经过期。\n为何不修复它? 这是一个好机会,我用它来向新人展示开始贡献是多么容易。\n创建代码仓库分支 第一步,通常是 fork 代码仓库,并克隆到本地。\n进行修改 下一步就是对相应文件进行修改。我创建了一个新的分支 “alternative-awestruct-link” 并对它作了如下修改:\n确保构建正确并且通过测试 尽管在这次的情况下,我的贡献并不针对网站的实际页面,而是对贡献指南(因此不太可能造成什么破坏),但是最好习惯每个贡献都遵循规范流程, 这样才能确保之后有所改变时构建也能够正常进行。\n如贡献指南所述,要构建此项目,我们只需在代码仓库的根目录中以默认的 “make” 作为 target 来运行构建命令。\n一旦命令执行完成,如果没有出现报错,我们就可以进行下一步:创建 Pull Request\n创建 PR 把我的改动 commit 并 push 到远程库以后,我就需要创建一个 PR 了。 有一个简单的方法,只需单击推送完成后在 git 日志中显示的链接,如果愿意的话也可以通过 GitHub UI 创建 PR; 或者甚至可以使用 GitHub CLI 的 “hub” 来完成它。\n这次我直接点击了链接,它将我跳转到 Github 的创建 PR 页面,我在这个页面上添加描述并创建了 PR。\n当创建这个代码仓库的 PR 后,可以发现有一些检查开始运行。Jenkins 代码仓库配置了 “Jenkins on Jenkins”, 它会为每个代码仓库运行 Jenkinsfile 中描述的相应 CI 流水线。\n检查结束后,可以在 PR 中看到结果:\n如果想看到执行的细节,可以点击 “Show all checks” 链接:\nPR review 现在我们已经创建好了 PR 并通过了自动测试,只需要等待代码 review 了。\n一旦 PR 被审核通过然后被 merge,你的贡献就会被整合到代码仓库的主分支并成为下次版本更新的一部分。\n我已经作出了贡献! 我做的这个贡献是微不足道的,它的复杂性很小,如果你的目标在于为 Jenkins 项目本身贡献代码,它可能看起来不是很有趣。\n然而对于我作为一名贡献者,这是一个熟悉代码库、贡献指南、jenkins.io 网站背后的技术的很好的方式; 并且最重要的是,我开始“放下恐惧”,为 Jenkins 这样的开源项目做出了贡献。\n因此,如果你同我一样,请不要犹豫。来吧,找到你自己的第一个贡献。每一个细节都很重要!\n",
        "auhtor": "romenrg",
        "translator": "P01son6415",
        "original": "https://jenkins.io/blog/2019/03/29/becoming-contributor-intro/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-03-the-benefits-and-challenges-of-continuous-integration/",
        "title": "持续集成的收益与挑战",
        "type": "wechat",
        "date": "2019-04-03 00:00:00 +0000 UTC",
        "tags": ["continuous integration", "ci"],
        "description": "本文介绍了持续集成的定义,并解释了实施CI的各种收益与挑战",
        "content": " 毫无疑问,持续集成( CI )已成为一个软件开发的主流原则。CI 的收益在业界众所周知的,并且很难找到反对实施它的人。\n在这里,我想把那些收益收集起来放到一个中心化的地方。但是我认为扮演反面角色并试图找出持续集成的弊端或挑战也是很有趣的。\n什么是持续集成? 从根本上说, 持续集成( CI )是一种开发实践,开发人员每天都要将代码集成到共享的仓库中。在该仓库中,代码被自动构建进行验证用来在这个流程中检验尽早的发现任何问题。这允许团队花更少的时间回溯,而花更多的时间构建新特性。\n持续集成的收益 1、缓解风险 据 Martin Fowler 说,持续集成的最大收益是减轻风险。由于延迟了代码集成,团队将不断增加合并冲突的数量和严重性。当团队频繁集成(使用自动构建),他们减轻了潜在风险的数量,因为他们总是知道系统的当前状态。\n2、质量保证 实施持续集成的团队对他们的操作更有信心。他们知道自动构建会立即捕获缺陷,这使他们能够保证质量。 他们也不会猜测系统中 bug 的数量,这允许他们能够向队友提供准确的数量,并为客户提供更好的服务。\n3、提高可见性和加强团队合作 自动构建为团队提供了对其系统的完全可见性。他们知道问题的数量,并能快速的解决问题。提高可见性可以让团队有机会在小问题变成大之前通过协作解决。\n持续集成的挑战 1、组织文化变革 一些企业更喜欢传统的方法,并且可能很难实施持续集成。 他们必须对员工进行再培训,这就意味着要对现有的业务进行大修。管理者可能会抵制因为持续集成并不能帮助他们实现公司的直接目标(例如:金钱在质量之上)。\n2、难以维护 构建一个自动化的代码仓库不是一个简单的任务。 团队必须构建适当的测试套件,并花时间编写测试用例,而不是开发代码。 起初,这可能会让他们放慢速度,让他们对按时完成自己的项目失去信心。如果测试套件不稳定,它可能在某些天内完美地工作,但其他天可能不起作用。 然后团队将不得不花费更多的时间来弄清楚发生了什么。\n3、大量的错误信息 对于较大的开发团队,他们可能每天都会看到 CI 错误消息,并开始忽略它们,因为它们还有其他任务和关注点。 他们可能会开始将一个破坏的构建视为一个正常的事情,并且缺陷可能开始堆积在一起。\n",
        "auhtor": "Jeffrey Lee",
LinuxSuRen's avatar
LinuxSuRen 已提交
453
        "translator": "donhui",
LinuxSuRen's avatar
LinuxSuRen 已提交
454
        "original": "https://dzone.com/articles/the-benefits-and-the-drawbacks-of-continuous-integ",
LinuxSuRen's avatar
LinuxSuRen 已提交
455
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
456 457
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
458 459
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-18-weekly-version/",
        "title": "Jenkins 更新通知",
LinuxSuRen's avatar
LinuxSuRen 已提交
460
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
461 462 463 464 465
        "date": "2019-03-20 00:00:00 +0000 UTC",
        "tags": ["weekly"],
        "description": "Jenkins LTS、Weekly 以及简体中文插件更新",
        "content": " Jenkins LTS 2.164.1 更新内容如下:  Java 11 现已全面支持。 自 2.150.x 开始在 Java 11 上运行 Jenkins 的多项改进,包括:支持插件在它们的元数据中申明最小 Java 版本,并拒绝加载不兼容的插件,以及当运行在 Java11 上时安装新的 JAXB 插件后允许使用 JAXB 的 API. (博客发布的申明, 运行在 Java 11, 升级到 Java 11, issue 52012, issue 52282, issue 55076, issue 55048, issue 55980, issue 55681, issue 52285) 当列出一个指定目录时 list-jobs 不再进行递归。 (issue 48220) 增加一个新的 CLI 命令 disable-plugin 来禁用一个或多个已安装的插件,并可以选择同时重启 Jenkins. (issue 27177) 更新 Trilead SSH 库以支持 OpenSSH 使用 AES256-CTR 加密。 (issue 47603, issue 47458, issue 55133, issue 53653) 在 Jenkins CLI 中增加对 ed25519 关键算法的支持。 (issue 45318) 减少以 ZIP 格式下载归档或者工作空间文件时 SECURITY-904 对性能的影响。 (issue 55050) 在插件向导中增加语言分类,并会根据浏览器的语言设置自动安装本地化插件。 (pull 3626) Windows Service Wrapper 从 2.1.2 更新到 2.2.0,Windows Agent Installer 从 1.9.3 更新到 1.10.0,支持禁用、重命名以及归档服务日志。 (pull 3854, Windows Service Wrapper 变更日志, Windows Agent Installer Module 变更日志) SSHD 模块从 2.5 更新到 2.6,当自定义值设置为 org.jenkinsci.main.modules.sshd.SSHD.idle-timeout system property 时,设定一个合适的 Apache Mina 空闲超时时间。 (issue 55978, 全部变更日志) 开发者: 登陆和注册页面在 2.129 中重新设计了,现在可以从多个插件中接收风格贡献 (SimplePageDecorator 的视图页面 footer) (issue 54325)  Jenkins 每周版 2.168 更新内容如下:  优化移动端的登陆、加载和重启界面。 通知管理员关于潜在的不安全的权限设置,导致以虚拟系统用户运行构建。 在 Microsoft Docker 中的 Windows Server 2016 上工作空间和归档文件的浏览不可用。(在 2.154 中引入) 开发者: StringParameterValue.getValue() 现在返回 String 以避免不必要的类型转换。  简体中文插件 0.0.14 新增了多条中文词条,更多细节从查看变更日志。\n",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
466 467 468
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
469 470
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
471 472
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-20-cdf-launch/",
        "title": "Jenkins 正在加入持续交付基金会",
LinuxSuRen's avatar
LinuxSuRen 已提交
473
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
474 475 476 477 478 479
        "date": "2019-03-20 00:00:00 +0000 UTC",
        "tags": ["cdf", "general", "community"],
        "description": "Jenkins 社区牵头成立 CDF",
        "content": "今天Linux 基金会与 CloudBees、Google 和一些其他公司启动了一个新的开源软件基金会,也就是持续交付基金会(CDF). CDF 相信持续交付的力量,它旨在培养与支持开源生态,以及厂商中立的项目。\nJenkins 的贡献者们已经决定,我们的项目应该加入这个新的基金会。 实际上,这样的讨论持续了多年,大致的动机简洁摘要在这里。\n此时,作为一名用户,又意味着什么呢?\n 首先,不会有大的中断。还是同样的人,URL 地址不会变,也会有正常的发布。决策方式也会延续,pull request 也不会发生变化。改变会逐步的进行。\n 这是 Jenkins 项目在这个领域的成熟和重要性的又一证明。在全球有25万个 Jenkins 在运行着,这着实从 IoT 到游戏、从云原生应用到机器学习项目撼动着整个软件研发的世界。对于任何寻求开放异构 DevOps 策略的人来说, Jenkins 是一个显然、安全的选择。\n CDF 创建了一个公平竞争的环境,这被组织中的贡献者所熟知,同时也会带来更多的贡献者,让 Jenkins 发展的更好、更快。在过去的几年里, Jenkins 项目正在稳步地增长,更多的结构使之变得清晰起来,CDF 是这一轨迹中的最新一步。\n 任何认真的研发团队都会把多种工具和服务结合起来,以覆盖整个软件研发领域。这些团队为了把这些工具集成起来投入了大量的工作。 Jenkins 将会在 CDF 旗下与其他项目紧密合作,使得这些软件之间减少重复。\n 我们的用户作为从业者尝试在他们的组织中改善软件研发流程。他们认为 CI/CD 和自动化可以释放组织所需要的生产力,但对他们的组织而言,并不总是那么显著。因此,我们的用户往往无法得到必要的支持。CDF 将会倡导持续交付的实践,因为这并不是来自某个厂商或项目,它将会联系可以提供帮助的人。\n  因此,我希望你能明白为什么我们会对此感到如此兴奋!\n实际上,对我们来说,已经为这个想法努力了将近两年。毫不夸张地说,整个 CDF 的想法 源自 Jenkins 项目。\n为此,已经有很多人在幕后做了大量的工作。但有些人扮演了举足轻重的角色,我须亲自感谢他们。为 Chris Aniszczyk 的耐心、坚持,R. Tyler Croy 酝酿并推动着这个想法,Tracy Miranda 将这些想法变成事实。\n",
        "auhtor": "kohsuke",
        "translator": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
480 481
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
482 483
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
484 485 486 487 488 489 490 491
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-13-electron-pipeline-demo/",
        "title": "Electron 应用的流水线设计",
        "type": "wechat",
        "date": "2019-03-13 00:00:00 +0000 UTC",
        "tags": ["Jenkins", "Pipeline", "Electron"],
        "description": "跨平台构建的流水线 demo",
        "content": "  审校:LinuxSuRen(https://github.com/LinuxSuRen)\n 面向读者:需要了解 Jenkins 流水线的基本语法。\nElectron 是由 Github 开发,用 HTML,CSS 和 JavaScript 来构建跨平台桌面应用程序的一个开源库。\n本文将介绍 Electron 桌面应用的流水线的设计。\n但是如何介绍呢?倒是个大问题。笔者尝试直接贴代码,在代码注释中讲解。这是一次尝试,希望得到你的反馈。\n完整代码 pipeline { // 我们决定每一个阶段指定 agent,所以, // 流水线的 agent 设置为 none,这样不会占用 agent agent none // 指定整条流水线的环境变量 environment { APP_VERSION = \u0026quot;\u0026quot; APP_NAME = \u0026quot;electron-webpack-quick-start\u0026quot; } stages { stage(\u0026quot;生成版本号\u0026quot;){ agent {label \u0026quot;linux\u0026quot; } steps{ script{ APP_VERSION = generateVersion(\u0026quot;1.0.0\u0026quot;) echo \u0026quot;version is ${APP_VERSION}\u0026quot; }} } stage('并行构建') { // 快速失败,只要其中一个平台构建失败, // 整次构建算失败 failFast true // parallel 闭包内的阶段将并行执行 parallel { stage('Windows平台下构建') { agent {label \u0026quot;windows \u0026amp;\u0026amp; nodejs\u0026quot; } steps { echo \u0026quot;${APP_VERSION}\u0026quot; } } stage('Linux平台下构建') { agent {label \u0026quot;linux \u0026amp;\u0026amp; nodejs\u0026quot; } // 不同平台可能存在不同的环境变量 // environment 支持阶段级的环境变量 environment{ SUFFIX = \u0026quot;tar.xz\u0026quot; APP_PLATFORM = \u0026quot;linux\u0026quot; ARTIFACT_PATH = \u0026quot;dist/${APP_NAME}-${APP_PLATFORM}-${APP_VERSION}.${SUFFIX}\u0026quot; } steps { script{ // Jenkins nodejs 插件提供的 nodejs 包装器 // 包装器内可以执行 npm 命令。 // nodejs10.15.2 是在 Jenkins 的全局工具配置中添加的 NodeJS 安装器 nodejs(nodeJSInstallationName: 'nodejs10.15.2') { // 执行具体的构建命令 sh \u0026quot;npm install yarn\u0026quot; sh \u0026quot;yarn version --new-version ${APP_VERSION}\u0026quot; sh \u0026quot;yarn install\u0026quot; sh \u0026quot;yarn dist --linux deb ${SUFFIX}\u0026quot; // 上传制品 uploadArtifact(\u0026quot;${APP_NAME}\u0026quot;, \u0026quot;${APP_VERSION}\u0026quot;, \u0026quot;${ARTIFACT_PATH}\u0026quot;) }}} // 将括号合并是为了让代码看起来紧凑,提升阅读体验。下同。 } stage('Mac平台下构建') { agent {label \u0026quot;mac \u0026amp;\u0026amp; nodejs\u0026quot; } stages { stage('mac 下阶段1') { steps { echo \u0026quot;staging 1\u0026quot; } } stage('mac 下阶段2') { steps { echo \u0026quot;staging 2\u0026quot; } } } } } } stage(\u0026quot;其它阶段,读者可根据情况自行添加\u0026quot;){ agent {label \u0026quot;linux\u0026quot;} steps{ echo \u0026quot;发布\u0026quot; } } } post { always { cleanWs() } } // 清理工作空间 } def generateVersion(def ver){ def gitCommitId = env.GIT_COMMIT.take(7) return \u0026quot;${ver}-${gitCommitId}.${env.BUILD_NUMBER}\u0026quot; } def uploadArtifact(def appName, def appVersion, def artifactPath){ echo \u0026quot;根据参数将制品上传到制品库中,待测试\u0026quot; }  代码补充说明 因为 Electron 是跨平台的,我们需要将构建过程分别放到 Windows、Linux、Mac 各平台下执行。所以,不同平台的构建任务需要执行在不同的 agent 上。我们通过在 stage 内定义 agent 实现。如在“Mac平台下构建”的阶段中,agent {label \u0026quot;mac \u0026amp;\u0026amp; nodejs\u0026quot; } 指定了只有 label 同时包括了 mac 和 nodejs 的 agent 才能执行构建。\n多平台的构建应该是并行的,以提升流水线的效率。我们通过 parallel 指令实现。\n另外,默认 Electron 应用使用的三段式版本号设计,即 Major.Minor.Patch。但是笔者认为三段式的版本号信息还不够追踪应用与构建之间的关系。笔者希望版本号能反应出构建号和源代码的 commit id。函数 generateVersion 用于生成此类版本号。生成的版本号,看起来类似这样:1.0.0-f7b06d0.28。\n完整源码地址:https://github.com/zacker330/electronjs-pipeline-demo\n小结 上例中,Electron 应用的流水线设计思路,不只是针对 Electron 应用,所有的跨平台应用的流水线都可以参考此思路进行设计。设计思路大概如下:\n 多平台构建并行化。本文只有操作系统的类型这个维度进行了说明。现实中,还需要考虑其它维度,如系统位数(32位、64位)、各操作系统下的各版本。 各平台下的构建只做一次编译打包。并将制品上传到制品库,以方便后续步骤或阶段使用。 全局变量与平台相关变量进行分离。  最后,希望能给读者带来一些启发。\n参考:  持续交付的八大原则:https://blog.csdn.net/tony1130/article/details/6673741 Jenkins nodejs 插件:https://plugins.jenkins.io/nodejs Electron 版本管理:https://electronjs.org/docs/tutorial/electron-versioning#semver  ",
        "auhtor": "zacker330",
LinuxSuRen's avatar
LinuxSuRen 已提交
492
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
493 494 495 496 497 498 499 500 501 502 503 504 505
        "original": "https://showme.codes/2019-03-10/electronjs-pipeline-demo/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-13-gsoc2019-announcement/",
        "title": "Jenkins 已经被 Google Summer Of Code 2019 接受!",
        "type": "wechat",
        "date": "2019-03-13 00:00:00 +0000 UTC",
        "tags": ["gsoc", "gsoc2019", "events", "community"],
        "description": "19年的 Google Summer Of Code 正式起航",
        "content": " 作为 Jenkins GSoC 管理员团队的代表,我很高兴地宣布 Jenkins 在2019年的 Google Summer of Code上 已经被接受。 今年,我们邀请了学生和导师加入 Jenkins 社区,并一起努力增强 Jenkins 生态圈。\n这里提供一些数字,这是有史以来最大的一次 GSoC,今年共有206个组织参与。并且,希望对 Jenkins 而言也是最大的一年。 我们有25个项目想法,而且有超过30个准导师(不断增多!)。 这已经超过了2016年以及2018年的总和。 有很多的插件,特别兴趣小组以及子项目已经加入了今年的 GSoC.而且,我们已经收到了十几个学生的消息以及第一次贡献,耶!\n下一步? GSoC 已经正式启动,请期待更多的学生在我们的Gitter 频道和邮件列表中联系项目。 在特别兴趣小组和子项目频道中已经有了很多沟通。 我们会努力帮助学生找到他们感兴趣的项目,在这个领域探索,并帮助他们在4月9日的截止日前准备好他们的项目提议。 然后,我们将会继续这个申请,选择项目并分配导师团队。\n所有关于 Jenkins GSoC 的信息都可以在子项目页面上找到。\n我是一个学生。如何申请? 在/projects/gsoc/students[学生的信息]页面中有完整的申请指导。\n我们鼓励感兴趣的学生尽早联系 Jenkins 社区并开始探索项目。所有的项目在对应的页面上都有聊天室与邮件列表。 我们也会为学生组织工作日的会议,在这些会议上你可以见到管理员和导师,并向他们提问。 另外,加入我们的Gitter 频道和邮件列表,以便收到项目中即将到来的事情。\n3月25日开放申请,但你现在就可以准备了!利用这段申请前的时间来讨论并改进你的项目提议。 我们也建议你着手熟悉 Jenkins 并开始探索你的提议的领域。项目的想法包括快速开始的指导,以及有助于初期研究时对新手友好的问题。 如果没有看到任何感兴趣的,你可以提出你自己的项目想法或者 查看由其他参与 GSoC 的组织提出的想法。\n我想要成为一名导师。会不会太晚了? 不晚!我们正在寻找更多的项目想法,以及 Jenkins 的贡献者或用户中对 Jenkins 富有热情并想要指导学生的人。 无须底层经验,导师可以和学生一起研究项目并给出技术指导。 我们尤其对 Java 技术栈方向感兴趣,以及一些新的技术和领域(例如:Kubernetes, IoT, Python, Go 或者其他的)。\n你可以提议一个新项目或者加入已有的。查看博客寻找导师以及导师的信息中的细节。 如果你想要提议一个新项目,那么请在3月11日之前完成,以便学生有时间探索并准备他们的提议。\n今年,导师并不必须要有 Jenkins 开发上的很强的专业知识。目标是指导学生参与到 Jenkins 社区。 如果需要特殊的专业知识,GSoC 组织管理员会帮助寻找顾问。\n重要的日期  3月11日 - 停止新的 GSoC 项目提议 4月9日 - 停止接受学生的申请 5月6日 - 宣布接受了的项目,团队开始社区合作以及编码 8月26日 - 结束编码 9月3日 - 宣布结果  查看 GSoC 时间线了解更多信息。 在 GSoC 期间和之后,我们也会组织 Jenkins 相关的特别活动(例如:在 Jenkins World 上)。\n",
        "auhtor": "oleg_nenashev",
        "translator": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
506 507
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
508 509
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
510 511
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-03-13-ready-for-cdf/",
        "title": "为 Continuous Delivery Foundation 的成立感到兴奋",
LinuxSuRen's avatar
LinuxSuRen 已提交
512
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
513 514 515 516 517 518 519
        "date": "2019-03-13 00:00:00 +0000 UTC",
        "tags": ["cdf", "cicd", "jenkins", "opensource"],
        "description": "CDF 就要来啦",
        "content": "大概十一年前,我就开始为现在被称为 Jenkins 的项目做贡献,自己当时其实也并不知道在做什么。但是接下来发生的事情令人感觉难以置信,数以百计的贡献者加入,成千上万的新用户开始使用 Jenkins,每天都会运行数以百万条的流水线。这样的增长是充满挑战性的,用户的增长意味着问题的增长,问题的增长就意味着需要新的解决方式。 在大约两年半之前,我在2017年的 Jenkins World Contributor Summit 大会上面对一大群 Jenkins 的贡献者们,为我的所谓的 \u0026lsquo;Jenkins软件基金会\u0026rsquo; 做了宣传,那就是,不要羞于从 Python 社区汲取思想,在我的朋友 Chris Aniszczyk 和 Linux 基金会的帮助下,这个基金会变成了一个更加全面的 *持续交付基金会*(CDF),我的同事 Tracy Miranda 一直在领导这项工作,帮助推动 CDF 的成立。\nKohsuke 为 jenkinsci-dev@ mailing list 撰写了一篇很好的概述文章,其中列举了如果 Jenkins 项目一旦建立后就应该加入 Continuous Delivery Foundation 的原因。如果你对 Jenkins 项目感兴趣,但是还没有阅读过这边文章的话,那我认为你应该花些时间来阅读 Kohsuke 的这份邮件。但是在 这篇文章 中,我 想分享我愿意帮助建立持续交付基金会(CDF)的原因。\n持续交付(CD)已经成为我职业生涯中不可或缺的一部分,甚至在 Jez Humble 将此概念清晰地表述之前,我就开始学习 CD 并且对它一直充满热情。我认为它对软件的开发实践至关重要,当有人说他们没有练习使用 CI 或 CD 时,我感觉这就像回到了原始社会。想象一下,如果有人说 \u0026ldquo;呃,我们在这里有一个采用 Source Control 的项目,但领导们觉得这个东西不太靠谱\u0026rdquo;,我想你肯定会惊掉下巴。\u0026rdquo;在这个时代竟然还有开发团队都不使用源代码管理?\u0026rdquo;。总体来说,我认为CD已经是现代软件开发的基础了。\n持续交付也 不是 说只依赖于 Jenkins 这样的单一工具,它也是依赖于其他的用于协同工作的许多工具。虽然我可能觉得 Jenkins 是所有工具中占最中心位置的工具,但也不是说 Jenkins 是这些工具中唯一优秀的一款工具。但是不幸的是,像 Jenkins 这样的许多开源社区往往对他们的世界有着一定的狭隘观点。他们只专注于他们的事情,虽然这是有道理的,但这及可能导致错失交叉合作产生新价值的机会。\n我们所依赖 CD 的许多工具现在都是完全支持的,或者一小部分由不同的供应商支持。Jenkins 从 CloudBees、微软和 Red Hat 获得了大量投资。在过去的五年中,我逐渐认识到像 CDF 这样的基金会需要在这些不同公司中保持中立的位置。我们为企业贡献者提供一套指导方针,规则和期望,这样开源项目就会更有可能从他们那里获得支持。无论是宣传,代码或是现金,帮助企业贡献者在与我们其他人在一个相同的中立立场上,都会有助于确保开源工作的长久性。而且基金会制定规则的附加好处是,公司的参与者不会有意或无意地想要去超越对方或某个贡献者。\n在免费和开源项目的早期阶段,我们自欺欺人地认为每个人都会阅读我们的许可证,订阅我们的“开源精神”,提出问题并修复问题,或者为我们贡献代码。但 现实情况是,运营大型开源社区其实需要更多的资源。它不仅需要人,需要基础设施,而且还需要钱。像 CDF 这样的基金会为依赖项目或以其他方式投资项目的组织提供了一种有意义的参与方式。 Jenkins 项目的资金预算很紧张,我们每年的花费大约在10,000-15,000美元之间。如果我们要将我们捐赠的资产,提供的免费服务或我过去十一年来所做的事情都收取报酬的话,那么这个数字每年在60,000-80,000美元之间。 Kohsuke 可以证明我有能力为 Jenkins 项目提供免费的东西,但免费的东西并不是每年都保证会有的。为了更好的发展,Jenkins 需要一个稳定的预算,类似于像 FreeBSD Foundation 这样的大型基金会,这样我们便可以投资于服务和人员。\n如果您发现自己在担心开源的可持续性,那么请查看不同的社区,众筹或其他意识形态工具(如许可变更),并且请允许我帮助您。一致的预算是让大型开源项目可持续发展的重要因素。因为开源项目靠的是 *人*。确保有才能的作家,开发人员,营销人员,测试人员和设计师继续提供支持,就代表着他们雇主必须代表他们投入时间的成本,或者他们需要通过其他方式获得报酬。我坚信开源基金会能够为更大的免费和开源项目发展提供解决 预算 问题的途径。\nCDF虽然尚未启动,但我已经对它的潜力感到兴奋。因为这个基金会不仅适用于Jenkins项目,还适用于整个持续交付领域。\n",
        "auhtor": "rtyler",
        "translator": "yuzp1996",
        "original": "https://brokenco.de/2019/01/31/lets-go-cdf.html",
LinuxSuRen's avatar
LinuxSuRen 已提交
520
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
521 522
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
523 524
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/03/2019-01-08-mpl-modular-pipeline-library/",
        "title": "MPL - 模块化的流水线库",
LinuxSuRen's avatar
LinuxSuRen 已提交
525
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
526 527 528 529 530 531 532
        "date": "2019-03-06 00:00:00 +0000 UTC",
        "tags": ["jenkins", "pipeline", "shared-library"],
        "description": "Jenkins 流水线共享库技术实践",
        "content": " MPL - 模块化的流水线库 尽管通过自动化部署加快了开发速度,但由于在 DevOps 方面缺少协作,我们一个客户正因此而放慢产品的上市时间。虽然他们也投入了资源来做 DevOps ,但每条生产流水线都是独立设置的,迫使团队为每个项目重新造轮子。更糟糕的是,由于没有跨团队协作,平台中的任何错误又会出现在每条新的流水线中。许多客户都有类似的问题存在,因此我们决定开发一个既能帮助现有客户,又能适应未来使用需求的通用工具。使用通用框架且标准化的 CI/CD 平台是最显而易见的选择,但这将导致缺少灵活性的单体结构(monolithic structure),最终会变得举步维艰。每个团队都需要在自己的流水线上工作,基于此,我们开发了一个方便 DevOps 流水线的每个可重用部分可供以后使用的解决方案 — Jenkins 驱动的模块化流水线库。\n解决方案:模块化流水线库 模块化流水线库(译注:modular pipeline library,简称 MPL)是一个高度灵活的 Jenkins 流水线共享库,它可以轻松将最佳实践共享到整个公司。它具有清晰的模块化结构,先进的测试框架,多级嵌套的能力,流水线配置系统,被改进了的错误处理机制以及许多其他有用的组件。\n我们将通过以下几部分内容深入了解并解释 MPL 是如何工作的:\n 探索用于构建 MPL 的技术和工具 回顾MPL,并说明它为何有效 一步一步在流水线样例中使用 MPL 深入研究 MPL 的一些重要的组件,例如测试框架和嵌套库  首先,让我们介绍构建 MPL 时使用到的关键技术。\n使用共享库和 Jenkins 流水线构建 MPL 我们的 Jenkins 自动化平台最近收到了一些 Jenkins 流水线的更新。这些更新允许我们创建一个 Jenkinsfile 文件来描述整条流水线,并用于执行一系列不言自明的脚本。这提高了最终用户对 CI/CD 自动化流程的可视化程度,并提高了 DevOps 团队对流水线的可支持性。\n然而,流水线存在一个很大的问题:很难用唯一的流水线支持多个 Jenkinsfile 文件(因此存在多少个项目就存在多少个 Jenkinsfile 文件)。我们需要一个地方存放公共逻辑,这正是 Jenkins 共享库能够实现的。共享库用于存放流水线公共的部分,它定义在 Jenkinsfile 文件中,并允许在其中使用接口简化自动化脚本。\n虽然共享库允许你存储公共逻辑并操作 Jenkins,但它们并没有提供一种好的方式去使用这些公共逻辑。所以,MPL 通过允许用户创建易于理解的流程描述来优化流水线和共享库,然后方便其他团队使用。\nMPL 致力于创建跨团队协作 DevOps 流程 通过 MPL,我们现在能够跨团队协作和共享 DevOps 实践,轻松地为特定的项目指定特定的流水线,并能在将它们集成到 MPL 库中之前进行调试和测试。每个团队都可以创建一个嵌套库,在其中增加流水线和模块,并在流水线中使用,这样还可以提高流水线的可视化程度。MPL 能够适用于任何包含 Jenkinsfile 文件的项目,还可以根据项目团队的需要灵活地管理它。\nMPL 的核心是提供一种简单的方法:\n 通过引入模块分离流水线和步骤 使用简单的接口描述模块中的步骤 测试所描述的模块并与其他流水线和项目共享结果  MPL 中还有许多其他功能,但本质上它是一个解决 DevOps 一般性协作问题的平台。为了简化开发和手动测试,MPL 提供了模块覆盖和继承模型,允许用户在不影响其他任何情况下测试项目中的特定修复。在 Jenkins 中,一个模块就是一个文件,其中包含脚本步骤和逻辑,以实现简单的目标(构建工件,运行测试,创建图像等)。这些模块在流水线的阶段中可以被组合使用,而且任何了解 Jenkins 流水线语法的人都可以轻松读懂。\nMPL 允许用户使用库的核心特性(结构,模块,管道)并创建嵌套库以满足特定 DevOps 团队的需求。DevOps 团队可以在他们的项目中使用任何自定义的逻辑来组装一条完整的流水线。他们还可以通过多种方式覆盖和继承核心 MPL 模块,或者轻松地与其他团队分享自定义模块。接下来的信息,展示了这些模块的适用范围:\n你还可以在模块中指定某些流水线所需的后续步骤。例如,动态部署模块的执行会创建测试环境,当流水线结束时,它又会销毁该测试环境。想要仔细查看 MPL 调用过程,请查看下图:\n此图显示了 MPL 的执行。首先,你必须创建一个 Jenkins 任务,它将调用 Jenkinsfile(例如,当源代码被更改时),之后 Jenkinsfile 将调用流水线。流水线逻辑可以被定义在这些位置:MPL 端、Jenkins 任务的流水线脚本中 、嵌套库或项目 Jenkinsfile 中。最后,流水线的各个阶段将调用模块,而这些模块所使用的特性,可能来自 groovy 逻辑,流水线步骤或者共享库中的步骤。\n现在我们已经完成对解决方案的概述,接下来,让我们通过一个简单的流水线来了解 MPL 是如何工作的。\n流水线在 MPL 中执行的示例 假设你有一个常规的 Java Maven 项目。你在项目中创建 Jenkinsfile,并希望使用 DevOps 团队准备的默认流水线。MPL 本身就提供一个简单的流水线:核心 MPLPipeline 。这是一个非常简单的流水线,但对于想要尝试 MPL 的人来说,这是一个很好的开端。我们来看一下这个简单的 Jenkinsfile 文件:\n@Library('mpl') _ MPLPipeline {}  这个 Jenkinsfile 文件只包含两行代码,一行加载 MPL 逻辑,另一行运行流水线。大多数的共享库实现了像这样的接口,调用步骤并提供参数。MPLPipeline 只是一个自定义的流水线步骤,因为它位于 vars 目录中。MPLPipeline 结构非常简单,执行步骤如下:\n 初始化 MPL MPL 使用 MPLManager 单例对象来控制流水线 使用默认值合并配置并将其存储 指定阶段所需的默认配置并预定义一些有用的配置 定义一个包含4个阶段和后续步骤的声明式流水线:  检出(Checkout)- 获取项目源代码 构建(Build)- 编译,静态分析,单元测试 部署(Deploy)- 将制品上传到动态环境(dynamic environment)并运行应用程序 测试(Test)- 检查与其他组件的集成 后续步骤(Poststeps)- 清理动态环境,发送通知等  运行已定义的流水线 这是 MPL 开始发挥其魔法并实际运行的地方  MPL 的主要阶段只有一步,即 MPLModule。此步骤包含 MPL 的核心特性:执行包含流水线逻辑的模块。你可以在 MPL 代码仓库中找到默认模块,这些模块位于 resources/com/griddynamics/devops/mpl/modules 目录中,包括:Checkout,Build,Deploy 和 Test 模块。在每个模块的目录中,我们都可以找到真正执行相应阶段逻辑的 Groovy 文件。下图是简化了的 MPL 代码仓库结构图:\n检出阶段启动时,MPLModule 按名称加载模块(默认为阶段名称),并运行 Checkout/Checkout.groovy 文件中的逻辑:\nif( CFG.'git.url' ) MPLModule('Git Checkout', CFG) else MPLModule('Default Checkout', CFG)  如果配置中包含该 git.url 选项,它将加载一个 Git Checkout 模块。否则,它将运行该 Default Checkout 模块。所有被调用的模块使用与父模块相同的配置,这就是 CFG 被传递给 MPLModule 调用的原因。在以上代码中,我们没有指定 git.url 配置,因此它将运行 Checkout/DefaultCheckout.groovy 中的逻辑。模块名称中的空格是将模块映射到特定文件夹的分隔符。\n在 Default Checkout 模块中,只有一行代码 checkout scm,它负责克隆 Jenkins 任务中指定的源代码仓库。这就是检出阶段所做的一切,MPL 对于这么小的阶段似乎有些多余,我们只需要在这里讨论它,以展示 MPL 在模块中的工作方式。\n当流水线运行 Maven Build 模块时,也是同样的运行逻辑:\nwithEnv([\u0026quot;PATH+MAVEN=${tool(CFG.'maven.tool_version' ?: 'Maven 3')}/bin\u0026quot;]) { def settings = CFG.'maven.settings_path' ? \u0026quot;-s '${CFG.'maven.settings_path'}'\u0026quot; : '' sh \u0026quot;\u0026quot;\u0026quot;mvn -B ${settings} -DargLine='-Xmx1024m -XX:MaxPermSize=1024m' clean install\u0026quot;\u0026quot;\u0026quot; }  这个阶段稍微复杂一些,但是操作很简单:我们使用默认名称为 Maven 3 的工具来运行 mvn clean install 命令。这些模块是脚本化的流水线(scripted pipeline),所以你可以执行所有 Jenkins 流水线支持的步骤。这些文件不需要任何特定的和复杂的语法,只需要一个普通的文件,其中包含步骤和 CFG, CFG 是包含了阶段配置的预定义变量。MPL 模块从父模块继承了沙盒(sandbox),因此你的脚本执行将是安全的,并且和一个普通的 Jenkins 流水线一样在 Jenkins 重启后还能生效。\n在 Deploy 文件夹中,Openshift Deploy 模块具有相同的结构。它的主要目的中是为了展示如何在模块中定义后续步骤(poststep):\nMPLPostStep('always') { echo \u0026quot;OpenShift Deploy Decommission poststep\u0026quot; } echo 'Executing Openshift Deploy process'  首先,我们定义了 always 后续步骤。它最终会被存放到 MPLManager 对象中(译注:https://github.com/griddynamics/mpl/blob/master/src/com/griddynamics/devops/mpl/MPLManager.groovy#L40),在真正执行后续步骤时被调用。我们可以多次定义 always MPLPostStep:所有后续步骤都将按先进后出(FILO)顺序存放和执行。因此,我们可以在同一模块中定义需要完成和撤消操作的后续步骤逻辑,例如动态环境的销毁。这样就可以确保在流水线完成时执行操作。\n在部署阶段之后,流水线会执行测试阶段,但是在测试阶段并没有太多有趣的事情发生。然而,测试中有一个非常重要的事情,那就是 MPL 本身的测试。\nMPL 本身的测试 MPL 的测试框架基于 LesFurets 的 JenkinsPipelineUnit,其中一个很小的区别是它能够测试 MPL 模块。测试整个流水线被认为是不现实的,因为流水线可能非常复杂,为这些怪物编写测试就像一项西西弗斯任务(sisyphean task,译注:永无尽头而又徒劳无功的任务)。而使用用少量的步骤测试一个黑盒要容易得多,可以确保任务能正常工作。\n在 MPL 源代码中,你可以找到构建模块的测试用例:所有测试都存放在 test/groovy/com/griddynamics/devops/mpl/modules 目录中,Build/BuildTest.groovy 文件内有多个测试用例。MPL 库的构建阶段会执行这些测试,测试的步骤如下:\nLoading shared library mpl with version snapshot MPLModule.call(Build, {maven={tool_version=Maven 2}}) Build.run() Build.MPLModule(Maven Build, {maven.tool_version=Maven 2}) MavenBuild.run() MavenBuild.tool(Maven 2) MavenBuild.withEnv([PATH+MAVEN=Maven 2_HOME/bin], groovy.lang.Closure) MavenBuild.sh(mvn -B -DargLine='-Xmx1024m -XX:MaxPermSize=1024m' clean install) Build.fileExists(openshift)  测试运行 MPLModule 自定义配置和模拟步骤,以检查在执行期间,工具是否已根据提供的配置更改为 Maven 2。我们使用此类测试覆盖所有测试用例,确保模块按预期工作,并且流水线将正常工作。如果需要,你可以测试整条流水线,但模块测试是简化测试过程的一种方法。\n现在我们已经了解了如何测试 MPL 模块,现在是时候看看 MPL 的一个关键特性,即嵌套库。\n嵌套库的好处 在大型公司中,支持一个大型库是没有意义的。每个部门都需要多个(不同于标准的)配置选项,并针对标准流水线进行调整,这会带来不必要的工作量。MPL 通过引入嵌套库来解决这些问题。下图展示了使用嵌套库与仅仅使用主库的区别:\n嵌套库与共享库相同,都通过导入 MPL 使用其特性,模块和流水线。此外,它允许将一些与团队相关的逻辑与公司的通用逻辑分离。以下是具有嵌套库的 MPL 的结构:\n你可以在重写的流水线中导入 MPL,指定一些附加模块的路径,覆盖模块逻辑,并由 Jenkins 负责协调(译注:此处原文是You can import the MPL in the overridden pipeline, specify the path of some additional modules, override module logic, and use Jenkins power moves: there are no limitations. 本人能力有限,无法真正理解作者的意思)。当另一个团队需要你的模块时,你只需向公司 MPL 基础仓库提交变更请求,如果变更请求通过,就可以与他们共享你的功能模块。\n因为嵌套库可以覆盖 MPL 或 Jenkins 流水线的基本功能,所以嵌套库可以调试和修改 MPL 提供的步骤(例如 MPLModule)和流水线。你可以覆盖任何功能,因为这些覆盖仅影响你自己的流水线。经常验证的嵌套库,可以与其他团队讨论,看看它是否也适用于其他嵌套库。\n嵌套库的嵌套层级数是没有限制的,但我们建议仅使用两层级( MPL 和嵌套库),因为在低层级上配置和测试嵌套库非常复杂。\n强大的模块覆盖 进一步了解嵌套库和项目端模块后,我们知道,模块名称是可以与上层库中模块名同名的。这是覆盖上层模块逻辑的好方法——使用自己的模块替换 Build/Build.groovy——真正执行时就会执行你的模块中的逻辑,而不是上层模块的。下图说明了模块覆盖是如何工作的:\n更棒的是,MPL 的优点之一是你仍然可以使用上层模块!MPL 具有防止循环调用的机制,因此同一运行分支中不会再次运行同一模块。但是,你可以轻松地通过在一个模块中调用原始模块来使用上层逻辑。\n上面的 Petclinic-Selenium 示例中,使用了默认值 MPLPipeline(您可以在 MPL Wiki 页面上找到它),并在 .jenkins 目录中包含项目级别模块。这些模块将在库模块之前调用。例如,Checkout 模块没有放在项目级别,因此它将从 MPL 调用,但 Build 模块存在于 .jenkins 项目端的目录中,它将被调用:\nMPLPostStep('always') { junit 'target/surefire-reports/*.xml' } MPLModule('Build', CFG) if( fileExists('Dockerfile') ) { MPLModule('Docker Build', CFG) }  如代码所示,项目中的 Build 模块注册了后续步骤,接着调用原始的 Build 模块,最后调用 Docker Build 模块。流水线的后续阶段更复杂,但所有模块覆盖基本原理都相同。现实中,有些项目可能很棘手,需要对现有模块进行一些小调整。但是,你可以在项目级别的模块中轻松调整,并考虑如何将功能移动到嵌套库或 MPL 中。\n结论:MPL 为 DevOps 带来了什么 许多 DevOps 团队和公司都使用臃肿,限制多的的和错误的 CI/CD 自动化平台。这增加了用户的学习曲线,导致团队工作更慢,并提高了生产成本。DevOps 团队发现,相同的问题经常在不同的项目中出现,而缺乏协作意味着团队每次都必须单独修复它们。\n但是,通过 MPL,DevOps 团队拥有一个共享、简单、灵活的 CI/CD 平台。可以改善生产过程中的用户支持,协作和整体项目源代码。通过利用 MPL,你的公司可以找到自动化共识,实现跨公司协作的目标,并重用来自大型社区的最佳实践。而且这些都是开源工具。如果你对构建 MPL 感兴趣,请联系我们以了解更多信息!\n其他资源  Jenkins Pipeline Engine Jenkins Shared Libraries MPL GitHub repository  概述和演示视频:  介绍 概述 MPL Build的演示 嵌套库的演示 流水线的演示  ",
        "auhtor": "sparshev",
        "translator": "zacker330",
        "original": "https://jenkins.io/blog/2019/01/08/mpl-modular-pipeline-library/",
LinuxSuRen's avatar
LinuxSuRen 已提交
533
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
534 535
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
536 537 538 539
        "uri": "https://jenkins-zh.cn/about/star-plan/",
        "title": "社区贡献激励方案",
        "type": "about",
        "date": "2019-03-03 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
540
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
541 542 543
        "description": "激励可以让社区活动更有趣",
        "content": "统计的基础分数为:GitHub 账号首页上 jenkinsci 、 jenkins-infra 、 jenkins-zh 、 jenkins-x 四个组织的贡献数和。\n附加分,统计发表在 Jenkins 公众号上的文章的阅读数,该数字除以100得到的整倍数。例如:某篇文章的阅读数为120,那么得分为1;阅读数为90,则没有得分。\n加权,是为了鼓励更多的原创。原创文章的加权数为1.2,例如:某篇原创文章的阅读数为230,那么最终得分为2.4。\n",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
544 545 546
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
547
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
548
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
549 550
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-27-jenkins-script-console-in-practice/",
        "title": "批量修改 Jenkins 任务的技巧",
LinuxSuRen's avatar
LinuxSuRen 已提交
551
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
552 553 554 555
        "date": "2019-02-27 00:00:00 +0000 UTC",
        "tags": ["Jenkins"],
        "description": "Jenkins 脚本命令行的一种实践",
        "content": " 通过脚本命令行批量修改 Jenkins 任务 最近,笔者所在团队的 Jenkins 所在的服务器经常报硬盘空间不足。经查发现很多任务没有设置“丢弃旧的构建”。通知所有的团队检查自己的 Jenkins 任务有没有设置丢弃旧的构建,有些不现实。\n一开始想到的是使用 Jenkins 的 API 来实现批量修改所有的 Jenkins 任务。笔者对这个解决方案不满意,经 Google 发现有同学和我遇到了同样的问题。他使用的更“技巧”的方式:在 Jenkins 脚本命令行中,通过执行 Groovy 代码操作 Jenkins 任务。\n总的来说,就两步:\n 进入菜单:系统管理 \u0026ndash;\u0026gt; 脚本命令行 在输入框中,粘贴如下代码:\nimport jenkins.model.Jenkins import hudson.model.Job import jenkins.model.BuildDiscarderProperty import hudson.tasks.LogRotator // 遍历所有的任务 Jenkins.instance.allItems(Job).each { job -\u0026gt; if ( job.isBuildable() \u0026amp;\u0026amp; job.supportsLogRotator() \u0026amp;\u0026amp; job.getProperty(BuildDiscarderProperty) == null) { println \u0026quot; \\\u0026quot;${job.fullDisplayName}\\\u0026quot; 处理中\u0026quot; job.addProperty(new BuildDiscarderProperty(new LogRotator (2, 10, 2, 10))) println \u0026quot;$job.name 已更新\u0026quot; } } return; /** LogRotator构造参数分别为: daysToKeep: If not -1, history is only kept up to this days. numToKeep: If not -1, only this number of build logs are kept. artifactDaysToKeep: If not -1 nor null, artifacts are only kept up to this days. artifactNumToKeep: If not -1 nor null, only this number of builds have their artifacts kept. **/   脚本命令行介绍 脚本命令行(Jenkins Script Console),它是 Jenkins 的一个特性,允许你在 Jenkins master 和 Jenkins agent 的运行时环境执行任意的 Groovy 脚本。这意味着,我们可以在脚本命令行中做任何的事情,包括关闭 Jenkins,执行操作系统命令 rm -rf /(所以不能使用 root 用户运行 Jenkins agent)等危险操作。\n除了上文中的,使用界面来执行 Groovy 脚本,还可以通过 Jenkins HTTP API:/script执行。具体操作,请参考 官方文档。\n问题:代码执行完成后,对任务的修改有没有被持久化? 当我们代码job.addProperty(new BuildDiscarderProperty(new LogRotator (2, 10, 2, 10)))执行后,这个修改到底有没有持久化到文件系统中呢(Jenkins 的所有配置默认都持久化在文件系统中)?我们看下 hudson.model.Job 的源码,在addProperty方法背后是有进行持久化的:\npublic void addProperty(JobProperty\u0026lt;? super JobT\u0026gt; jobProp) throws IOException { ((JobProperty)jobProp).setOwner(this); properties.add(jobProp); save(); }  小结 本文章只介绍了批量修改“丢弃旧的构建”的配置,如果还希望修改其它配置,可以参考 hudson.model.Job 源码。\n不得不提醒读者朋友,Jenkins 脚本命令行是一把双刃剑,大家操作前,请考虑清楚影响范围。如果有必要,请提前做好备份。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
556 557
        "auhtor": "zacker330",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
558
        "original": "https://showme.codes/2019-02-23/jenkins-script-console-in-practice/",
LinuxSuRen's avatar
LinuxSuRen 已提交
559
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
560 561
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
562 563 564 565
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-27-contribution-inspire/",
        "title": "社区贡献激励活动",
        "type": "wechat",
        "date": "2019-02-27 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
566
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
567 568 569
        "description": "Jenkins 中文社区送福利",
        "content": "自 Jenkins 官方微信公众号开通以来,收到了很多热心、愿意参与开源社区的同学的贡献。这里,包括有 Jenkins 官方博客中的博文翻译,也有 Jenkins 中文站点维护的 Pull Request。我能够看到的是,有些同学从英文技术文章的翻译过程中,对 Jenkins 相关技术的理解更加深入了;而有的则从对 GitHub 不甚了解到逐渐熟悉社区贡献的大致流程;对于深度参与社区贡献的同学,更是能够在“中文本地化”以及 Jenkins 其他的特别兴趣小组(SIG)会议讨论上获得最新的动态。\n本着给社区贡献者谋福利的想法,Jenkins 中文社区携手“人民邮电出版社”给大家提供三本技术相关的书籍。从19年3月开始,截止到5月,我们会给予三名贡献者每人一本书。我们会在下次公众号文章中介绍评选规则,欢迎任何一位认可开源、希望参与开源的朋友提出你的建议,不要吝惜你的 PR。获选的同学,按照贡献量可以从下面的列表中依次任选一本:\n最后,再次让我们对“人民邮电出版社”给予开源社区的大力支持表示感谢。\n",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
570 571 572
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
573 574
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
575 576 577 578 579 580 581 582 583
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-20-java11-preview-availability/",
        "title": "Java 11 预览支持已在 Jenkins 2.155+ 中可用",
        "type": "wechat",
        "date": "2019-02-20 00:00:00 +0000 UTC",
        "tags": ["core", "developer", "java11", "community", "platform-sig"],
        "description": "Java 11 预览支持已在 Jenkins 2.155+ 中可用",
        "content": "  NOTE: 这是由 Java 11 支持团队 联合撰写的博客。 在 12 月 18 号(UTC时间下午4点)我们也会在 Jenkins 在线 Meetup 展示对 Java 11 的预览支持。(链接)\n Jenkins 作为领先的开源自动化服务器之一,目前仍然只支持到 Java 8。在 9 月 25 日 OpenJDK 11 发布了。这是一个长期支持版本,并将持续多年,我们想要在 Jenkins 项目中对这个版本进行全面的支持。在过去的一年中,许多贡献者一直致力于在项目中支持 Java 11(Jenkins JEP-211)。这是一条艰辛的道路,但是现在,代表 Jenkins Platform SIG,我们很高兴的宣布在 Jenkins 每周发布提供 Java 11 预览!\n为什么我们需要 Java 11 的预览?\n这是因为它可以提供给 Jenkins 贡献者和早期使用者一个在明年年初(译者注:此文发布于 2018 年)GA 发布之前尝试这些变化的途径。它也可以帮助我们进行更多的探索性测试,并且有希望在 Jenkins 正式地提供 Java 11 支持之前,解决大部分的问题。\n在这篇文章中,我们将会介绍如何在 Java 11 环境下运行 Jenkins,还有如何调查兼容性问题并报告它们。\n背景 你可能还记得,在 2018 年 6 月我们举办了一个针对 Java 10+ 支持的在线黑客马拉松。作为黑客马拉松的一部分,我们提供了 Java 11 的实验性支持。这次活动对我们来说非常成功。我们可以在 Java 10 和 Java 11-ea 环境下运行 Jenkins 以及一些主要的功能 —— 包括流水线、JobDSL、Docker/Kubernetes plugin、Configuration as Code、BlueOcean 等。它让我们相信我们可以在 Jenkins 中提供Java 11支持而不会发生破坏性变化。在这场马拉松之后 Oleg Nenashev 创建了 \u0026ldquo;Java 10+ support in Jenkins\u0026rdquo;(之后修改为只针对支持 Java 11)。Jenkins Platform SIG 也已成立,以协调 Java 11 的支持工作和其他平台的支持工作(打包,操作系统支持等)。\n一组贡献者一直持续致力于 Java 11 支持,他们主要在关注上游的功能性补丁、在开发工具中提供 Java 11 支持、测试和解决已知的兼容性问题。详细的状态的更新,请参阅 Platform SIG 的会议记录。从 Jenkins 2.148 开始,Jenkins 在多个不同的 Linux 和 Windows 平台下成功的在最新的 OpenJDK 11 版本下运行。我们进行了大量的自动化和探索性测试,除了一些例外(见下文),大部分 Jenkins 插件运行良好。GA 版本发布需要的自动化测试工作还在进行,但是我们已经成功的运行了 Jenkins core 的测试,通过了全部的 Acceptance Test Harness,以及在推荐插件上运行通过了 Plugin Compat Tester。我们也部署了一个临时的为 Java 11 搭建的 Experimental Update Center,可以为 Java 11 的早期采用者提供快速的问题修复。使用Java 11 运行时,Jenkins 2.155+ 将会默认使用此更新中心,这就是我们宣布此版本的预览可用性的原因。\n在 2018 年 11 月 19 日,我们在 Platform SIG 会议的幻灯片上展示了当前的 Java 11 支持的状态,我们同意发布 Java 11 的可用性预览,以便我们可以提供内容让 Jenkins 用户得以进行评估。 在 12 月 4 日的下一次会议上,所有障碍都已得到解决,Platform SIG 会议签署发布了Java 11 预览版。\n在 Docker 中运行 Jenkins 和 Java 11 从 Jenkins 2.155 开始,我们开始为 Jenkins master 和 agent 提供 Docker 镜像。 所有这些镜像都基于官方的由 Docker 社区维护的 openjdk:11-jdk 镜像。这里有一些关于迁移到其他基本镜像的讨论,但是我们决定在预览可用性的范围中将其排除。基于同样的原因,我们目前不提供 Alpine 镜像。\nJenkins master 镜像 官方的 jenkins/jenkins 镜像现在已经提供了 Java 11 的支持。你可以向下面这样简单在 Java 11 的环境中运行 Jenkins。\ndocker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:jdk11  可以使用下面这些标签:\n jdk11 - 最新的包含 Java 11 支持的每周发布 2.155-jdk11 - 包含 Java 11 支持的每周发布=  这些镜像完全和 jenkins/jenkins documentation 兼容。例如:你可以使用 plugins.txt 来安装插件、挂载卷或者通过环境变量传递额外选项。\nAgent 镜像 如果你通过 Docker 或 Kubernetes 插件使用容器化的 agent,我们也发布了 Jenkins agent 的官方 Docker 镜像:\n jenkins/slave jenkins/jnlp-slave jenkins/ssh-slave  所有的镜像都可以使用 latest-jdk11 标签来获取 JDK 11 的捆绑。同时为这些过时的名字抱歉!\n实验性 Jenkins master 镜像 为了简化测试,我们也在 DockerHub 提供了一些实验性的镜像。 对于这些镜像,我们为其搭建好了持续交付流水线,所以不需要等待 Jenkins 的每周发布,就可以获得补丁。\n jenkins4eval/blueocean-platform-support - 等同于 jenkinsci/blueocean  标签: latest-jdk11 这个镜像捆绑了在 Java 11 上运行时需要的所有的 Jenkins 流水线和 Blue Ocean 的补丁 如果你想要使用流水线,使用这个镜像  jenkins/jenkins-experimental - 等同于 jenkins/jenkins  标签: latest-jdk11 这个镜像是从 Jenkins core 的 java11-support 分支中发布的 这个分支可能轻微的领先或落后于 master 分支,我们可能会用这个分支去快速发布补丁给 Java 11 用户   我们最终会把这个实验性流水线移到新的在 jep:217 中创建的 jenkins4eval 组织中去。\n在 Java 11 中运行 jenkins.war 在 Docker 外运行 Jenkins 并没有那么简单。这是因为 Jenkins 依赖一些在 Java 11 中已经被移除的模块。我们计划在 GA 发布中以某种方式解决掉这个问题 (参见 JENKINS-52186),但是现在,我们还需要一些手动操作才能在 Java 11 中运行 Jenkins WAR。\n 下载 2.155 版本的 Jenkins WAR 下载下面这些库到 jenkins.war 所在的目录中去  jaxb-api-2.3.0.jar (保存为 jaxb-api.jar) jaxb-core-2.3.0.1.jar (保存为 jaxb-core.jar) jaxb-impl-2.3.0.1.jar (保存为 jaxb-impl.jar) javax.activation v.1.2.0 (保存为 javax.activation.jar)  运行下列命令  Run Jenkins with ${JAVA11_HOME}/bin/java \\ -p jaxb-api.jar:javax.activation.jar --add-modules java.xml.bind,java.activation \\ -cp jaxb-core.jar:jaxb-impl.jar \\ -jar jenkins.war --enable-future-java --httpPort=8080 --prefix=/jenkins  已知的兼容性问题 为了帮助用户追踪兼容性问题,我们新创建了 Known Java 11 Compatibility Issues wiki 页面。\n几个重要的问题和障碍:\n Pipeline: Support Plugin 有一个已知的在 Java 11 中运行会产生的上下文持久性问题 (JENKINS-51998)  我们已经在 Experimental Update Center for Java 11 中部署了一个临时的修复版本。修复版本号: 3.0-java11-alpha-1。 如果你使用 Jenkins 流水线,请确认你使用了这个版本,否则你的 Job 会几乎立即失败 当你更新实例到 Java 11 时,请确认没有正在运行的流水线。  JENKINS-54305 - JDK Tool Plugin 不提供 JDK 11 的安装器 JENKINS-52282 - Java Web Start 在 Java 11 中已经不再可用, 所以我们不再可能在网页图形界面中启动 agent。我们也没有计划提供一个替代品。  我们也在其它插件中发现了一些次要的不兼容问题,但是我们不认为它们对于预览可用性来说是一个阻碍。\n报告兼容性问题 如果你碰到了任何有关 Java 11 兼容性的问题,请在我们的 bug 跟踪工具中报告问题。并为这类问题添加 java11-compatibility 标签,这样它们会自动出现在 wiki 页面中,并被分级。\n对于安全性问题,请使用标准的 漏洞报告流程。尽管我们在预览发布时,会公开修复 Java 11 相关的问题,但是遵守这个安全流程也会帮助我们调查它对 Java 8 用户的影响。\nJava 11 支持团队 一旦 Java 11 支持发布,我们希望会有插件和 Jenkins core 的回归 (regression)报告。我们关心的部分之一就是不同平台的本地库,还有其它的 Java 的版本的问题。同样,这里也存在第三方库和 Java 11 不兼容的风险。为了减轻这些风险,我们创建了 Java 11 支持团队。这个团队将会专注于对到来的问题进行分级、帮助 review PR、在一些情况下也会修复问题。这个团队的工作流程可在 JEP-211 文档中看到。\n我们不希望 Java 11 支持团队 去修复所有的发现的问题,我们将会和 Jenkins core 和插件的维护者一起解决它们。假如你有兴趣加入这个团队,可以在 Platform SIG Gitter Channel 中联系我们。\n贡献 我们感谢任何一种对 Java 11 支持的贡献, 包括在 Java 11 下运行 Jenkins,报告和解决兼容性问题。\n 假如你想要进行一些探索性测试,我们推荐你在你的其中一个测试实例中尝试 Java 11 支持。我们对这样的测试感激不尽。我们在上面提供了问题报告的准则。 假如你是一个插件的开发者/维护者,我们非常感谢你能在 Java 11 中测试你的插件。为了帮助你,我们创建了 Java 11 Developer guidelines。这个页面阐述了如何在 Java 11 下测试你的插件,同时它也列出了在开发工具中的已知的问题。  无论你做什么,请通过向 Platform SIG mailing list发送邮件告诉我们你的体验。这些信息将帮助我们跟踪变化和贡献。有关迁移复杂性的任何其他反馈将不胜感激!\n下一步是什么? 在 12 月 18 号(UTC时间下午4点)我们也会在 Jenkins 在线 Meetup 展示对 Java 11 预览支持(链接)。在这个 meetup 上我们将会总结目前的 Java 11 预览支持的状态。如果你是插件开发者,我们还将会组织单独的会议讨论有关在 Java 11 下测试插件以及有关修复兼容性问题的常见最佳实践。如果你有兴趣,请关注 Platform SIG 的公告。\n在下一周,我们将会专注于处理来自早期使用者的反馈并且修复一些发现的兼容性问题。我们还将继续为明年的 GA 发布开发 Java 11 支持补丁 (JENKINS-51805)。除此之外,我们将会开始在子项目中提供 Java 11 支持,包括 Jenkins X 和 Jenkins Evergreen。\n",
        "auhtor": "oleg_nenashev",
        "translator": "cizezsy",
LinuxSuRen's avatar
LinuxSuRen 已提交
584 585
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
586 587
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
588 589
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-13-outreachy-audit-log-plugin/",
        "title": "Jenkins 对审计日志的支持",
LinuxSuRen's avatar
LinuxSuRen 已提交
590
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
591 592 593 594 595 596
        "date": "2019-02-13 00:00:00 +0000 UTC",
        "tags": ["community", "outreachy", "outreachy2018"],
        "description": "Outreachy 实习生提供了 Jenkins 对审计日志的支持",
        "content": "今年是 Jenkins 项目首次参与 Outreachy. Outreachy 是一个类似于 Google Summer of Code (GSoC) 的项目, 实习生有偿地为开源项目工作。 关键的不同之处在于,Outreachy 面向那些在他们国家的技术行业中受到歧视或偏见的小众群体。 当我了解到这个项目后,由于它的包容性与社区建设与我的理念相符就立即自愿作为导师来参与。 我很高兴地说,Jenkins 项目和我的雇主 CloudBees 对此非常支持。\n基于我们之前在 GSoC 上指导学生的付出,今年我们已经加入 Outreachy 并指导了两个实习生。 在 Outreachy 的这次活动中,我们的实习生 David Olorundare 和 LathaGunasekar 将与我一起研发 Jenkins 对审计日志的支持。 我很高兴欢迎 David 和 Latha, 并期待他们能在软件工程专业和对开源社区的贡献上都有所收获。 请继续关注后续博客对他们的介绍。\n该审计日志支持项目在 Jenkins 和 Apache Log4j 之间形成了一个新的链接,这给予我们的实习生学习 更多有关开源治理和认识新朋友的机会。 作为奖金,该项目旨在为支持高级的业务检测提供便利,例如:在认证事件中检测潜在的入侵尝试。 我们也会编写一个 JEP 来描述由插件提供的审计日志 API,以及其他插件如何定义并记录除 Jenkins 核心以外插件的审计事件。\n我期待我们将会一起完成了不起的作品,而且我希望在将来能够帮助更多的 Outreachy 实习生!\n",
        "auhtor": "jvz",
        "translator": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
597 598
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
599 600
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
601 602 603 604 605 606 607 608 609 610
        "uri": "https://jenkins-zh.cn/about/how-to-involve/",
        "title": "如何参与",
        "type": "about",
        "date": "2019-01-05 22:56:04 +0800 +0800",
        "tags": [],
        "description": "不满意只做吃瓜群众的请看过来",
        "content": " 参与开源社区真的不只有 Coding 一条路可选。只要你认同“开源”,有热情,就可以!任何岗位、校大学生、甚至\u0026rdquo;不懂\u0026rdquo;技术都能够加入我们。走过路过的朋友们别错过,下面的参与方式总有一种能把你带上开源事业的“不归路”,如果真的没有包含你希望的参与方式,也可以从现在就发起一个 Pull Request 开始:\nJenkins 本地化  Jenkins 中文官网 有很多的 翻译任务 需要各路英雄自由领取。无规矩不成方圆,在享受自由的同时,也请牢记如下几点:\n 认真、负责第一位 翻译任务通常不建议超过两周  翻译规范   翻译包括 Jenkins 官网的本地化,以及 博客 的翻译。翻译完成后,提交 Pull Request 并等待 Review。对于质量较高、或者适合在微信公众号上发布的文章,需要另外提交一个 Pull Request 。\nJenkins 的 简体中文语言插件 也热切地期待你的 Pull Request 。\n新手 Bug 如果你之前没有参与过 Jenkins 的贡献或者对如何开始不太情况,可以查看 新手 Bug 。这是一些相对比较简单,容易修改的问题。\n分享 你可以在本站或者 Meetup 上分享你在使用 Jenkins 或者相关技术时总结的经验、教训、成果等。\n维护本站点 你可以从了解本站的架构开始。小到错别字修正,大到站点风格、架构完善都需要你的参与。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
611
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
612 613
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
614 615 616 617
        "uri": "https://jenkins-zh.cn/about/channels/",
        "title": "交流",
        "type": "about",
        "date": "2019-01-04 21:13:30 +0800 +0800",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
618
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
619 620 621
        "description": "Jenkins 中文社区交流指南",
        "content": " 为了方便各位 Jenkins 的爱好者、用户以及贡献者之间互相交流,我这里列出来一些途径:\n 邮件组 即时聊天 在本站留言  邮件组 Jenkins 社区有很多 邮件组 ,感兴趣的童鞋请自行翻阅。本文仅介绍中文相关的邮件组:\n            Jenkins 中文用户邮件组  查看历史  订阅 取消订阅 求助   Jenkins 中文本地化兴趣邮件组  查看历史  订阅 取消订阅 求助     注意:点击上面的订阅或者取消都应该会弹出一个发送邮件的窗口,请不要做任何修改,邮件正文保持空白(不要添加邮件签名等内容)直接发送即可。邮件发送成功后,会收到确认的回复。鉴于邮件组是由 Google 提供的服务,无法科学上网的童鞋是无法查看历史邮件的。\n  即时聊天 即时聊天是一种很方便的线上交流方式,你有可能及时地收到大家的帮助,但是不要认为其他人有回答问题的义务。你没有能及时地得到帮助,可能是因为大家在忙、消息太多而被忽略、问题描述的不够详细等等。因此,建议大家在提问之前尽可能保证自己已经对问题理解的很清楚,并在提问时尽可能地给出上下文、复现步骤;当没有及时得到回答的话,可以把问题发送到邮件组(发送之前,请在邮件组中搜索其他人是否已经解决过类似问题),相信遇到过类似问题的人也会尽可能帮助你。\n Jenkins Gitter 中文聊天室 欢迎你!\n留言 本站的留言系统建立在 Github 提供的 Issues 上。欢迎大家在遵守社区行为规范的基础上积极地留言互动。\n",
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
622 623 624
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
625 626
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
627 628 629
        "uri": "https://jenkins-zh.cn/about/",
        "title": "",
        "type": "about",
LinuxSuRen's avatar
LinuxSuRen 已提交
630
        "date": "2019-05-15 20:30:05 +0800 +0800",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
631 632
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
633
        "content": "我们是由 Jenkins 社区在国内的爱好者、贡献者组成。\n请准守我们的行为规范,文明留言。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
634 635 636 637
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
638 639
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
640 641 642 643
        "uri": "https://jenkins-zh.cn/event/readme/",
        "title": "",
        "type": "event",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
644 645
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
646
        "content": " 该目录下,保存 Jenkins 社区相关的活动内容。文件格式为 Markdown,包含的头信息(字段)包括如下:\n type 活动类型,目前只支持 meetup(必需) city 活动举办地(必需) hostDate 活动时间(必需) year 活动所属年份,用于按年度分开展示(必需) poster 活动海报(必需) topic 活动主题 speakers 分享人,数组格式 sponsors 赞助商(公司、社区等),数组格式 abstract 活动简介 agenda 活动日程  time 时间 item 事项  status 活动状态  发起活动 希望发起活动的人或者组织,请按照如上格式写入一个 Markdown 文件中,并打开一个 Pull Request 到该仓库,等待审核。\n分享人 对某个活动感兴趣的同学,请在目录 content/speaker 下以 JSON 格式增加自己的个人信息,文件名为 GitHub 账户 ID。然后在您感兴趣的活动中的 speakers 下添加您的 ID。\n赞助 如果您所在的企业、出版社、社区等对某个活动感兴趣,打算给 Jenkins 开源社区活动一定的赞助,请参考“分享人”的流程添加自己的信息。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
647 648 649 650
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
651 652
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
653 654 655 656
        "uri": "https://jenkins-zh.cn/event/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
657 658
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
659
        "content": "sdfsdds\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
660 661 662
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
663
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
664
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
665
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
666 667 668 669
        "uri": "https://jenkins-zh.cn/event/beijing-2019-04-20/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
670 671
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
672 673 674 675
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
676
        "poster": "/images/meetup/cloud-native-community-day.jpeg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
677 678
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
679 680 681 682
        "uri": "https://jenkins-zh.cn/event/beijing-2019-11/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
683 684
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
685 686 687 688
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
689
        "poster": "/images/meetup/hacktberfest.jpg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
690 691
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
692 693 694 695 696 697 698 699
        "uri": "https://jenkins-zh.cn/event/hangzhou-2019-05/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
700 701
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
702
        "poster": "/images/meetup/hangzhou.jpeg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
703 704
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
705 706 707 708 709 710 711 712 713
        "uri": "https://jenkins-zh.cn/event/shanghai-2019-06/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "sssdfssfasdfs\n",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
714
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
715
        "poster": "/images/meetup/shanghai.jpeg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
716
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
717
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
718 719 720 721
        "uri": "https://jenkins-zh.cn/event/shenzhen/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
722 723
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
724 725 726 727
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
728
        "poster": "/images/meetup/shenzhen.jpeg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
729 730
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
731 732 733 734
        "uri": "https://jenkins-zh.cn/event/wuhang/",
        "title": "",
        "type": "meetup",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
735 736
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
737 738 739 740
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
741
        "poster": "/images/meetup/hacktberfest.jpg"
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
742
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
743
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
744 745 746 747
        "uri": "https://jenkins-zh.cn/sponsor/alauda/",
        "title": "",
        "type": "sponsor",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
748 749
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
750 751 752 753 754
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
755
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
756
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
757 758
        "uri": "https://jenkins-zh.cn/wechat/contributing/",
        "title": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
759
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
760 761 762 763 764
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " Contributing to Jenkins WeChat This page provides information about contributing articles to the Jenkins WeChat subscription account.\nScope  Translated blogs from jenkins.io Jenkins events Other Jenkins-related articles  How to do Everyone could create a PR what are you hoping to publish to Jenkins WeChat. But you\u0026rsquo;d better do this ahead of schedule one week.\nCopy from the sample.md, then change the content and front matter. All files name only can use numbers, alphabets or -. The file name should contains the publish date.\nReview All PRs should get at least one approve. If your PR gets no response then please ping @jenkins-infra/chinese-localization-sig.\n",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
765
        "translator": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
766 767 768 769
        "original": "",
        "poster": ""
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
770 771 772 773
        "uri": "https://jenkins-zh.cn/wechat/readme/",
        "title": "",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
774 775
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
776
        "content": " Jenkins WeChat WeChat is similar with Twitter. Almost everyone have their own account with WeChat in China.\nJenkins WeChat subscription account will deliver the messages or events from the Jenkins Community.\nAll articles should be open-source, every contributor could create a PR. Once we reviewed it, your articles could be released.\nWe have a robot who can reply to your messages automatically. Unfortunately, its ability is very limitation. It just can understand a few words from here.\nTODO List Pick up a task from here, if you\u0026rsquo;re interesting in contribution. See our contributing guide.\nYou can find all contributors at here.\nJoin us Please scan QRCode below:\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
777 778 779 780
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
781
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
782
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
783 784 785 786
        "uri": "https://jenkins-zh.cn/wechat/articles/readme/",
        "title": "",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
787 788
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
789
        "content": " 这里存放的是 Jenkins 官方微信公众号文章,文件采用 Markdown 格式,但包含一些必要的描述性字段。文章的校对、审核、排期等都通过 Pull Request 来完成。PR 合并后会发布到 Jenkins 中文社区网站。\n目录 文章以发布的排期来存放,层级为:年份/月份。如果月份为个位数的话,要以0开头,例如:01。\n以文章的文件名前缀作为图片的目录,例如:文章的文件名为 2019-01-01-sample.md,我们需要在同级目录下创建文件夹 2019-05-01-sample , 并在里面保存当前文章中的图片(封面、插图等)。\n排期 为了尽可能满足你期望的发布日期,可以自行选择,但同时需要满足如下的条件:\n 为保障大家有足够的时间进行 Review,建议排到一周以后 工作日 避免同一天有相同类型的文章  文件名 文件名前缀为“年月日”,中间部分需要以英文来描述。例如:2019-01-01-sample.md。\n字段 文件中的字段,是为了描述文章相关的必要信息。具体的说明请参考:sample.md。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
790 791 792 793
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
794
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
795
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
796 797 798 799
        "uri": "https://jenkins-zh.cn/wechat/images/readme/",
        "title": "",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
800 801
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
802
        "content": "这里用来存放图片素材。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
803 804 805 806
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
807 808
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
809 810 811 812
        "uri": "https://jenkins-zh.cn/wechat/management/auto-reply/readme/",
        "title": "",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
813 814
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
815
        "content": "通过微信公众号的 API 接口实现部分功能,这里主要是存放自动回复的消息。\n我们的 API 后端代码是基于 Golang 编写的。\n支持的消息类型包括:\n 文本 图片 文章(公众号中的)  上面提到的消息类型,也就是字段 msgType 的值,包括:text、image、news。 更多的细节可以参考源码。\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
816 817 818 819
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
820 821
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
822 823 824 825
        "uri": "https://jenkins-zh.cn/wechat/management/contributors/readme/",
        "title": "",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
826
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
827
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
828
        "content": " 我们在发布原创、翻译等文章时,会首先从该目录下查找是否有对应的文件,没有的话就使用作者的 GitHub ID 作为署名。\n如果作者(或译者)希望采用其他的署名,请在当前目录下提交相应的信息。 文件名为小写的 GitHub ID ,例如:linuxsuren.yml。\n字段说明  name 唯一标示,与 GitHub ID 一致 github GitHub ID nickname 署名  ",
LinuxSuRen's avatar
LinuxSuRen 已提交
829 830 831 832
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
833
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
834
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
835 836
        "uri": "https://jenkins-zh.cn/wechat/management/menus/readme/",
        "title": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
837
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
838 839 840 841 842 843 844
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "这里存存放菜单信息。\n",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
845 846 847
        "poster": ""
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
848 849
        "uri": "https://jenkins-zh.cn/wechat/management/operators/readme.en/",
        "title": "",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
850
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
851
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
852 853
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
854
        "content": " About Records about how can publish the Jenkins WeChat articles.\nRequest permission If you want to help publish Jenkins WeChat articles, you need to create a PR with the file below. The file name should follow this pattern: githubid-short-term.yaml.\nExample file:\nwechat: wechatid github: linuxsuren terms: - 2018-11-11  Duty All articles should exist in the current git repo. Your job is just copying it then choose the right date to publish. Formatting is necessary, the content modify is unacceptable.\n",
LinuxSuRen's avatar
LinuxSuRen 已提交
855 856 857 858
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
859
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
860
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
861 862 863 864
        "uri": "https://jenkins-zh.cn/wechat/management/operators/readme/",
        "title": "",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
865
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
866 867 868
        "description": "",
        "content": " 关于 本文描述如何发布 Jenkins 官方微信公众号文章。\n发布时间 我们在每周一、三、五晚上九至十点发布文章。\n每次发布,同一类型的文章只能包含一篇。需要在同一天发布多篇文章的话,顺序如下:\n 活动、通知 原创 翻译 转载  申请权限 如果您愿意帮忙发布 Jenkins 微信公众号文章,您需要新建(或更新)如下的示例文件,并创建一个 PR 。文件名的格式如:githubid-short-term.yaml.\n示例文件:\nwechat: wechatid github: linuxsuren terms: - 2018-11-11  根据微信公众号平台的规定,可以绑定5个长期运营者, 20个短期(一个月)运营者。上面的字段 terms 为管理周期。\n短期运营者 有至少一篇文章被发布在公众号上,熟悉发布流程,认真负责。\n长期运营者 有至少三次的短期运营者经历,并经过小组全体成员同意。\n职责 所有的文章,都需要提交到该仓库中。您的任务是从该仓库中拷贝文章,然后在公众号平台上创建,进行必要的排版处理。在发布之前,需要把预览链接发送到给大家进行审查。最后,没问题的话,设置发送时间。注意,公众号中的内容必须与该仓库保持一致。\n",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
869 870 871
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
872
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
873
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
874 875 876 877 878 879 880 881
        "uri": "https://jenkins-zh.cn/weibo/weibo-operating-charter/",
        "title": "",
        "type": "weibo",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": " Jenkins 官方微博运营章程 该文旨在说明 Jenkins 官方微博运营规范。\n需要讨论的问题  运营者选取形式\n志愿或其他形式 发布的内容\n同步微信公众号/同步 Twitter/类似其他机构官方账号与粉丝互动 发布内容的形式(分享/原创长微博)\n微博官方提供了分享微博和发布长微博的接口。 发布的时间/频率 微博的自动化\n 维护 Jenkins weibo plugin,需要进一步测试(较长时间无人维护,可能存在接口变动)\n 开发新的插件  对评论的回复  ",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
882
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
883
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
884
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
885 886
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
887 888
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/12/2018-12-19-jenkins-survey/",
        "title": "2018年 Jenkins 国内使用情况调查问卷",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
889
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
890 891 892 893
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": ["survey"],
        "description": "共建开放、包容、活跃的 Jenkins 社区",
        "content": "近年来,在数字化转型的压力之下,以 DevOps 和微服务为代表的云原生技术,作为企业数字化转型的重要支撑,活跃于开源技术的舞台。 而 DevOps 作为一种理念,落地交付必然离不开 CI/CD 等工具的支持。 Jenkins 在此方面的重要作用,相信大家也是有目共睹。Jenkins 之所以深受国内用户的喜爱,不仅因为它开源免费、功能强大、插件众多,其背后社区的开放、包容和活跃,更是其生命力之所在!\n在新的一年里, Jenkins 社区希望能够更好地推广和传播这项技术,使越来越多的 Jenkins 中文用户能在实际工作中体会它的魅力。正因如此,我们发起了 “2018年 Jenkins 国内使用情况调查问卷”,希望通过这份问卷的互动,我们能够更加清晰 Jenkins 社区2019年的发展方向。\n请扫一扫下面的二维码,或者在微信中长按识别,完成下面的问卷。只需要占用您大概1~2分钟的时间。\n问卷有效时间,从 2018年12月19日 到 2019年1月9日 截止。\n另外,还有两则好消息与大家分享。\n第一则好消息是 Jenkins 中文站点已经正式上线,大家可以在上面找到入门教程、使用案例以及优秀的技术博客,我们会不断完善相关文档和教程。当然,无论是贡献文档、代码,还是其他任何形式的贡献,非常欢迎大家参与其中。从来没有参与过开源项目的朋友也不用担心,可以通过微信公众号留言给我们,志同道合的小伙伴们会主动与你联系,助你一同踏入精彩的开源世界。\n另一则好消息是我们将通过此官方微信公众号,陆续推出 Jenkins 相关系列视频,由浅入深地为使用者们介绍 Jenkins 相关知识及使用经验。对于“如何构建特定语言的项目”、“如何在 Kubernetes 集群中更好地利用 Jenkins ”以及“如何排查问题”等大家感兴趣的热门话题,都可以从这些视频中得到经验分享。\n最后,欢迎订阅 Jenkins 中文邮件组与我们进行交流和互动。衷心希望能够通过更多小伙伴的加入,不断完善开源社区氛围,深度技术互动,协力共建一个更加开放、更加包容、更加活跃的 Jenkins 社区!\n有内容、有态度的 Jenkins 社区,期待有你同行!\n",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
894
        "auhtor": "linuxsuren",
LinuxSuRen's avatar
LinuxSuRen 已提交
895 896 897
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
898 899
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
900 901 902 903 904 905 906 907 908
        "uri": "https://jenkins-zh.cn/tags/ai/",
        "title": "Ai",
        "type": "tags",
        "date": "2019-04-22 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
909 910
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
911 912
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
913 914
        "uri": "https://jenkins-zh.cn/tags/ansible/",
        "title": "Ansible",
LinuxSuRen's avatar
LinuxSuRen 已提交
915
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
916
        "date": "2019-05-20 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
917 918
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
919 920 921 922 923
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
924
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
925
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
926 927 928 929
        "uri": "https://jenkins-zh.cn/categories/",
        "title": "Categories",
        "type": "categories",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
930 931
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
932 933 934 935 936
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
937
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
938
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
939 940
        "uri": "https://jenkins-zh.cn/tags/cd/",
        "title": "Cd",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
941
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
942
        "date": "2019-05-24 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
943 944
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
945 946 947 948 949
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
950 951
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
952 953 954 955 956 957 958 959 960
        "uri": "https://jenkins-zh.cn/tags/cdf/",
        "title": "Cdf",
        "type": "tags",
        "date": "2019-05-13 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
961 962
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
963 964
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
965 966
        "uri": "https://jenkins-zh.cn/tags/cdsummit/",
        "title": "Cdsummit",
LinuxSuRen's avatar
LinuxSuRen 已提交
967
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
968
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
969 970
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
971 972 973 974 975
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
976 977
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
978 979
        "uri": "https://jenkins-zh.cn/tags/cfp/",
        "title": "Cfp",
LinuxSuRen's avatar
LinuxSuRen 已提交
980
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
981
        "date": "2019-05-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
982 983
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
984 985 986 987 988
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
989
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
990
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
991 992 993
        "uri": "https://jenkins-zh.cn/tags/ci/",
        "title": "Ci",
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
994
        "date": "2019-05-24 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
995
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
996 997 998
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
999 1000 1001 1002
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1003
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1004 1005 1006 1007
        "uri": "https://jenkins-zh.cn/tags/cicd/",
        "title": "Cicd",
        "type": "tags",
        "date": "2019-03-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1008
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
1009 1010 1011
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1012 1013 1014
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1015
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1016
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1017 1018 1019
        "uri": "https://jenkins-zh.cn/tags/cloud-native/",
        "title": "Cloud Native",
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1020
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1021 1022
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1023
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1024 1025 1026 1027
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1028
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1029
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1030 1031 1032
        "uri": "https://jenkins-zh.cn/tags/community/",
        "title": "Community",
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1033
        "date": "2019-05-27 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1034 1035
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1036
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1037 1038 1039 1040
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1041
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1042
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1043 1044 1045
        "uri": "https://jenkins-zh.cn/tags/configuration-as-code/",
        "title": "Configuration as Code",
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1046
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1047 1048
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1049 1050 1051 1052
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1053
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1054 1055
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1056 1057 1058 1059
        "uri": "https://jenkins-zh.cn/tags/continuous-integration/",
        "title": "Continuous Integration",
        "type": "tags",
        "date": "2019-04-03 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1060 1061
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1062 1063 1064 1065
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1066
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1067 1068
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1069 1070 1071 1072
        "uri": "https://jenkins-zh.cn/tags/contributing/",
        "title": "Contributing",
        "type": "tags",
        "date": "2019-04-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1073 1074
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1075 1076 1077 1078
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1079
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1080 1081
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1082 1083 1084 1085
        "uri": "https://jenkins-zh.cn/tags/core/",
        "title": "Core",
        "type": "tags",
        "date": "2019-02-20 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1086 1087
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1088
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1089 1090 1091
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1092
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1093
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
    {
        "uri": "https://jenkins-zh.cn/tags/coverage/",
        "title": "Coverage",
        "type": "tags",
        "date": "2019-05-22 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1107
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1108 1109 1110
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/12/2018-12-5-custom-war-packager/",
        "title": "Custom WAR Packager",
        "type": "wechat",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1111
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
        "tags": ["tools", "docker", "jenkins-x", "cloud-native"],
        "description": "打造你自己的 Jenkins!了解自定义 WAR/Docker Packager",
        "content": "我打算给 Jenkins 管理员和开发者介绍一个新的工具 Custom WAR Packager。该工具可以打包 Jenkins 的自定义 WAR 发行版、 Docker 镜像和 Jenkinsfile Runner 包。 它可以打包 Jenkins、插件以及配置为开箱即用的发行版。 Custom WAR Packager 是我们在博客 A Cloud Native Jenkins(/blog/2018/09/12/speaker-blog-a-cloud-native-jenkins/) 中介绍过的无状态 Jenkins master 工具链的一部分。这个工具链已经在 Jenkins X 中被使用,用于构建 serverless 镜像(https://github.com/jenkins-x/jenkins-x-serverless)。\n在这篇文章中,我将会介绍几种 Custom WAR Packager 常见的使用场景。\n== 历史\n正如 Jenkins 本身一样,Custom WAR Packager 开始于一个小的开发工具。在 Jenkins 内运行集成测试很长时间以来都是一个难题。 对此,我们有三个主要的框架: Jenkins Test Harness, Acceptance Test Harness, 和 Plugin Compatibility Tester. 这些框架都需要一个 Jenkins WAR 文件来运行测试。但是假如你想在类似 AWS 一样的自定义环境中进行 Jenkins 测试呢? 或者,你希望基于 Pluggable Storage 的环境也可以复用 Jenkins 流水线测试,来确保没有回归缺陷?\n这并不是一个无意义的问题。Jenkins 项目中有重大的活动正在进行:云原生 Jenkins、Jenkins Evergreen 以及 Jenkins X。 这些都需要很多集成测试来保障持续部署流程。为了复用已有的框架,我们需要打包一个自带配置的 WAR 文件,使得可以在已有的框架中运行集成测试。 这正是 Custom WAR Packager 于 2018年4月 创建的原因。到 2018年9月,它相继支持了 Docker 镜像和 Jenkinsfile Runner, 后者由 Kohsuke Kawaguchi 创建并由 Nicolas de Loof 完善。\n== 包含的内容?\nCustom WAR Packager 是一个工具,可以作为命令行、Maven 插件或者 Docker 来用。 它从用户那获取配置和包。所有内容都由一个 YAML 配置文件管理:\nimage::/images/post-images/2018-10-16-cwp/cwp_flow.png[Custom WAR Packager 构建流程]\n它支持多种输入类型。插件列表可以来自 YAML,pom.xml 或一个 BOM(jep:309[] 提出的 Bill of Materials) 文件。 Custom WAR Packager 不仅支持发布版本,还可以构建部署到 增量仓库 (Jenkins 核心及插件的 CD 流程 - jep:305[]), 甚至直接从 Git 或指定目录中构建。它允许构建的包来自任何源,而无需等待官方的发版。 构建过程也非常快,因为,插件已经通过 Commit ID 缓存到了本地的 Maven 仓库中。\nCustom WAR Packager 还支持下面的配置选项:\n** Jenkins 配置即代码 的 YAMl 文件 ** Groovy Hooks (例如:预配置的 init hooks) ** 系统属性\n== WAR 打包\n每当这个库构建时会打包出来一个 WAR 文件。 通常,Custom WAR Packager 会根据下面对 Jenkins 核心和 JCasC 的配置把所有内容打包的一个 WAR 文件中。\n样例配置:\nbundle: groupId: \u0026quot;io.jenkins.tools.war-packager.demo\u0026quot; artifactId: \u0026quot;blogpost-demo\u0026quot; vendor: \u0026quot;Jenkins project\u0026quot; description: \u0026quot;Just a demo for the blogpost\u0026quot; war: groupId: \u0026quot;org.jenkins-ci.main\u0026quot; artifactId: \u0026quot;jenkins-war\u0026quot; source: version: 2.138.2 plugins: - groupId: \u0026quot;io.jenkins\u0026quot; artifactId: \u0026quot;configuration-as-code\u0026quot; source: # Common release version: 1.0-rc2 - groupId: \u0026quot;io.jenkins\u0026quot; artifactId: \u0026quot;artifact-manager-s3\u0026quot; source: # Incrementals version: 1.2-rc259.c9d60bf2f88c - groupId: \u0026quot;org.jenkins-ci.plugins.workflow\u0026quot; artifactId: \u0026quot;workflow-job\u0026quot; source: # Git git: https://github.com/jglick/workflow-job-plugin.git commit: 18d78f305a4526af9cdf3a7b68eb9caf97c7cfbc # etc. systemProperties: jenkins.model.Jenkins.slaveAgentPort: \u0026quot;9000\u0026quot; jenkins.model.Jenkins.slaveAgentPortEnforce: \u0026quot;true\u0026quot; groovyHooks: - type: \u0026quot;init\u0026quot; id: \u0026quot;initScripts\u0026quot; source: dir: src/main/groovy casc: - id: \u0026quot;jcasc\u0026quot; source: dir: casc.yml  == Docker 打包\n为了打包 Docker,Custom WAR Packager 使用官方的 Docker 镜像 jenkins/jenkins 或同样格式的其他镜像。构建中,WAR 文件会被该工具所替换。这也就意味着镜像的 所有 特色在该自定义构建中都可用: plugins.txt, Java 选项, Groovy hooks 等等。\n## ... ## WAR configuration from above ## ... buildSettings: docker: build: true # Base image base: \u0026quot;jenkins/jenkins:2.138.2\u0026quot; # Tag to set for the produced image tag: \u0026quot;jenkins/custom-war-packager-casc-demo\u0026quot;  例如:示例 展示了打包带有将构建日志存储到 Elasticsearch 的 Docker 镜像。 尽管这些已经作为了 jep:207[] 和 jep:210[] 的一部分,你还是可以查看这个示例,了解该 Docker 镜像是如何配置、连接到 Elasicsearch、 然后启动外部的日志存储,而不需要改变日志的界面。一个 Docker Compose 文件对于运行整个集群是必要的。\n== Jenkinsfile Runner 打包\n这可能是 Jenkinsfile Runner 最有意思的模式。 三月份,在开发者列表中 宣布了 一个新的项目 Jenkinsfile Runner。 大体的思路是,支持在单一 master 上只运行一次并打印输出到控制台的 Jenkins 流水线。 Jenkinsfile Runner 作为命令或一个 Docker 镜像来运行。 虽然只推荐 Docker 的形式,但是 Custom WAR Packager 都能够生成。 有了 Jenkinsfile Runner 你可以像下面的方式来运行流水线:\ndocker run --rm -v $PWD/Jenkinsfile:/workspace/Jenkinsfile acmeorg/jenkinsfile-runner  当我们开始在云原生特别兴趣小组(Cloud Native SIG)中开始研究无状态(也就是“一次”)时, 有一个想法就是使用 Custom WAR Packager 和其他已有的工具(Jenkinsfile Runner, Jenkins Configuration as Code 等)来实现。 也许只是替换 Jenkinsfile Runner 中的 Jenkins 核心的 JAR 以及插件,但这还不够。 为了高效,Jenkinsfile Runner 镜像应该启动的 *很快*。在这个实现中,我们使用了 Jenkins 和 Jenkinsfile Runner 一些实验性的选项, 包括:类加载预缓存、插件解压等等。有了这些后,Jenkins 使用 configuration-as-code 和几十个插件可以在几秒钟内启动。\n那么,如何构建自定义 Jenkinsfile Runner 镜像呢?尽管现在还没有发布,我们继续实现上面提到的内容。\n##... ## WAR Configuration from above ##... buildSettings: jenkinsfileRunner: source: groupId: \u0026quot;io.jenkins\u0026quot; artifactId: \u0026quot;jenkinsfile-runner\u0026quot; build: noCache: true source: git: https://github.com/jenkinsci/jenkinsfile-runner.git commit: 8ff9b1e9a097e629c5fbffca9a3d69750097ecc4 docker: base: \u0026quot;jenkins/jenkins:2.138.2\u0026quot; tag: \u0026quot;onenashev/cwp-jenkinsfile-runner-demo\u0026quot; build: true  你可以从 这里 找到用 Custom WAR Packager 打包 Jenkinsfile Runner 的例子。\n== 更多\n还有很多其他的特色没有在本文中提到。例如:它还可以修改 Maven 构建配置或增加、替换 Jenkins 核心中的库(例如:Remoting)。 请查看 Custom WAR Packager 文档 获取更多信息。这个库中还有很多示例。\n如果你有兴趣对这个库做贡献,请创建 PR 并抄送 @oleg-nenashev 和 Raul Arabaolaza,第二位维护者正在研究 Jenkins 自动化测试流程。\n== 下一步?\n还有很多值得改进的地方可以让这个工具更加高效:\n 增加对插件依赖传递的检查以便在构建过程中发现冲突 允许在 YAML 配置文件中设置各种系统属性和 Java 选项 改进 Jenkinsfile Runner 的性能 集成到 Jenkins 集成测试流程中,(查看 Jenkins 流水线库中的 essentialsTest())  还有很多其他的任务需要在 Custom WAR Packager 中实现,但是,现在它已经能够让 Jenkins 用户构建他们自己的发行版。\n",
        "auhtor": "oleg_nenashev",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/developer/",
        "title": "Developer",
        "type": "tags",
        "date": "2019-04-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1125 1126
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1127 1128 1129 1130
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1131
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1132 1133
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1134 1135 1136
        "uri": "https://jenkins-zh.cn/tags/devops/",
        "title": "Devops",
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1137
        "date": "2019-05-17 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1138 1139
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1140 1141 1142 1143
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1144
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1145 1146
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1147 1148 1149 1150
        "uri": "https://jenkins-zh.cn/tags/docker/",
        "title": "Docker",
        "type": "tags",
        "date": "2019-04-10 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1151 1152
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1153 1154 1155 1156 1157
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1158 1159
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1160 1161
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/12/2018-12-26-official-docker-image/",
        "title": "Docker Hub 上的官方 Jenkins 镜像",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1162 1163
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1164 1165 1166 1167 1168 1169 1170 1171
        "tags": ["docker"],
        "description": "正确地使用 Jenkins 镜像",
        "content": " 目前,在 Docker Hub 上有三个不同的仓库正(或曾经)被当作“官方” Jenkins 镜像。 本文是为了申明哪个是当前的官方镜像(截至2018年12月).\n官方的 docker pull jenkins/jenkins\n例如:https://hub.docker.com/r/jenkins/jenkins/ 是正确的仓库。\n在我的博客 对于使用 Jenkins 官方 Docker 镜像推荐的方法 上也有一些记录。\n废弃的 jenkins 已经废弃了很久。 我们停止使用和更新该镜像的简短原因是,我们每次发版时都需要人工参与。 jenkinsci/jenkins 同样已经废弃了很久,但为了过渡,我们会同时更新 jenkins/jenkins(正确的那个) 和 jenkinsci/jenkins。 2018年12月初,我们停止更新 jenkinsci/jenkins(如果您感兴趣的话,查看 INFRA-1934 可以获取更多详情)。\n感谢您的阅读!\n",
        "auhtor": "batmat",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
    {
        "uri": "https://jenkins-zh.cn/tags/docs/",
        "title": "Docs",
        "type": "tags",
        "date": "2019-05-27 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/documentation/",
        "title": "Documentation",
        "type": "tags",
        "date": "2019-05-27 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1198 1199 1200 1201 1202
    {
        "uri": "https://jenkins-zh.cn/tags/electron/",
        "title": "Electron",
        "type": "tags",
        "date": "2019-03-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1203 1204
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1205
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1206 1207 1208 1209
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1210 1211
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1212 1213 1214 1215
        "uri": "https://jenkins-zh.cn/tags/events/",
        "title": "Events",
        "type": "tags",
        "date": "2019-03-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1216 1217
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1218
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1219 1220 1221 1222
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1223 1224
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1225 1226 1227
        "uri": "https://jenkins-zh.cn/tags/evergreen/",
        "title": "Evergreen",
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1228
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1229 1230
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1231
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1232 1233 1234 1235
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1236
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1237
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1238 1239 1240 1241
        "uri": "https://jenkins-zh.cn/tags/flagger/",
        "title": "Flagger",
        "type": "tags",
        "date": "2019-04-26 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1242 1243
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1244
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1245 1246 1247 1248
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1249
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1250
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1251 1252 1253 1254
        "uri": "https://jenkins-zh.cn/tags/general/",
        "title": "General",
        "type": "tags",
        "date": "2019-03-20 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1255 1256
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1257
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1258 1259 1260 1261
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1262
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1263
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1264 1265 1266 1267
        "uri": "https://jenkins-zh.cn/tags/gsoc/",
        "title": "Gsoc",
        "type": "tags",
        "date": "2019-03-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1268
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
1269
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1270
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1271 1272 1273 1274
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1275
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1276
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1277 1278 1279 1280
        "uri": "https://jenkins-zh.cn/tags/gsoc2019/",
        "title": "Gsoc2019",
        "type": "tags",
        "date": "2019-03-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1281 1282
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1283
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1284 1285 1286 1287
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1288
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1289
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1290 1291 1292
        "uri": "https://jenkins-zh.cn/tags/installers/",
        "title": "Installers",
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1293
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1294
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
1295
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1296
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1297 1298 1299 1300
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1301
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1302
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1303 1304 1305 1306
        "uri": "https://jenkins-zh.cn/tags/istio/",
        "title": "Istio",
        "type": "tags",
        "date": "2019-04-26 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1307 1308
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1309
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1310 1311 1312 1313
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1314
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
    {
        "uri": "https://jenkins-zh.cn/tags/jacoco/",
        "title": "Jacoco",
        "type": "tags",
        "date": "2019-05-22 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1328
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1329 1330 1331 1332
        "uri": "https://jenkins-zh.cn/tags/java11/",
        "title": "Java11",
        "type": "tags",
        "date": "2019-02-20 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1333 1334
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1335
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1336 1337 1338 1339
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1340 1341
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1342 1343 1344
        "uri": "https://jenkins-zh.cn/tags/jenkins/",
        "title": "Jenkins",
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1345
        "date": "2019-05-28 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1346 1347 1348 1349
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1350 1351 1352
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1353 1354
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1355 1356 1357
        "uri": "https://jenkins-zh.cn/about/meetups/",
        "title": "Jenkins Area Meetup",
        "type": "about",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1358
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1359
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
1360 1361
        "description": "Jenkins 中国本地活动",
        "content": "我们欢迎每一位愿意一起合作、组织的个人、企业、社区,形式包括但不局限于:\n 案例、经验分享 工作坊,实际操作演练 活动拍照、录像 茶歇、场地赞助 礼品、奖品赞助  下面是目前收集到的,在国内组织过 Meetup 的城市。\n  北京   上海   西安   杭州   成都   深圳   广州   ",
LinuxSuRen's avatar
LinuxSuRen 已提交
1362 1363 1364 1365
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1366
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1367
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1368 1369
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/12/2018-12-12-gasc/",
        "title": "Jenkins Configuration-as-Code: 看,我都不用手动配置",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1370
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
1371
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1372 1373 1374 1375 1376
        "tags": ["configuration-as-code", "jenkinsworld", "jenkinsworld2018"],
        "description": "JCasC 允许我们在启动时或通过 web UI 按需在 Jenkins master 上应用一组 YAML 文件",
        "content": " NOTE: 这篇文章是 Configuration-as-Code 系列的第一部分。\nJenkins 非常灵活,如今已成为实现 CI/CD 的事实标准,同时拥有一个活跃的社区来维护几乎所有工具和用例的插件。但是灵活也是要付出代价的:除了 Jenkins 核心之外,许多插件需要一些系统级别的设置才能正常工作。\n在某些情况下,“Jenkins 管理员”是一个全职职位。 Jenkins 管理员在负责维护基础设施的同时,还要为一个巨大的 Jenkins master 提供数百个已安装的插件和数千个托管作业。 维护最新的插件版本是一项挑战,故障转移(failover)也会是一场噩梦。\n这就像几年前系统管理员必须要为每个服务管理特定的机器一样。 在 2018 年,通过使用基础架构自动化工具和虚拟化,一切都可以作为代码进行管理。 需要一个新的应用服务器作为你的应用的暂存环境吗?那你只需要部署一个 Docker 容器。 基础设施缺少资源吗?那就在你喜欢的云服务上分配更多资源来使用 Terraform。\n在这种情况下,Jenkins 管理员的角色怎么样?他们是否还要花费数小时来点击网页表单上的复选框?也许他们已经采用了一些自动化、依赖于 Groovy 脚本或一些自己写的 XML 模板。\n今年早些时候我们发布了第一个 alpha 版本的 “Jenkins Configuration-as-Code” (JCasC),它是一种基于 YAML 配置文件和自动模型发现的 Jenkins 配置管理新方法。\u0026rdquo;JCasC\u0026rdquo; 已经升级为顶级 Jenkins 项目。 同时,对应的 Jenkins 增强提案已经被接受。\nJCasC 能为 Jenkins 管理员做些什么? JCasC 允许我们在启动时或通过 web UI 按需在 Jenkins master 上应用一组 YAML 文件。 与 Jenkins 用于实际储存配置的详细 XML 文件相比,这些配置文件非常简洁易读。 这些文件还有用户友好的命名约定,使管理员能够轻松地配置所有 Jenkins 组件。\n下面是一个例子:\n[source, yaml] jenkins: systemMessage: \u0026ldquo;Jenkins managed by Configuration as Code\u0026rdquo;\nsecurityRealm: ldap: configurations: - server: ldap.acme.com rootDN: dc=acme,dc=fr managerPasswordSecret: ${LDAP_PASSWORD} cache: size: 100 ttl: 10 userIdStrategy: CaseInsensitive\ngroupIdStrategy: CaseSensitive 如你所见,不需要很长的解释你就可以理解这个 YAML 文件如何配置你的 Jenkins master。\n== 优点\nJCasC 最直接的好处就是可重复性。 管理员现在可以使用完全相同的配置通过一个简单的设置来引导新的 Jenkins master。 这允许他们创建一个测试实例并检查升级插件在沙盒环境中的影响。 这也使他们对故障转移和灾难恢复方案更有信心。\n当管理员开始在源代码管理中管理 Jenkins 的 YAML 配置文件时,他们也会感受到类似使用 Terraform 一样的好处。 这样做可以让他们对 Jenkins master 配置进行审核,使其具有可逆性。 他们可以建立一个合理的配置改变运行 Jenkins 实例的工作流,并确保在实际应用任何修改到他们的 Jenkins master 之前配置是健康的。\n最后也是最重要的是,由于能够快速设置 Jenkins master 并且能用一组共享的 YAML 配置文件控制它们,管理员现在可以给每个团队提供一个 Jenkins 实例,并且在安装插件有更高的灵活性。 只要他们还在使用 Jenkinsfiles 管理构建定义(build definition),master 就会或多或少地成为你们团队的短期的基础架构。\n使用 Configuration-as-Code,我们可以不再像对待宠物那样对待我们的 Jenkins master,而像对待牛那样管理它们,你也可以毫不费力地替换它们。 欢迎来到 “as-code” 的世界。\n.他们仍然很可爱,对吧? Cattle not pets\nOk, 那么之后呢? 你可以在项目中阅读有关 Jenkins Configuration-as-Code 插件的更多信息。 与社区和贡献者们交流,加入我们的 gitter 频道, 或者来我们的 Jenkins World 一起讨论 JCasC 项目及其未来!\n另外,不要错过 Configuration-as-Code 系列的下一篇文章,我们将会了解 JCasC 如何处理密码及其他凭据等敏感数据。\n",
        "auhtor": "ndeloof",
        "translator": "arjenzhou",
LinuxSuRen's avatar
LinuxSuRen 已提交
1377 1378
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1379
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1380
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1381 1382 1383
        "uri": "https://jenkins-zh.cn/tags/jenkins-x/",
        "title": "Jenkins X",
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1384
        "date": "2019-05-24 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1385 1386 1387 1388 1389
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1390 1391
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1392 1393
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1394 1395 1396
        "uri": "https://jenkins-zh.cn/",
        "title": "Jenkins 中文社区",
        "type": "page",
LinuxSuRen's avatar
LinuxSuRen 已提交
1397
        "date": "2019-05-28 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1398
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
1399 1400
        "description": "",
        "content": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1401 1402 1403 1404
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1405
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1406
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1407
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-15-kubecon-cn/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1408
        "title": "Jenkins 中文社区邀您来上海共同参与2019年的国际开源盛宴",
LinuxSuRen's avatar
LinuxSuRen 已提交
1409 1410
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1411 1412
        "tags": ["cloud-native", "kubernetes", "kubecon", "ci", "cd", "cdsummit"],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1413 1414 1415 1416 1417
        "content": " KubeCon + CloudNativeCon | Open Source Summit | 持续交付峰会 中国2019 2019年4月10日,旧金山 - Linux基金会是一家以开源促进大众创新的非营利组织,今天公布将于2019年6月24至26日在中国上海举行的 KubeCon + CloudNativeCon + Open Source Summit 中国2019日程。\nOpen Source Summit 中国2019前身为 LinuxCon + ContainerCon + CloudOpen 中国(LC3),是开源社区寻求合作、共享信息、了解当今最有影响力的开源技术和议题的重要平台,包括:云原生、无服务器、微服务、物联网、人工智能、网络、Linux 等。\n2019年,首次将Open Source Summit中国和KubeCon + CloudNativeCon中国整合成一项活动,只需购票一次即可参加KubeCon + CloudNativeCon + Open Source Summit中国。\n本届持续交付峰会将由 CNCF 承办在大会的第 0 天举行,汇聚了各个开源 CI/CD 社区。\nJenkins 中文社区成员在大会上将进行分享 Jenkins 中文社区成员夏润泽(北京优帆科技有限公司)将在大会上作为演讲嘉宾为大家带来主题为 Jenkins X 在 kubernetes 之上运行的无服务器 Jenkins 的分享。\nJenkins 中文社区邀您参与社区共同成长 在开源盛会开展的同时,我们希望能够与更多的小伙伴们一同在线上完善开源社区氛围、线下深度互动,努力构建一个有内容、有态度的优质技术社区。\n",
        "auhtor": "runzexia",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1418
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1419
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1420
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-16-localization-zh-cn-plugin/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1421
        "title": "Jenkins 中文语言包",
LinuxSuRen's avatar
LinuxSuRen 已提交
1422 1423
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1424
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
1425
        "description": "Jenkins 中文版本升级通知",
LinuxSuRen's avatar
LinuxSuRen 已提交
1426 1427 1428 1429 1430
        "content": "部分 Jenkins 中文用户可能已经发现,在最近升级 Jenkins 版本,或下载较新的 Jenkins 后,界面上很多部分显示的是英文。对此,我简单介绍一下原因以及如何安装中文插件。\n各种语言的本地化资源文件都是集中存放在 Jenkins Core 及其插件中,这对于要做本地化贡献的人来说,需要向很多代码仓库中提交 PR。最明显的一个现象就是,这些仓库不一定都会有熟悉中文的维护者,因此导致 PR 无法真实、及时地进行 Review 以及合并发布。基于以上的考虑,我开发了简体中文插件,并从 Jenkins 2.145 版本中把大部分的中文本地化资源文件迁移到了该插件中。而且,最终会对 Jenkins Core 以及流行的插件中所有的中文本地化资源文件进行迁移。\n安装简体中文插件也很简单,只要在 Jenkins 的插件管理界面上,搜索*中文*就能找到该插件。安装并重启后就能看到中文界面。\n更多细节请查看 变更记录 。欢迎对中文本地化工作感兴趣的同学加入我们!\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1431
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1432
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1433
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-30-k8s-jenkins-secet-agent/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1434
        "title": "Jenkins 和 Kubernetes -云上的神秘代理",
LinuxSuRen's avatar
LinuxSuRen 已提交
1435 1436
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1437 1438
        "tags": ["jenkinsworld", "jenkinsworld2018", "cloud-native", "kubernetes"],
        "description": "运行在 K8S 上的 Jenkins 动态节点",
LinuxSuRen's avatar
LinuxSuRen 已提交
1439 1440 1441 1442 1443
        "content": " 最近我们构建和部署服务的方式与原来相比简直就是突飞猛进,像那种笨拙的、单一的、用于构建单体式应用程序的方式已经是过去式了。我们努力了这么久,终于达到了现在的效果。现在的应用为了提供更好的拓展性和可维护性,都会去拆解成各种相互依赖小、解耦性强的微服务,这些服务有各自的依赖和进度。如果你想去构建你所负责的服务,那么从一开始,就应该使用 CI/CD 的方式;当然,如果你走上了这条路, Jenkins 就是你的良师益友。\n如果你是做微服务的话,那让我们在开始之前先花些时间想一想。如果你只在 Jenkins 上构建单体式应用程序,那你肯定每天都会运行很多 Jenkins job, 而且还要不厌其烦地运行很多次。所以,我们应该好好想清楚怎么样来做出一些改变来适应这种事情。其实只需要付出一些努力,Jenkins 就可以帮我们很好地解决这种事情。\n我的 Jenkins 的进阶之路 作为一个 Devops 从业者,我遇到的最大问题是如何管理并优化自己的 Jenkins agent 结构。如果只是用 Jenkins 玩玩,实验性地跑一些流水线,那根本不用考虑 agent 的事情。如果你每天要跑成百上千条流水线的话,那考虑怎么去做优化就是一件非常非常重要的事情了。在 Jenkins 进阶之路中,我也尝试了各种不同的方式来寻找最好的 Jenkins agent 的使用方式。相信如果你也和我一样经历过,那下面这些事情你一定会很熟悉喽。\n下面是我在这些年中使用 Jenkins 的各个阶段.\n 所有的构建都在 master 节点上跑,在这个节点上运行所有的组件. (我给这个阶段起了个可爱的名字, Hello Jenkins) 创建一个 Jenkins EC2 代理,并且在这个代理上运行所有的构建,怎么说呢, 就是大而全,这个节点什么都能做。如果需要同时做多条任务,那就把这个大而全的节点克隆一份。 (这个阶段我起的名字是 Monster Agent.) 为每种服务创建不同的 Jenkins EC2 的节点 (这个阶段我起的名字叫做 Snowflake Agent.) 在容器中运行流水线的所有步骤。 打个比方,在 Jenkins 中使用 Docker Plugin 这个插件将代理挂载到容器中,或者使用 multi-stage Dockerfiles 把所有构建,测试打包的流程都封装起来。这两种方法都是很好的容器抽象化的开端,并且允许您轻松地将制品从一个容器复制到另一个容器。当然了,每一种方法都是需要访问 Docker engine 的。为了让我的 Jenkins 代理能够正常工作,现在我用以下几种方式来管理 docker host 在我的 Jenkins 主容器中运行一个Docker engine - Docker in Docker (DinD) 把主机上的 Docker socket 挂载到我的容器中来,让我的容器能够以 sidecar 的方式运行。 为 Jenkins 主服务器配置单个外部 EC2 Docker 主机,以用于在容器中启动构建 使用 EC2 插件和包含 Docker Engine 的 AMI 动态启动代理,然后运行多阶段 Dockerfile 中的所有步骤  以上这些阶段各有利弊,但都是为了让我们从管理 Jenkins 节点中解放出来。不过,最近我又进阶到了另外一个阶段:Jenkins on Kubernetes.\n一旦你在 Jenkins 中把构建节点和 job 都容器化了的话,迁移工作平台将变的十分简单易行。在这里郑重声明一下,在我用这个方法之前我一直没有接触过 Kubernetes,一次也没有。也就是说,在 Google Cloud Platform(GCP)GKE 中创建 Kubernetes 集群,使用 Helm Chart启动 Jenkins master ,并在 Kubernetes 集群中的 Jenkins 代理中运行构建是非常简单的。\n流水线脚本中启动 K8s 中的代理 这篇文章就是为了向大家说明,如何配置 Jenkins 才能使流水线脚本能够在 K8s 集群中启动 Jenkins 节点。首先你要先安装 Kubernetes plugin 这个插件。有意思的是,当我用 Helm chart 来安装我的 Jenkins 时,安装好的 Jenkins 里面已经有了这个插件。还有一个前提,是你启动的 Jenkins 节点要和你的 Jenkins master 在同一个 K8s 集群里。\n一旦在 K8s 中运行了你的 Jenkins master 节点,那只需要再简单地配置几步,就能启动一个小构建啦。\n配置 Jenkins Master 为了保证 Jenkins 能够访问 K8s 集群的资源,首先你需要按照以下步骤创建一些凭据:\n 进入 Jenkins 的 UI 界面,点击左边导航栏里的凭据链接 点击 Stores scoped to Jenkins 列表下 global 中的 Add credentials (将鼠标悬停在链接旁边即可看到箭头) 点击添加凭证 写好 Kubernetes Service Account 将范围设置为全局 点击 OK 按钮  这样之后 Jenkins 就可以使用这个凭据去访问 K8s 的资源啦\n在 Jenkins Master 中配置云 下一步就是在 Jenkins 中设置云的配置\n 进入 Jenkins UI 界面,点击 系统管理 → 系统设置 进入管理界面后查找 『云』,一般在下面,然后点击 『新增一个云』,选择 kubernetes 类型 然后这些是必填的参数 Name: 这个自定义, 默认的是kubernetes Kubernetes URL: https://kubernetes.default- 这个一般是从你的 service account 自动配置的 Kubernetes Namespace: 一般是 default 除非你要在一个特殊的命名空间 ,否则不要动他 Credentials: 选择上一步你创建的凭据 Jenkins URL: http://\u0026lt;your_jenkins_hostname\u0026gt;:8080 Jenkins tunnel: \u0026lt;your_jenkins_hostname\u0026gt;:5555 - 这就是用来和 Jenkins 启动的 agent 进行交互的端口  你看,只需要几个参数就能在 K8s 集群中启动一些节点了,当然你的环境有需要的话,你也可以做一些其他的调整\n现在你已经可以通过定义一些 pod 来让 Jenkins master 访问 K8s 集群了。pod其实是 K8s 中的概念,在一个 pod 中里面会有一个或者多个容器,它们共享网络还有存储,然后我们可以在这个 pod 中执行一些构建工作。每一个 Jenkins 节点都是作为 K8s pod 来启动的。这个 pod 里面经常都会包含一个默认的 JNLP 的容器,还有一些你在 pod 模板中定义的容器。现在有至少两种方法来定义你的 pod template。\n通过 Jenkins UI 配置一个 pod template  还是老地方 Manage Jenkins → Configure Systems 还是老地方 找到之前配置 Jenkins K8s 的地方 点击 Add Pod Template button 选择 Kubernetes Pod Template 输入下面的值   Name:自定义 Namespace: default-除非你想换个你在上一步自定义的命名空间 Labels: 自定义 - 这个将用来匹配你在 jenkinsfile 中的 label 值 Usage: 如果你想让这个 pod 作为默认节点的话,就选择 \u0026ldquo;Use this node as much as possible\u0026rdquo;, 如果选择 \u0026ldquo;Only build jobs with label matching expressions matching this node\u0026rdquo; 的话 那就是只有在 Jenkins 脚本中定义的label匹配的构建才能使用这个节点 The name of the pod template to inherit from: - 这个可以置空. 现在还用不到 Containers: 你想在这个 pod 中启动的容器,在下面会有详细的介绍 EnvVars: 你想在 pod 中注入的环境变量 下面会有接受 Volumes: 你想在 pod 中挂载的任何一种的卷  需要记住,在一个 pod 中会有不止一个容器,它们都是同生共死的。如果你是用 Helm chart 安装 Jenkins 的话,pod 中就会包含 JNLP 这个容器,这个容器也是 Jenkins agent 中必须包含的。然而为了完成更多的服务的构建,你还需要添加一些其他工具链的容器。\n添加容器模板  进入 Jenkins UI 界面,回到上一步创建 pod template 的地方 点击 Add Container 按钮, 选择 Container Template 输入下面的值 Name:自定义 Docker image: 根据你自己的需求来写,比如你在构建一个用 go 写的应用,那你就可以输入 golang:1.11-alpine3.8 Label: 表明要用在流水线脚本中引用此容器模板的标签字符串 Always pull image: - 如果你想让 pod 启动的时候都去拉取镜像 那就选择这个  你可以保留其他参数的默认值,但是你可以看到该插件可以对你的 pod 以及在其中运行的各个容器进行很详细地控制。你可以通过此插件设置在 Kubernetes pod 配置中的任何值。你还可以通过输入原始 YAML 来注入配置数据。你无需因选项过多而分心,选择配置它们中得一小部分就可以获得工作环境啦。\n您可以单击容器模板中的“添加环境变量”按钮,将环境变量注入特定容器,也可以单击模板中的“添加环境变量”按钮,将环境变量注入所有的容器。 以下环境变量会自动注入默认的 JNLP 容器,来保障它能自动连接到 Jenkins 主服务器:\n JENKINS_URL: Jenkins 网页界面网址 JENKINS_JNLP_URL: Jenkins 特定 slave 中 jnlp 的 url JENKINS_SECRET: 身份验证的密钥 JENKINS_NAME: Jenkins 代理的名称  如果单击“添加卷”按钮,您将看到几个用于添加卷的选项,在这里我使用 Host Path Volume 选项将 docker socket 安装在 pod 中。然后,我可以运行安装了 Docker 客户端的容器,并且来构建和推送 Docker 镜像。\n此时,我们为 Kubernetes 集群创建了一个云配置,并定义了一个由一个或多个容器组成的 pod。现在,我们如何使用它来运行 Jenkins 工作? 很简单,只需要我们在 Jenkins 流水线脚本中通过标签引用 pod 和容器就可以了。 本文中的示例是使用脚本流水线,当然您可以使用声明式流水线语法实现相同的结果:\nnode('test-pod') { stage('Checkout') { checkout scm } stage('Build'){ container('go-agent') { // This is where we build our code. } } }  用 jenkinsfile 来实现相同的功能 通过 UI 配置插件现在看起来是很不错的。但是有一个明显的问题是,配置不能像源代码一样能够进行版本控制和存储。幸运的是,您可以直接在 Jenkinsfile 中创建整个 pod 定义。哈哈,在 Jenkinsfile 中有什么你不能做的???\n可以将 UI 或 YAML 定义中可用的任何配置参数添加到 podTemplate 和 containerTemplate 部分。 在下面的示例中,我已经定义了一个包含两个容器模板的 pod。 pod 标签将会用于节点,表示我们想要启动此 pod 的实例。 直接在节点内定义但没有在容器块中定义的任何步骤,都可以在默认的 JNLP 容器中运行。\n容器块用于表示该容器块内的步骤应在具有给定标签的容器内运行。我已经定义了一个标签为 golang 的容器模板,我将用它来构建 Go 可执行文件,我最终将其打包成 Docker 镜像。在 volumes 中,我已经指出我想要挂载主机的 Docker 套接字,但我仍然需要 Docker 客户端使用 Docker API 与它进行交互。因此,我已经定义了一个标签为 docker 的容器模板,该模板使用安装了 Docker 客户端的镜像。\npodTemplate( name: 'test-pod', label: 'test-pod', containers: [ containerTemplate(name: 'golang', image: 'golang:1.9.4-alpine3.7'), containerTemplate(name: 'docker', image:'trion/jenkins-docker-client'), ], volumes: [ hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock', ], { //node = the pod label node('test-pod'){ //container = the container label stage('Build'){ container('golang'){ // This is where we build our code. } } stage('Build Docker Image'){ container(‘docker’){ // This is where we build the Docker image } } } })  在我的基于 Docker 的流水线脚本中,我构建了 Docker 镜像并将它们推送到了 Docker 仓库,对我来说,能够复制这些配置信息非常重要。完成后,我已准备好使用 gcloud(Google Cloud SDK)构建我的镜像,并将该镜像推送到 Google Container Registry,以便部署到我的 K8s 群集。\n为此,我使用 gcloud 镜像指定了一个容器模板,并将我的 docker 命令更改为 gcloud 命令。 就这么简单!\npodTemplate( name: 'test-pod', label: 'test-pod', containers: [ containerTemplate(name: 'golang', image: 'golang:1.9.4-alpine3.7'), containerTemplate(name: 'gcloud', image:'gcr.io/cloud-builders/gcloud'), ], { //node = the pod label node('test-pod'){ //container = the container label stage('Build'){ container('golang'){ // This is where we build our code. } } stage('Build Docker Image'){ container(‘gcloud’){ //This is where we build and push our Docker image. } } } })  在 Kubernetes 上运行 Jenkins master、 Jenkins 代理,构建和部署示例应用程序其实只花了我几个小时。但这之后,我花了一个周末的时间才深入了解了平台。如果你学得够快,我相信你在几天内就可以完全掌握并且灵活运用这个平台了。\n",
        "auhtor": "devmandy",
        "translator": "yuzp1996",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
1444 1445
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1446
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/11/2018-11-14-first-voice/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1447
        "title": "Jenkins 微信订阅号",
LinuxSuRen's avatar
LinuxSuRen 已提交
1448 1449
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1450
        "tags": [],
LinuxSuRen's avatar
LinuxSuRen 已提交
1451
        "description": "来自 Jenkins 官方的消息",
LinuxSuRen's avatar
LinuxSuRen 已提交
1452 1453 1454 1455 1456
        "content": "Jenkins 作为 CI/CD 领域里非常有实力和生命力的平台,不但在国外有很多用户,在国内也有很多的拥趸者。大家拥抱 Jenkins,不仅仅因为它是新的方向,更因为这背后有着一个非常开放、活跃的开源社区。\n为了使更多的 Jenkins 中文用户,能够及时、准确地获得来自官方的最新动态,经过社区贡献者的讨论,大家一致认为,开通 Jenkins 微信订阅号是非常必要也非常有意义的一件事情。同时,Jenkins 的创始人 Kohsuke Kawaguchi 先生对这个想法非常认同,他亲自签名并授权,对我们创建 Jenkins 微信订阅号提供了巨大的支持和鼓励。\n于是,Jenkins 微信订阅号便在今天,正式与您见面了。\n随着 Jenkins 订阅号的开通,我们将有更加直接的平台来与各位分享社区目前在做的一些事情。在这之前,我们早已着手进行 Jenkins 中文本地化的相关工作。目前社区贡献者主要在做的事情包括:创办并维护 Jenkins 以及 Jenkins X 的中文官网、Jenkins Core 以及插件的本地化等。\n如果您愿意和其他 Jenkins 用户进行线下面对面的交流和分享,Jenkins Area Meetups(后文简称“JAM”) 将会是一个不错的选择。目前,在社区贡献者和技术爱好者的共同努力下,我们已经在北京、深圳、西安等地成功举办过多次 JAM 活动。在 JAM 上,您除了可以体验到很多有关 Jenkins 的实际应用、最新特性之外,还可以结识社区里的朋友并进行深度互动。\nJenkins 社区贡献者们秉承传播 Jenkins 技术、加强互动交流、推动 Jenkins 中文本地化的理念,将在今后定期举办多种多样的线上线下活动。我们尊重任何形式、任何规模的贡献,并热忱地欢迎新贡献者的加⼊,也欢迎您联系我们来分享您的心得、体会,或者共同举办一次 JAM 活动。Jenkins 官网对如何参与有更加详细的说明,有任何问题,欢迎大家留言给我们。\n我们衷心希望,随着 Jenkins 订阅号的开通,能够与更多的小伙伴们一同在线上完善开源社区氛围、线下深度互动,努力构建一个有内容、有态度的优质技术社区。\n",
        "auhtor": "linuxsuren",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1457
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1458
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1459
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/12/2018-12-26-security-updates/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1460
        "title": "Jenkins 的重要安全更新",
LinuxSuRen's avatar
LinuxSuRen 已提交
1461 1462
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1463 1464
        "tags": ["core", "security"],
        "description": "重要安全更新",
LinuxSuRen's avatar
LinuxSuRen 已提交
1465 1466 1467 1468 1469
        "content": " 我们刚刚发布了版本 2.154 和 LTS 2.150.1 的 Jenkins 安全更新,修复了多个安全漏洞。 由于 2.150.1 是新的 LTS 中的第一个版本,而且,我们还发布了上一个 LTS 2.138.4 版本的安全更新。 这使得管理员们可以安装今天的安全修复,而不必立即升级到新的 LTS 版本。\n查看 link:/security/advisory/2018-12-05[安全报告],了解有哪些被修复。 查看我们的 link:/doc/upgrade-guide/2.138/#upgrading-to-jenkins-lts-2-138-4[LTS 2.138.4 升级指导],了解影响范围。\n当前修复中有关之前发布变更的部分 在八月和十月份的 Jenkins 核心安全更新中,包括一项改进,可以通过设置多个系统属性来禁用。 那些变更是 SECURITY-595 修复的重要部分,因此,我们强烈建议禁用。而且,之前发布的文档已更新。\n",
        "auhtor": "daniel-beck",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
1470 1471
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1472 1473 1474
        "uri": "https://jenkins-zh.cn/tags/jenkinsworld/",
        "title": "Jenkinsworld",
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1475
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1476 1477
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1478 1479 1480 1481 1482
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1483 1484
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1485 1486 1487
        "uri": "https://jenkins-zh.cn/tags/jenkinsworld2018/",
        "title": "Jenkinsworld2018",
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1488
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1489 1490
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1491 1492 1493 1494 1495
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1496
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1497
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
        "uri": "https://jenkins-zh.cn/tags/jira/",
        "title": "Jira",
        "type": "tags",
        "date": "2019-05-08 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1508
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1509 1510
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1511 1512
        "uri": "https://jenkins-zh.cn/tags/k8s/",
        "title": "K8s",
LinuxSuRen's avatar
LinuxSuRen 已提交
1513
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1514
        "date": "2019-05-24 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1515 1516
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1517 1518 1519 1520 1521
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1522 1523
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1524 1525
        "uri": "https://jenkins-zh.cn/tags/kubecon/",
        "title": "Kubecon",
LinuxSuRen's avatar
LinuxSuRen 已提交
1526
        "type": "tags",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1527
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1528 1529
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1530 1531 1532 1533 1534
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1535
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1536
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1537 1538
        "uri": "https://jenkins-zh.cn/tags/kubernetes/",
        "title": "Kubernetes",
LinuxSuRen's avatar
LinuxSuRen 已提交
1539
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1540
        "date": "2019-05-24 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1541 1542 1543 1544 1545 1546 1547 1548
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1549
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1550 1551
        "uri": "https://jenkins-zh.cn/tags/maven/",
        "title": "Maven",
LinuxSuRen's avatar
LinuxSuRen 已提交
1552
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1553
        "date": "2019-05-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1554 1555
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1556 1557 1558 1559 1560
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1561
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1562
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1563 1564
        "uri": "https://jenkins-zh.cn/tags/newcomer/",
        "title": "Newcomer",
LinuxSuRen's avatar
LinuxSuRen 已提交
1565
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1566
        "date": "2019-04-08 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1567 1568
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1569 1570 1571 1572 1573
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
1574
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1575
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1576 1577
        "uri": "https://jenkins-zh.cn/tags/nginx/",
        "title": "Nginx",
LinuxSuRen's avatar
LinuxSuRen 已提交
1578
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1579
        "date": "2019-04-25 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1580 1581
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1582 1583 1584 1585 1586
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1587
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1588
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1589 1590
        "uri": "https://jenkins-zh.cn/tags/opensource/",
        "title": "Opensource",
LinuxSuRen's avatar
LinuxSuRen 已提交
1591
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1592
        "date": "2019-03-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1593 1594
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1595 1596 1597 1598 1599
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1600
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1601
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1602 1603
        "uri": "https://jenkins-zh.cn/tags/outreachy/",
        "title": "Outreachy",
LinuxSuRen's avatar
LinuxSuRen 已提交
1604
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
        "date": "2019-02-13 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/outreachy2018/",
        "title": "Outreachy2018",
        "type": "tags",
        "date": "2019-02-13 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1619 1620
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1621 1622 1623 1624 1625
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
1626
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1627
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1628
        "uri": "https://jenkins-zh.cn/tags/performance/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1629
        "title": "Performance",
LinuxSuRen's avatar
LinuxSuRen 已提交
1630 1631
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1632 1633
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1634 1635 1636 1637 1638
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1639
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665
    {
        "uri": "https://jenkins-zh.cn/tags/pipeline/",
        "title": "Pipeline",
        "type": "tags",
        "date": "2019-04-30 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/platform-sig/",
        "title": "Platform Sig",
        "type": "tags",
        "date": "2019-02-20 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1666
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1667
        "uri": "https://jenkins-zh.cn/tags/plugins/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1668
        "title": "Plugins",
LinuxSuRen's avatar
LinuxSuRen 已提交
1669 1670
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1671
        "tags": [],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1672
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1673 1674 1675 1676 1677
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1678
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
    {
        "uri": "https://jenkins-zh.cn/tags/progressive-delivery/",
        "title": "Progressive Delivery",
        "type": "tags",
        "date": "2019-04-26 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/release/",
        "title": "Release",
        "type": "tags",
        "date": "2019-05-15 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1705
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1706
        "uri": "https://jenkins-zh.cn/tags/remoting/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1707
        "title": "Remoting",
LinuxSuRen's avatar
LinuxSuRen 已提交
1708 1709
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1710 1711
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1712 1713 1714 1715 1716
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1717
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1718
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1719
        "uri": "https://jenkins-zh.cn/tags/scalability/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
        "title": "Scalability",
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/security/",
        "title": "Security",
        "type": "tags",
        "date": "2019-04-28 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/shared-library/",
        "title": "Shared Library",
        "type": "tags",
        "date": "2019-03-06 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/shipper/",
        "title": "Shipper",
LinuxSuRen's avatar
LinuxSuRen 已提交
1760
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1761 1762 1763 1764 1765 1766 1767 1768 1769
        "date": "2019-04-26 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782
    {
        "uri": "https://jenkins-zh.cn/tags/spec/",
        "title": "Spec",
        "type": "tags",
        "date": "2019-05-20 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1783 1784 1785 1786
    {
        "uri": "https://jenkins-zh.cn/sponsor/",
        "title": "Sponsors",
        "type": "sponsor",
LinuxSuRen's avatar
LinuxSuRen 已提交
1787
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1788 1789
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1790 1791 1792 1793 1794
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1795
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808
    {
        "uri": "https://jenkins-zh.cn/tags/spring-boot/",
        "title": "Spring Boot",
        "type": "tags",
        "date": "2019-05-24 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
    {
        "uri": "https://jenkins-zh.cn/tags/springboot/",
        "title": "Springboot",
        "type": "tags",
        "date": "2019-05-20 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1822
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1823
        "uri": "https://jenkins-zh.cn/tags/survey/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1824
        "title": "Survey",
LinuxSuRen's avatar
LinuxSuRen 已提交
1825 1826
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1827 1828
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1829 1830 1831 1832 1833
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1834
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847
    {
        "uri": "https://jenkins-zh.cn/tags/",
        "title": "Tags",
        "type": "tags",
        "date": "2019-04-22 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1848
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1849
        "uri": "https://jenkins-zh.cn/tags/tools/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1850
        "title": "Tools",
LinuxSuRen's avatar
LinuxSuRen 已提交
1851 1852
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1853 1854
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1855 1856 1857 1858 1859
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1860
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1861
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1862
        "uri": "https://jenkins-zh.cn/tags/webhooks/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877
        "title": "Webhooks",
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/wechat/",
        "title": "Wechats",
        "type": "wechat",
LinuxSuRen's avatar
LinuxSuRen 已提交
1878
        "date": "2019-05-28 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/weekly/",
        "title": "Weekly",
LinuxSuRen's avatar
LinuxSuRen 已提交
1890
        "type": "tags",
LinuxSuRen's avatar
LinuxSuRen 已提交
1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903
        "date": "2019-03-20 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/weibo/",
        "title": "Weibos",
        "type": "weibo",
LinuxSuRen's avatar
LinuxSuRen 已提交
1904
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1905 1906
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1907 1908 1909 1910 1911
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
1912 1913
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1914
        "uri": "https://jenkins-zh.cn/tags/windows/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1915
        "title": "Windows",
LinuxSuRen's avatar
LinuxSuRen 已提交
1916 1917
        "type": "tags",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1918 1919
        "tags": [],
        "description": "",
LinuxSuRen's avatar
LinuxSuRen 已提交
1920 1921 1922 1923 1924
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1925
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951
    {
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/02/2019-02-27-windows-installers/",
        "title": "Windows 安装程序更新",
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
        "tags": ["windows", "platform-sig", "installers"],
        "description": "平台特别兴趣小组提供了 Windows 安装程序的更新",
        "content": " Jenkins 的 Windows 安装程序已经存在很多年了,它是用户在 Windows 上安装 Jenkins Master 作为服务的一种方式。 从被开发出来至今,它还没有什么新特性,但现在是时候做出改变了。\n首先,让我们瞧瞧现版本安装程序的使用经验。\n第1步 启动安装程序 这是使用 WiX Toolset Windows 安装程序的默认界面外观,算不上太好看,而且没有太多对安装程序进行说明的品牌信息。\n第2步 安装目录 同样,没有太多的品牌信息。\n第3步 安装 除了选择安装位置外,安装程序大体上没有提供一些安装 Jenkins 的选项。\n问题 现在的安装程序存在一些问题,平台特别兴趣小组会修复这些问题,并为用户提供新的安装体验。\n 安装程序只支持32位安装。 用户不能选择 Jenkins 作为 Windows 服务启动时的端口以及账户。 安装程序捆绑了32位的 Java Runtime,而没有使用已存在的 JRE。 安装程序不支持 Jenkins for Java 11中的实验性支持。 JENKINS_HOME 目录并不适合现代 Windows。 安装程序中没有品牌。  前进 使用实验性的 Jenkins Windows 安装程序,大部分问题都已解决!\n 安装程序将只支持64位系统,这也是如今大多数 Windows 系统的现状,所以能让更多的用户能够使用安装包来安装 Jenkins。 用户能够为服务输入用户信息,同时选择端口以便于 Jenkins 验证端口是否可用。 安装程序不再捆绑 JRE 而是在操作系统中寻找合适的 JRE。如果用户想要使用一个不同的 JRE,可以在安装时指定。 安装程序已经支持 Java 11,包括在 Java 11 预览上面列出的组件。 JENKINS_HOME 目录被放置在启动服务用户的 LocalAppData 目录下,这与现代 Windows 文件系统布局一致。 安装程序已经升级带有品牌了,这让它看起来更酷并能提供一个更好的用户体验。  截图 以下是新安装程序的系列屏幕截图:\n第1步 启动安装程序 Jenkins logo 现在是安装程序 UI 的重要组成部分。\n第2步 安装目录 在安装程序的所有阶段,Jenkins logo 和名称都出现在标题中。\n第3步 选择账户 安装程序现在允许您指定要运行的帐户的用户名/密码,并检查该帐户是否具有 LogonAsService 权限。\n第4步 端口选择 安装程序还允许您指定 Jenkins 运行的端口,并且在输入和测试有效端口之前不会继续。\n第5步 JRE 选择 安装程序现在不再捆绑 JRE,而是在系统上搜索兼容的 JRE (现在是 JRE 8)。 如果你想使用与安装程序搜索到不同的 JRE,你可以浏览目录并指定它。只支持 JRE 8 和 JRE 11 Runtime。如果发现选定的 JRE 是版本11,安装程序将自动添加必要的参数和其他 jar 文件,以便在 Java 11下运行。\n第6步 安装 用户能在安装程序中输入的所有选项也可以在命令行上覆盖以进行自动部署。可以覆盖的完整属性列表即将推出。\n接下来的步骤 新版本安装程序正在被平台特别兴趣小组的成员 Review 中,但我们需要人测试安装程序并给予反馈。你过你对测试新安装程序感兴趣的话,请加入平台特别兴趣小组 gitter room 获取更多信息。\n在新安装程序中还使用了许多一些正在研发的东西(例如,在进行升级时保留端口和其他选择),但它已接近发布。\n除了基于 MSI 的 Windows 安装程序的更新之外,平台特别兴趣小组还在努力接管 Chocolatey Jenkins 软件包并为每次更新发布一个版本。\n",
        "auhtor": "slide_o_mix",
        "translator": "arjenzhou",
        "original": "https://jenkins.io/blog/2019/02/01/windows-installers/",
        "poster": ""
    },
    {
        "uri": "https://jenkins-zh.cn/tags/zabbix/",
        "title": "Zabbix",
        "type": "tags",
        "date": "2019-04-15 00:00:00 +0000 UTC",
        "tags": [],
        "description": "",
        "content": "",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1952
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1953
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-12-what-is-cicd/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1954
        "title": "什么是 CI/CD?",
LinuxSuRen's avatar
LinuxSuRen 已提交
1955 1956
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1957
        "tags": ["ci", "cd"],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1958
        "description": "本文介绍了 CI/CD 的概念及应用场景",
LinuxSuRen's avatar
LinuxSuRen 已提交
1959 1960 1961 1962 1963
        "content": " CI/CD 的出现改变了开发人员和测试人员发布软件的方式。本文是描述这一变化的系列文章第一篇, 这些文章将提供各种工具和流程的讲解,以帮助开发人员更好的使用 CI/CD。\n从最初的 瀑布模型, 到后来的 敏捷开发, 再到今天的 DevOps, 这是现代开发人员构建出色产品的技术路线。 随着 DevOps 的兴起,出现了持续集成,持续交付(CI/CD)和持续部署的新方法, 而传统的软件开发和交付方式在迅速变得过时。过去的敏捷时代里, 大多数公司的软件发布周期是每月、每季度甚至每年(还记得那些日子吗?), 而在现在 DevOps 时代,每周、每天甚至每天多次都是常态。 当 SaaS 成为业界主流后尤其如此,您可以轻松地动态更新应用程序, 而无需强迫用户下载更新组件。很多时候,用户甚至都不会注意到正在发生变化。\n开发团队通过软件交付流水线(Pipeline)实现自动化,以缩短交付周期, 大多数团队都有自动化流程来检查代码并部署到新环境。 我们一直在关注自动化测试流程,但这将在之后的文章中介绍。 今天,我们将介绍什么是 CI/CD/CD ,以及现代软件公司如何使用工具将部署代码的流程自动化。\n持续集成注重将各个开发者的工作集合到一个代码仓库中,通常每天会进行几次, 主要目的是尽早发现集成错误,使团队更加紧密结合,更好地协作。 持续交付的目的是最小化部署或发布过程中团队固有的摩擦, 它的实现通常能够将构建部署的每个步骤自动化,以便任何时刻能够安全地完成代码发布(理想情况下)。 持续部署是一种更高程度的自动化,无论何时代码有较大改动, 都会自动进行构建/部署。\n以上的每一个阶段都是交付流水线的一部分。 Humble 和 Ferley 在他们的书作《持续交付:通过自动化构建、测试和部署实现可靠软件版本发布》中解释说: 「对软件的每次更改都要经过一个复杂的过程才能发布,该过程包括多个测试和部署阶段进行软件的构建。 反过来看,这个过程需要许多人之间的合作,甚至可能需要几个团队间合作。 部署流水线对这一过程进行建模,并且它的持续集成和发布管理工具能让您在代码从版本控制转移到各种测试和部署时, 查看和控制每次更改的过程。」\n持续集成(CI) 通过持续集成,开发人员能够频繁地将其代码集成到公共代码仓库的主分支中。 开发人员能够在任何时候多次向仓库提交作品,而不是独立地开发每个功能模块并在开发周期结束时一一提交。\n这里的一个重要思想就是让开发人员更快更、频繁地做到这一点,从而降低集成的开销。 实际情况中,开发人员在集成时经常会发现新代码和已有代码存在冲突。 如果集成较早并更加频繁,那么冲突将更容易解决且执行成本更低。\n当然,这里也有一些权衡,这个流程不提供额外的质量保障。 事实上,许多组织发现这样的集成方式开销更大,因为它们依赖人工确保新代码不会引起新的 bug 或者破坏现有代码。 为了减少集成期间的摩擦,持续集成依赖于测试套件和自动化测试。 然而,要认识到自动化测试和持续测试是完全不同的这一点很重要,我们会在文章结尾处详细说明。\nCI 的目标是将集成简化成一个简单、易于重复的日常开发任务, 这样有助于降低总体的构建成本并在开发周期的早期发现缺陷。 要想有效地使用 CI 必须转变开发团队的习惯,要鼓励频繁迭代构建, 并且在发现 bug 的早期积极解决。\n持续交付(CD)实际上是 CI 的扩展,其中软件交付流程进一步自动化,以便随时轻松地部署到生成环境中。 成熟的持续交付方案也展示了一个始终可部署的代码库。使用 CD 后,软件发布将成为一个没有任何紧张感的例行事件。 开发团队可以在日常开发的任何时间进行产品级的发布,而不需要详细的发布方案或者特殊的后期测试。\nCD 集中依赖于部署流水线,团队通过流水线自动化测试和部署过程。此流水线是一个自动化系统, 可以针对构建执行一组渐进的测试套件。CD 具有高度的自动化,并且在一些云计算环境中也易于配置。\n在流水线的每个阶段,如果构建无法通过关键测试会向团队发出警报。否则,将继续进入下一个测试, 并在连续通过测试后自动进入下一个阶段。流水线的最后一个部分会将构建部署到和生产环境等效的环境中。 这是一个整体的过程,因为构建、部署和环境都是一起执行和测试的,它能让构建在实际的生产环境可部署和可验证。\nAWS 上提供了可靠的当前 CI/CD 的展示,亚马逊是云计算的提供商之一,提供出色的 CI/CD 流水线环境和实验过程, 有众多开发资源可供选择,您可以将它们在一个易于配置和监控的流水线中组合起来。\n许多人认为持续交付的吸引力主要在于,它自动化了从提交代码到仓库,再到测试和发布产品过程的所有步骤。 这是构建和测试过程细致的自动化,但是如何发布以及发布什么仍然是需要人工操作,持续部署可以改变这一点。\n持续部署(CD) 持续部署扩展了持续交付,以便软件构建在通过所有测试时自动部署。在这样的流程中, 不需要人为决定何时及如何投入生产环境。CI/CD 系统的最后一步将在构建后的组件/包退出流水线时自动部署。 此类自动部署可以配置为快速向客户分发组件、功能模块或修复补丁,并准确说明当前提供的内容。\n采用持续部署的组织可以将新功能快速传递给用户,得到用户对于新版本的快速反馈,并且可以迅速处理任何明显的缺陷。 用户对无用或者误解需求的功能的快速反馈有助于团队规划投入,避免将精力集中于不容易产生回报的地方。\n随着 DevOps 的发展,新的用来实现 CI/CD 流水线的自动化工具也在不断涌现。这些工具通常能与各种开发工具配合, 包括像 GitHub 这样的代码仓库和 Jira 这样的 bug 跟踪工具。此外,随着 SaaS 这种交付方式变得更受欢迎, 许多工具都可以在现代开发人员运行应用程序的云环境中运行,例如 GCP 和 AWS。\n最受欢迎的自动化工具是 Jenkins(以前的 Hudson), 这是一个由数百名贡献者和商业公司 Cloudbees 支持的开源项目。 Cloudbees 甚至聘请了 Jenkins 的创始人,并提供了一些 Jenkins 培训项目和附加组件。 除了开源项目之外,还有一些更现代化的商业产品例如 CircleCI,Codeship 和 Shippable。 这些产品各有优缺点,我鼓励开发人员在开发流程中一一尝试它们,以了解它们在您的环境中的工作方式, 以及它们如何与您的工具、云平台、容器系统等协作。\n在 mabl 中,我们在 Google Cloud Platform 上进行构建, 因此,我们正在寻找与 GSP 兼容或者最好是已经集成进 GSO 的产品。我们尝试过 CircleCI,Codeship 和 Shippable, 下面有一个简单的表格,展示了每个工具的一些细节:\n我们最终选择了 Codeship,我认为我们的选择是正确的, 也感谢 Codeship 团队的支持。\n接下来? 一旦部署了现代化的 CI/CD 流水线,您可能会意识到开发人员工作流程中的一些工具和流程也需要进行现代化改造。 测试是一个要着重关注的领域,如果您的部署频率是每天或者一天多次,您的每次测试可能需要数小时甚至一晚上才能完成。 mabl 正在使用机器学习解决这个问题。\n",
        "auhtor": "Izzyazeri",
        "translator": "p01son6415",
        "original": "https://dzone.com/articles/what-is-cicd",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1964
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1965
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1966
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/12/2018-12-19-scaling-network-connections/",
LinuxSuRen's avatar
LinuxSuRen 已提交
1967
        "title": "从 Jenkins Master 扩展网络连接",
LinuxSuRen's avatar
LinuxSuRen 已提交
1968 1969
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
1970 1971
        "tags": ["jenkinsworld", "jenkinsworld2018", "cloud-native", "performance", "scalability", "remoting"],
        "description": "从 Jenkins Master 扩展网络连接",
LinuxSuRen's avatar
LinuxSuRen 已提交
1972 1973 1974 1975 1976
        "content": "Oleg Nenashev 和我今年将在旧金山的 DevOps World | Jenkins World 上,做从 Jenkins Master 扩展网络连接 的演讲。 多年来,我们一直致力于分析、优化和加强 Remoting channel, 才有了现如今 master 能够协调 agent 的活动,并且接收构建的结果。 尽管许多技术可以改进服务,比如优化代理启动器,但是想要有质的改变,只有从根本上改变传播的内容和方式。\n3月,JENKINS-27035 引入了一个框架,用于检查 Remoting channel 在高级别上的通信。 以前,开发人员只能使用一般的低级工具,例如 Wireshark, 它不能精确的识别 Jenkins 负责通信的代码片段。\n在过去的几个月里,Cloud Native SIG 在解决根本原因方面取得了进展。 Artifact Manager on S3 plugin 已经发布并与 Jenkins Evergreen 整合, 支持在 agent 和 Amazon 服务器之间,进行大制品的上传和下载, 源生插件允许由 agent 生成的所有构建的日志内容(例如在 steps 的 sh 中) 直接定向流到外部存储服务,如 AWS CloudWatch Logs。 与此同时也开始上传 junit 格式的测试结果,这些测试结果有时会变的很大,将直接从 agent 到存储数据库。 所有这些努力都可以减轻 Jenkins Master 和本地网络的负载,而不需要开发人员修改他们的 pipeline 脚本。\n其他方法也在酝酿之中。 虽然“一次性”的 agent 在新的 vm 或容器中运行,可以极大地提高可重复性, 但是每一次构建都需要传输兆字节的 Java 代码,所以 Jenkins 的特征是需要对它们建立预缓存。 使用 Apache Kafka 的工作正在进行中,以使得通道在网络故障时更加健壮。 最引人注目的是,这个提议 Cloud Native Jenkins MVP 将消除单个 Jenkins Master 服务处理数百个构建的瓶颈。\n",
        "auhtor": "jglick",
        "translator": "sailingwithoutwind",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
1977
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
1978
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1979
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-23-configuring-jenkins-pipeline-with-yaml-file/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1980
        "title": "使用 YAML 文件配置 Jenkins 流水线",
LinuxSuRen's avatar
LinuxSuRen 已提交
1981 1982
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1983 1984
        "tags": ["pipeline"],
        "description": "这也是一种自定义流水线 DSL 的方法",
LinuxSuRen's avatar
LinuxSuRen 已提交
1985 1986 1987 1988 1989
        "content": " 几年前,我们的 CTO 写了一篇关于 使用 Jenkins 和 Docker 为 Ruby On Rails 应用提供持续集成服务 的文章。这些年,我们一直使用这个 CI 流水线解决方案,直到我们最近决定做一次升级。为什么呢?\n Jenkins 的版本过低,已经很难升级 Wolox 过去几年增长显著,一直面临着如何伸缩的问题 只有极少数人如何修复 Jenkins 服务的问题 配置 Jenkins 任务不是一件简单的任务,使我们的项目启动过程变慢 更改每个作业运行的命令也不是一件简单的任务,并且有权限更改的人并不多。 Wolox 拥有广泛的项目,语言种类繁多,使得这个问题尤为突显。  考虑到这些问题,我们开始深入研究最新版的 Jenkins,看看如何提升我们的 CI 服务。我们需要构建一个新的CI服务,至少要解决以下问题:\n 支持 Docker 构建。我们的项目依赖的一个或多个 Docker 镜像的执行(应用,数据库,Redis 等) 如有必要,易于配置和复制 易于增加新项目 易于修改构建步骤。工作在项目上的所有人都应该能修改它,如果他们希望执行 npm install 或 yarn install  安装Jenkins和Docker 安装 Jenkins 非常简单,直接从 官方教程 选择一种方式安装。\n以下是我们在 AWS 上的安装步骤:\nsudo rpm — import https://pkg.jenkins.io/debian/jenkins.io.key sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins.io/redhat/jenkins.repo sudo yum install java-1.8.0 -y sudo yum remove java-1.7.0-openjdk -y sudo yum install jenkins -y sudo yum update -y sudo yum install -y docker  从 GitHub 上自动添加项目 从 Github 上自动添加项目可以通过 GitHub Branch Source 插件实现。它能将 GitHub 的组织中符合规则的项目自动添加到 Jenkins 中。唯一的约束就是在每一个分支下都必须有一个 Jenkinsfile,用于描述如何构建项目。\n易于修改的配置 我们之前使用 Jenkins 最痛苦的是修改项目的构建步骤。在 Jenkins 任务中,你会看到像以下代码(用于构建):\n#!/bin/bash +x set -e # Remove unnecessary files echo -e \u0026quot;\\033[34mRemoving unnecessary files...\\033[0m\u0026quot; rm -f log/*.log \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null rm -rf public/uploads/* \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null # Build Project echo -e \u0026quot;\\033[34mBuilding Project...\\033[0m\u0026quot; docker-compose --project-name=${JOB_NAME} build # Prepare test database COMMAND=\u0026quot;bundle exec rake db:drop db:create db:migrate\u0026quot; echo -e \u0026quot;\\033[34mRunning: $COMMAND\\033[0m\u0026quot; docker-compose --project-name=${JOB_NAME} run \\ -e RAILS_ENV=test web $COMMAND # Run tests COMMAND=\u0026quot;bundle exec rspec spec\u0026quot; echo -e \u0026quot;\\033[34mRunning: $COMMAND\\033[0m\u0026quot; unbuffer docker-compose --project-name=${JOB_NAME} run web $COMMAND # Run rubocop lint COMMAND=\u0026quot;bundle exec rubocop app spec -R --format simple\u0026quot; echo -e \u0026quot;\\033[34mRunning: $COMMAND\\033[0m\u0026quot; unbuffer docker-compose --project-name=${JOB_NAME} run -e RUBYOPT=\u0026quot;-Ku\u0026quot; web $COMMAND  在构建步骤后,执行 Docker 构建的清理工作:\n#!/bin/bash +x docker-compose --project-name=${JOB_NAME} stop \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null docker-compose --project-name=${JOB_NAME} rm --force \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null docker stop `docker ps -a -q -f status=exited` \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null docker rm -v `docker ps -a -q -f status=exited` \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null docker rmi `docker images --filter 'dangling=true' -q --no-trunc` \u0026amp;\u0026gt; /dev/null || true \u0026amp;\u0026gt; /dev/null  尽管这些命令并不复杂,但是更改其中的任何命令都需要具有权限的人员来操作相应的 Jenkins 任务,并清楚知道自己需要做什么。\nJenkinsfile的成与败 使用当前的 Jenkins 版本,我们可以利用 Jenkins pipeline 对我们的构建流进行建模,并保存到一个文件中。 该文件会被签入代码库。因此,任何有权访问它的人都可以修改其中的步骤。棒极了。\nJenkins 流水线还支持:\n Docker 及多个镜像可用于构建 使用 withEnv 设置环境变量,还支持很多其它内建的 函数  这为 Wolox 提供了完美的用例。我们可以将构建配置写入到一个被检入到代码库的文件中,并且允许任务有权限访问的人修改。但是,一个简单的 Rails 项目的 Jenkinsfile 看起来却像这样:\n# sample Jenkinsfile. Might not compile node { checkout scm withEnv(['MYTOOL_HOME=/usr/local/mytool']) { docker.image(\u0026quot;postgres:9.2\u0026quot;).withRun() { db -\u0026gt; withEnv(['DB_USERNAME=postgres', 'DB_PASSWORD=', \u0026quot;DB_HOST=db\u0026quot;, \u0026quot;DB_PORT=5432\u0026quot;]) { docker.image(\u0026quot;redis:X\u0026quot;).withRun() { redis -\u0026gt; withEnv([\u0026quot;REDIS_URL=redis://redis\u0026quot;]) { docker.build(imageName, \u0026quot;--file .woloxci/Dockerfile .\u0026quot;).inside(\u0026quot;--link ${db.id}:postgres --link ${redis.id}:redis\u0026quot;) { sh \u0026quot;rake db:create\u0026quot; sh \u0026quot;rake db:migrate\u0026quot; sh \u0026quot;bundle exec rspec spec\u0026quot; } } } } } } }  这样的文件不仅难以理解,还难以修改。这样的构建逻辑非常容易被破坏,如果你不熟悉 Groovy。如果你对 Jenkins 流水线是如何工作的一无所知,就更容易了。这样,修改或增加一个新的 Docker 镜像就变得不简单,也容易导致混淆。\n通过 YAML 配置 Jenkins 流水线 就个人而言,我总是期望为 CI 配置简单的配置文件。这次我们有机会构建使用 YAML 文件配置的 CI。经过分析,我们总结出以下这样的 YAML,它已经能满足我们的需求:\nconfig: dockerfile: .woloxci/Dockerfile project_name: some-project-name services: - postgresql - redis steps: analysis: - bundle exec rubocop -R app spec --format simple - bundle exec rubycritic --path ./analysis --minimum-score 80 --no-browser setup_db: - bundle exec rails db:create - bundle exec rails db:schema:load test: - bundle exec rspec security: - bundle exec brakeman --exit-on-error audit: - bundle audit check --update environment: RAILS_ENV: test GIT_COMMITTER_NAME: a GIT_COMMITTER_EMAIL: b LANG: C.UTF-8  它描述了项目基本的配置、构建过程中需要的环境变量、依赖的服务、还有构建步骤。\nJenkinsfile + Shared Libraries = WoloxCI 经过调研 Jenkins 和流水线之后,我们发现可以通过扩展共享库(shared libraries)来实现。共享库是用 Groovy 编写的,可以导入到流水线中,并在必要时执行。\n如果你细心观察以下 Jenkinsfile,你会看到代码是一个接收闭包的方法调用链,我们执行另一个方法将一个新的闭包传递给它。\n# sample Jenkinsfile. Might not compile node { checkout scm withEnv(['MYTOOL_HOME=/usr/local/mytool']) { docker.image(\u0026quot;postgres:9.2\u0026quot;).withRun() { db -\u0026gt; withEnv(['DB_USERNAME=postgres', 'DB_PASSWORD=', \u0026quot;DB_HOST=db\u0026quot;, \u0026quot;DB_PORT=5432\u0026quot;]) { docker.image(\u0026quot;redis:X\u0026quot;).withRun() { redis -\u0026gt; withEnv([\u0026quot;REDIS_URL=redis://redis\u0026quot;]) { docker.build(imageName, \u0026quot;--file .woloxci/Dockerfile .\u0026quot;).inside(\u0026quot;--link ${db.id}:postgres --link ${redis.id}:redis\u0026quot;) { sh \u0026quot;rake db:create\u0026quot; sh \u0026quot;rake db:migrate\u0026quot; sh \u0026quot;bundle exec rspec spec\u0026quot; } } } } } } }  Groovy 语言足够灵活,能在在运行时创建声明式代码,这使我们能使用 YAML 来配置我们的流水线!\nWolox-CI介绍 wolox-ci 诞生于 Jenkins 的共享库。以下是关于 Wolox-CI 的具体使用方式。\n使用 wolox-ci,Jenkinsfile 被精简成:\n@Library('wolox-ci') _ node { checkout scm woloxCi('.woloxci/config.yml'); }  它会检出代码,然后调用 wolox-ci。共享库代码会读取到 YAML 文件,如下:\nconfig: dockerfile: .woloxci/Dockerfile project_name: some-project-name services: - postgresql - redis steps: analysis: - bundle exec rubocop -R app spec –format simple - bundle exec rubycritic –path ./analysis –minimum-score 80 –no-browser setup_db: - bundle exec rails db:create - bundle exec rails db:schema:load test: - bundle exec rspec security: - bundle exec brakeman –exit-on-error audit: - bundle audit check –update environment: RAILS_ENV: test GIT_COMMITTER_NAME: a GIT_COMMITTER_EMAIL: b LANG: C.UTF-8  然后,Jenkins 就会执行你的构建任务。\n共享库有一个好处是我们可以集中扩展和修改我们的共享库代码。一旦添加新代码,Jenkins 就会自动更新它,还会通知所有的任务。\n由于我们有不同语言的项目,我们使用 Docker 来构建测试环境。WoloxCI 假设有一个 Dockerfile 要构建,并将在容器内运行所有指定的命令。\nconfig.yml 各部分介绍 config部分 这是 config.yml 的第一部分,用于指定基本配置,包括项目的名称,Dockerfile 的路径。Dockerfile 用于构建镜像,所有的命令都运行在该镜像的容器中。\nServices 部分 这部分定义了哪些服务被暴露到容器中。WoloxCI 支持以下开箱即用的服务:postgresql、mssql 和 redis。你还可以指定 Docker 镜像的版本。\n增加一个新的服务类型也不难。你只需要在该目录下(https://github.com/Wolox/wolox-ci/tree/development/vars)添加,然后告诉共享库该服务是如何被转换的,如https://github.com/Wolox/wolox-ci/blob/development/src/com/wolox/parser/ConfigParser.groovy#L76\nSteps 部分 在此部分列出的命令,都会被运行在 Docker 容器中。你可以在 Jenkins 界面上看到每一步的执行结果。\nEnvironment 部分 如果构建过程需要一些环境变量,你可以在这部分指定它们。Steps 部分中描述的步骤执行过程中,Docker 容器会提供你设置好的所有环境变量。\n总结 目前,WoloxCI 还在我们所有项目中一小部分项目进行测试。这让有权限访问它的人通过 YAML 文件更改构建步骤。这是对我们 CI 工作流程来说是一个重大改进。\nDocker 使我们轻松更换编程语言,而不用对 Jenkins 安装做任何的更改。并且,当检查到 GitHub 组织中的新项目(项目中有 Jenkinsfile)时,Jenkins GitHub Branch Source 插件会自动添加新的 Jenkins 项目。\n所有这些改进节约了我们维护 Jenkins 的大量时间,并使我们可以轻松扩展而无需任何额外配置。\n译者小结 本文最大的亮点是它介绍了一种实现自定义构建语言的方式。通过 Jenkins 的共享库技术,将构建逻辑从 Jenkinsfile 中移到了 YAML 文件中。同样的,我们可以将构建逻辑移动 JSON 文件中,或者任何格式的文件中,只你的共享库能解析它,并将它转换成 Jenkins 能理解的格式。\n",
        "auhtor": "Matias De Santi",
        "translator": "zacker330",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1990
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1991
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
1992
        "uri": "https://jenkins-zh.cn/about/about-site/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1993
        "title": "关于本站",
LinuxSuRen's avatar
LinuxSuRen 已提交
1994 1995
        "type": "about",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
1996 1997
        "tags": [],
        "description": "本站的架构",
LinuxSuRen's avatar
LinuxSuRen 已提交
1998 1999 2000 2001 2002
        "content": "Jenkins 中文社区站点是基于 Hugo 生成的静态文件,托管在 GitHub Page 上。下面列出相关的源码位置:\n 网站内容 网站主题 微信订阅号  ",
        "auhtor": "",
        "translator": "",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2003
    },
LinuxSuRen's avatar
LinuxSuRen 已提交
2004
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
2005
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/12/2018-12-25-year-in-review/",
LinuxSuRen's avatar
LinuxSuRen 已提交
2006
        "title": "回顾 2018: 革新的一年",
LinuxSuRen's avatar
LinuxSuRen 已提交
2007 2008
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2009 2010
        "tags": ["core", "community"],
        "description": "Jenkins 创始人 KK 先生的年终总结",
LinuxSuRen's avatar
LinuxSuRen 已提交
2011 2012
        "content": "临近年终,是一个思考总结、展望全局的好时机。那就让我们暂时从日常繁复的工作中停下脚步,一起来盘点 Jenkins 在 2018 这一年的得失与喜乐。\n在整个行业中,对进一步自动化的不懈追求仍在继续。我们正以前所未有的速度编写软件,与此同时,对于软件的需求似乎越来越高,我觉得越来越多的企业和高管都敏锐地意识到软件和开发者已登基为王。在底层的角度,我遇到的每个团队都认为软件交付自动化是他们的“软件工厂”的关键部分,对这些团队而言,创建、管理具有不可思议的灵活性和可视性的自动化十分重要。\n自诞生14年以来,Jenkins 将继续在实现这一目标上发挥重要作用,总之,增长的步伐似乎正在加速。在这个发展飞快的行业里,成为这一成就的一份子着实让我感到自豪。\n把 Jenkins 打造为每个人都会使用的工具,这具有很大的责任感。所以在 Jenkins 社区,我们一直都十分努力。事实上,在各个领域和层面上来说,*2018年是整个项目历史上最具有创新性的一年*。\n 随着不断发展壮大,我们亟需探索出能使更多人更好地参与其中的方法。JEPs 和 SIGs 便应运而生。2018年,我们看到了这些形式得到了巨大的吸引力。经过一年的运营,我认为我们已经学到了很多东西,希望我们会在此基础上继续改进。 这些新的形式带来了新的协作方式。例如:中文本地化 SIG运营的 微信公众号和本地化网站。平台 SIG 在 Java 11 support 中也给予了不少帮助。 我也很高兴看到新一批领导者。由于害怕遗漏一些人,所以我不打算在此一一列出,我们在今年秋天祝贺他们中的许多人作为 Jenkins 大使(请在明年提名更多人!)。那些领导关键工作的人往往是那些不熟悉这些角色的人。 一些领导者也努力发掘新的贡献者。我们正在有意识地思考,我们哪一部分的潜在贡献者没有被发掘出来,为什么没有被发掘出来。这也是任一个企业都在做的事情。同时我们也是 Google Summer of Code 和 Outreachy 参与者。 今年我们的安全流程和修复速度再次大幅提升,反映出用户对我们的信任也随之增强。例如,我们今年推出了遥测系统,通知我们更快地开发出更好的修复方案。  现在,社区改进的最重要的地方是我们为您使用的软件带来的影响。在这一方面,我认为我们在2018年做得不错,产生了我所谓的“五个超级武器”\n Jenkins X 可能是今年最明显的创新,使得在 Kubernetes 上创建现代云应用程序变得更加容易。这也标志着 Jenkins 社区及其使命的重大扩展。 Jenkins Configuration as Code 在今年达到了一重要的里程碑 \u0026ldquo;1.0\u0026rdquo; ,并且他继续获得更大的动力。 \u0026ldquo;Cloud Native Jenkins\u0026rdquo; 是我为新努力作的术语,把 Jenkins 转换为 Kubernetes 上大规模运行的通用 CI/CD 引擎。这里还有许多东西需要定义,但你已经可以看到如 Serverless Jenkins 这样的好东西了。 Evergreen 是另一个需要推出的新项目,它有着雄心勃勃的主题——大量地简化了 Jenkins 的使用和操作。 流水线方面的努力形成了一个新的 SIG,我期待它在2019年带来的新影响。  Jenkins 社区能够将用户可见的改变与社区的改进结合在一起,这不仅是不算秘密的秘密,也是社区不断发展的能力。 展望2019年,毫无疑问,随着我们不断地学习和实践,上述提到的事情将不断地发展、变化、融合和分裂。\n所以,请在 Twitter 上关注 @jenkinsci 和 @jenkinsxio,了解我们将如何发展的最新动态,加入我们的社区来共同构建震撼世界的软件。多少开源项目敢说出这种话呢?\n",
        "auhtor": "kohsuke",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2013
        "translator": "arjenzhou",
LinuxSuRen's avatar
LinuxSuRen 已提交
2014 2015
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2016 2017
    },
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
2018
        "uri": "https://jenkins-zh.cn/wechat/articles/2018/11/2018-11-21-validate-jenkinsfile/",
LinuxSuRen's avatar
LinuxSuRen 已提交
2019
        "title": "在 VS Code 中校验 Jenkinsfile",
LinuxSuRen's avatar
LinuxSuRen 已提交
2020 2021
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
LinuxSuRen 已提交
2022 2023
        "tags": [],
        "description": "VS Code 中的 Jenkinsfile 插件",
LinuxSuRen's avatar
LinuxSuRen 已提交
2024 2025 2026 2027 2028
        "content": "在日常工作中,我经常需要创建或修改很多 Jenkinsfile,有时还会发生错误。这是一个非常繁琐的流程——修改 Jenkinsfile,提交、推送,然后等 Jenkins 提醒你少加了一个括号。\nCommand-line Pipeline Linter(https://jenkins.io/doc/book/pipeline/development/) 可以有效地减少编写 Jenkinsfile 所需要的调试时间,但是它也有一些不方便的地方。你需要使用像 curl 或 ssh 的工具来连接你的 Jenkins,还需要正确地记住验证 Jenkinsfile 的命令。尽管如此,对我来说,这个方案还是不尽如人意。\n鉴于每天都会使用 VS Code,于是我开始着手为此研发插件,使得校验 Jenkinsfile 变得更加友好。\nJenkins Pipeline Linter Connector 的作用就是,把当前打开的文件推送到你的 Jenkins,然后在 VS Code 中显示校验结果。\n你可以在 VS Code 插件浏览器中或通过下面的地址找到该插件 https://marketplace.visualstudio.com/items?itemName=janjoerke.jenkins-pipeline-linter-connector 。\n该插件会在 VS Code 中添加四个配置选项,你必须要使用这些选项来配置用于验证的 Jenkins。\n jenkins.pipeline.linter.connector.url 是 Jenkins 期望的 POST 请求地址,包含你要校验的 Jenkinsfile 文件。通常为 *http:///pipeline-model-converter/validate*。 jenkins.pipeline.linter.connector.user 允许指定你的 Jenkins 用户名。 jenkins.pipeline.linter.connector.pass 允许指定你的 Jenkins 密码。 jenkins.pipeline.linter.connector.crumbUrl 当你的 Jenkins 启用了 CRSF 时必须指定。通常为 *http:///crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)*。 ​  ",
        "auhtor": "janjoerke",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2029
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2030
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
2031
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-16-webhook-firewalls/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2032
        "title": "在安全防火墙内通过 WebHook 触发构建",
LinuxSuRen's avatar
LinuxSuRen 已提交
2033 2034
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2035
        "tags": ["jenkins", "webhooks", "security"],
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2036
        "description": "谁说局域网里就不能带 GitHub 的 WebHook 玩?",
LinuxSuRen's avatar
LinuxSuRen 已提交
2037 2038 2039 2040 2041
        "content": " 在这篇文章中,我将向大家展示,如何让运行在防火墙内的 Jenkins 依然可以实时地收到 GitHub 的 WebHook。当然,你也可以把这个方法应用到如 BitBucket、 DockerHub 或任何可以推送 WebHook 的其他服务中。但是,下面的步骤仅适用于托管在 GitHub 上的项目。\n什么是 WebHook 简单地描述下什么是 WebHook:事件消息(通常是 JSON,也可以是其他的)由服务端以 HTTP(S) 协议发送到监听的客户端。\n事件流自左到右,Jenkins 会监听类似 /github-webhook/ 或 /dockerhub-webhook/ 等路径上的 HTTP 请求,唤醒并执行一些任务。\nGitHub 或 BitBucket 可能会报告一个新的提交或 PR,DockerHub 报告一个上游的镜像发生了变更。这些事情的共同之处在于,它们会推送给 Jenkins,并期待可以推送成功(例如:可以访问到 Jenkins)。在网络是开放的情况下时,例如 GitHub 企业版 或 Jenkins 在监听公网时,这是可以正常工作的。\n内网环境 当有东西挡在中间时,也就是防火墙:\n(_按照行业标准,所有防火墙都必须能起到屏障的作用。因此,无论如何,请不要在你的组织内搞破坏_)\n当你在笔记本电脑上运行 Jenkins 并希望从 GitHub 接收 WebHook 时,这也是一样的。可能是为了测试你的设置,也可能是为了在 Mac 上运行 iOS 版本构建,又或者是部分网络没有暴露在互联网中,这都是合理的。 除非你的笔记本电脑可以让整个互联网访问到(这当然不太可能),或者你的网络配置得恰到好处,否则网络连接将无法流动,此时 WebHook是不可用的。\n没关系,我们可以退而求其次,使用轮询变更的方式。只是这样很糟糕。你会用尽 API 配额,还无法实时地获取变更,这真的不是一个好方法。\n问题可能也是机会 我们可以解决这个问题,但也可以把这个视为一个机会。有的东西在互联网中不可访问,或者以某些默认的方法锁定是一个特色,不是一个 Bug。你可以很大程度上减少你的攻击面,同时可以进行深度防护:\n一个 WebHook 转发服务 输入 link:https://smee.io/[Smee] 这个很容易记住的名字。这是一个由 GitHub 提供的 link:https://github.com/probot/smee[开源软件项目],还能以服务的方式托管在 GitHub 上。这可以为你捕获并转发 WebHook。我会用一个图来给你解释它。\nGitHub 把一个事件(该场景下是通过 HTTPS/json)推送给 Smee.io(也就是圆圈标记的部分,暴露在互联网上并能被 GitHub 访问到),而 Jenkins 通过一个客户端使用一个向外的连接订阅 Smee 。注意箭头的方向:Jenkins 只有一个向外的连接。\n这一点很重要,只要防火墙允许向外访问就可以工作(像 NAT 以及其他网络通常就是这样的)。如果 Jenkins 无法访问外部的任何服务,那么,本文也就当然不会有什么帮助了(但是这通常不会出现的)。\n设置 步骤1:首先,访问 https://smee.io/ 并点击 “Start a new channel”:\n你会得到一个唯一的 URL(你应该拷贝出来以便后续使用):\n然后,在你运行 Jenkins 的地方安装 smee 客户端:\nnpm install --global smee-client\n(这让 smee 命令行客户端可以接收并转发 WebHook)。\n现在,启动 smee 客户端并指向你的 Jenkins。在该案例中,我的 Jenkins 运行在 8080 端口(这是默认的,如果在你的笔记本上运行的话,根据需要修改端口和 smee 地址):\nsmee --url https://smee.io/GSm1B40sRfBvSjYS --path /github-webhook/ --port 8080\n这样的话,会连接 smee 服务并转发 WebHook 到 /github-webhook/(最后的斜线很重要,不要丢了)。当运行起来,你将会从日志里看到,它已经连接并转发 WebHook。只要你希望能收到 WebHook 就需要保持该命令的运行。\n下一步,你需要配置一个使用 GitHub 的流水线。这里我从头开始配置。如果你已经有了一个的话,可以跳过:\n我选择 GitHub 作为代码仓库:\n然后,选择你的仓库。这将会设置好来准备接收来自 GitHub 的 WebHook(如果你已经有了流水线,并使用 GitHub 作为 SCM 源,那么也是可以的)。\n最后一步,是告诉 GitHub 为那个仓库(或组织也可以)发送 WebHook 事件给 Smee(最终会由 Jenkins 接收到)。\n选择你的 GitHub 仓库设置选项卡,并点击 “add webhook”:\n然后,配置 WebHook:\n 粘贴从上面步骤中拷贝的 smee 的 URL 选择 application/json 作为内容类型 选择 send everything(你可以选择你想要的事件,但我只是处于简单这么做)。 点击 Add Webhook(或 update)  它看起来应该像这样:\n好,现在 WebHook 应该可以了。你可以在你的仓库中添加一个变更,并稍后检查构建状态:\n祝你好运!\n",
        "auhtor": "michaelneale",
        "translator": "linuxsuren",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2042
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2043
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
2044
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/04/2019-04-15-security-spring-cleaning/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2045
        "title": "春季安全清查",
LinuxSuRen's avatar
LinuxSuRen 已提交
2046 2047
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2048
        "tags": ["plugins", "security"],
LinuxSuRen's avatar
LinuxSuRen 已提交
2049
        "description": "Jenkins 管理员们应该关注的安全问题",
LinuxSuRen's avatar
LinuxSuRen 已提交
2050 2051 2052 2053 2054
        "content": "今天我们公布了一个 安全报告, 主要是关于 Jenkins 的插件中 还没有被修复 的问题。 发生了什么?\nJenkins 安全团队将 漏洞反馈分类发布在 Jira 和我们的非公开邮件列表中。 一旦我们确定它不是由 Jenkins 安全团队成员维护的插件,我们会尝试将该问题通知插件维护者,以帮助我们开发,审查和发布修复。\n这种情况下,我们会发布 安全报告,将这些问题告知用户,即使没有发布修复版本。 这样可以让管理员作出决定,是否继续使用具有未解决的安全漏洞的插件。 今天发布的报告里大多数都是这样的安全问题。\n在这个列表中看到您感兴趣的插件并且想要帮忙?了解如何 认领一个插件。\n",
        "auhtor": "daniel-beck",
        "translator": "p01son6415",
        "original": "https://jenkins.io/blog/2019/04/03/security-advisory/",
        "poster": ""
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2055
    },
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2056
    {
LinuxSuRen's avatar
LinuxSuRen 已提交
2057
        "uri": "https://jenkins-zh.cn/wechat/articles/2019/01/2019-01-09-jenkins-evergreen/",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2058
        "title": "自动更新、易于使用的 Jenkins",
LinuxSuRen's avatar
LinuxSuRen 已提交
2059 2060
        "type": "wechat",
        "date": "0001-01-01 00:00:00 +0000 UTC",
LinuxSuRen's avatar
deploy  
LinuxSuRen 已提交
2061 2062
        "tags": ["jenkinsworld", "jenkinsworld2018", "evergreen"],
        "description": "借助 Evergreen 持续提供易于使用的 Jenkins",
LinuxSuRen's avatar
LinuxSuRen 已提交
2063 2064 2065 2066 2067
        "content": " 当我第一次 写 Jenkins Evergreen 相关的文章 , 后来被称为 \u0026ldquo;Jenkins Essentials\u0026rdquo;,我提到的一系列的未来的发展在接下来的几个月里已经变成了 现实 。 今年在旧金山举办的 DevOps World - Jenkins World 会议上,我会介绍 Jenkins Evergreen 背后哲学的更多细节,展示我们已经做了什么,并且讨论这个激进的 Jenkins 发行版的走向。\n正如我在第一篇博客以及 JEP-300 中所讨论的 Jenkins Evergreen 的前两大支柱是我们关注的要点.\n自动更新的发行版 不出所料, 实现安全、自动地更新Jenkins发行版(包括核心和插件)所需的机制需要很多的工作。在 Baptiste 的演讲中 他将讨论如何使 Evergreen \u0026ldquo;走起来\u0026rdquo;,而我会讨论 为何 自动更新的发行版很重要。\n持续集成和持续交付变得越来越普遍,并且是现代软件工程的基础 ,在不同的组织当中有两种不同的方式使用 Jenkins 。在一些组织当中,Jenkins 通过 Chef ,Puppet 等自动化工具有条不紊的被管理和部署着。然而在许多其他组织当中, Jenkins 更像是一个 设备 ,与办公室的无线路由器不同。当安装完毕,只要它能继续完成工作,人们就不会太多的关注这个设备。\nJenkins Evergreen 发行版通过确保最新的功能更新,bug 修复以及安全性修复始终能安装到 Jenkins 当中,\u0026ldquo;让 Jenkins 更像是一个设备\u0026rdquo;。\n除此之外, 我相信 Evergreen 能够向一些我们现在没有完全服务的团队提供良好的服务:这些团体希望能够以 服务 的形式使用 Jenkins 。我们暂时没有考虑提供公有云版本的 Jenkins 。我们意识到了自动接收增量更新,使用户可以在无需考虑更新 Jenkins 的情况下进行持续开发的好处。\n我相信 Jenkins Evergreen 可以并且可以提供相同的体验。\n自动配置默认值 Jenkins 平台真正强大的地方是可以为不同的组织提供不同的模式和做法。对于很多新用户来说,或一些只希望使用通用案例的用户来说, Jenkins 的灵活性与让用户做出合适的选择形成了悖论。使用 Jenkins Evergreen,很多常用的配置将自动配置,使 Jenkins 变成开箱即用的工具。\n默认情况下将包括 Jenkins 流水线和 Jenkins Blue Ocean,我们也删除了一些 Jenkins 的遗留功能。\n我们同样在使用非常棒的 Configuration as Code 进行工作, Configuration as Code 现在已经完成了1.0版本的发布, 我们通过它实现自动进行默认配置。\n现状 迄今为止,这个项目取得了重大的进展,我们非常高兴有用户开始尝试 Jenkins Evergreen,现在 Jenkins Evergreen 已经可以被 早期使用者 尝试. 不过我们现在 不 推荐在生产环境中使用 Jenkins Evergreen 。\n我们希望能够得到您的反馈和想法在我们的 Gitter channel !\n",
        "auhtor": "rtyler",
        "translator": "runzexia",
        "original": "",
        "poster": ""
LinuxSuRen's avatar
LinuxSuRen 已提交
2068
    }]