<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>devops | 伪架构师</title>
    <link>/tags/devops/</link>
      <atom:link href="/tags/devops/index.xml" rel="self" type="application/rss+xml" />
    <description>devops</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Thu, 03 Oct 2019 20:37:11 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>devops</title>
      <link>/tags/devops/</link>
    </image>
    
    <item>
      <title>可能是最适合自定义的 Pipeline：Tekton</title>
      <link>/post/customizable-cicd-tekton/</link>
      <pubDate>Thu, 03 Oct 2019 20:37:11 +0800</pubDate>
      <guid>/post/customizable-cicd-tekton/</guid>
      <description>

&lt;p&gt;持续集成是云原生应用的支柱技术之一，因此在交付基于云原生的一些支撑产品的时候，CICD 是一个无法拒绝的需求。为了满足这种需要，自然而然会想到对 Jenkins(X) 或者 Gitlab 进行集成，然而这两个东西虽说功能强大，却也不是为了做螺丝钉而设计的，其中包含了大量的周边功能，并非我们产品的需要，并且其接口和 Pipeline 设计也不太容易复用和提供给用户进行定制，而 Tekton 这个东西就有趣多了：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kubernetes 原生
Tekton 的所有配置都是使用 CRD 方式进行编写存储的，非常易于检索和使用。&lt;/li&gt;
&lt;li&gt;配置和流程分离
Tekton 的 Pipeline 和配置可以分开编写，使用名称进行引用。&lt;/li&gt;
&lt;li&gt;轻量级
核心的 Pipeline 非常轻便，适合作为组件进行集成，另外也有周边的 Dashboard、Trigger、CLI 等工具，能够进一步挖掘其潜力。&lt;/li&gt;
&lt;li&gt;可复用、组合的 Pipeline 构建方式
非常适合在集成过程中对 Pipeline 进行定制。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;安装&#34;&gt;安装&lt;/h2&gt;

&lt;p&gt;安装过程非常轻松：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl apply -f \
    https://storage.googleapis.com/tekton-releases/latest/release.yaml
namespace/tekton-pipelines created
podsecuritypolicy.policy/tekton-pipelines created
clusterrole.rbac.authorization.k8s.io/tekton-pipelines-admin created
...
$ kubectl get pods -n tekton-pipelines
NAME                                           READY   STATUS    RESTARTS   AGE
tekton-pipelines-controller-5888756f5c-t5kgx   1/1     Running   0          2m10s
tekton-pipelines-webhook-7494f6f84b-gm92g      1/1     Running   0          2m10s
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;概念&#34;&gt;概念&lt;/h2&gt;

&lt;p&gt;今天的内容主要涉及几个 CRD：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Task：任务环节。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;TaskRun：Task 对象的运行参数。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Pipeline：Task 的组合。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;PipelineRun：Pipeline 的运行参数。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;hello-world&#34;&gt;Hello world&lt;/h2&gt;

&lt;p&gt;这里有个比 Hello world 稍稍复杂一点的小例子：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;下载一个文件。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;传递给下一个环节。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;为什么不用官方例子呢？我想糊弄过 CI/CD/DevOps 的同学们应该都清楚，能使用容器、能执行 Shell、能获得输出、能传递文件，这几个能力加起来，足够冒充工具链小能手了。循序渐进并不适合心急的朋友们。&lt;/p&gt;

&lt;h3 id=&#34;下载文件并显示内容&#34;&gt;下载文件并显示内容&lt;/h3&gt;

&lt;p&gt;首先引入的是 Task 对象：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: get-http-file
spec:
  steps:
    - name: show
      image: dustise/sleep
      command:
        - curl
      args:
        - &amp;quot;-s&amp;quot;
        - &amp;quot;https://httpbin.org/ip&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里定义了一个 Task CRD，使用 &lt;code&gt;kubectl apply -f&lt;/code&gt; 提交到集群，会看到 &lt;code&gt;task.tekton.dev/get-http-file created&lt;/code&gt; 的反馈信息。&lt;/p&gt;

&lt;p&gt;要运行这个环节，可以创建一个 TaskRun 对象：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
  name: get-http-file-run
spec:
  taskRef:
    name: get-http-file
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;提交之后，可以使用 &lt;code&gt;kubectl get taskrun get-http-file-run -o yaml&lt;/code&gt; 来查看任务执行状况：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
...
status:
...
  conditions:
  - message: All Steps have completed executing
    reason: Succeeded
    status: &amp;quot;True&amp;quot;
    type: Succeeded
  podName: get-http-file-run-pod-51fddd
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里能看到很多任务执行信息，还能看到执行这个步骤的 Pod 名称，看看它的日志：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl logs -f get-http-file-run-pod-51fddd
{
  &amp;quot;origin&amp;quot;: &amp;quot;165.22.223.124, 165.22.223.124&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;看来 CICD 过程中的日志输出和命令执行基本是有保障的，那么如何完成工件的传递呢？&lt;/p&gt;

&lt;h3 id=&#34;文件传递&#34;&gt;文件传递&lt;/h3&gt;

&lt;p&gt;通常我们都会想到使用 PVC 来进行文件存储和共享，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: trans
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;首先把上面的步骤命令行改为：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;command:
- curl
args:
- &amp;quot;-s&amp;quot;
- &amp;quot;-o&amp;quot;
- &amp;quot;/share/share.json&amp;quot;
- &amp;quot;https://httpbin.org/ip&amp;quot;
volumeMounts:
- name: trans
  mountPath: /share
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;第二个步骤就更加简单，只要显示文件内容即可：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: display
spec:
  steps:
    - name: showcontent
      image: alpine
      command: [&amp;quot;cat&amp;quot;]
      args: [&amp;quot;/share/share.json&amp;quot;]
      volumeMounts:
        - name: trans
          mountPath: /share
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里需要使用 Pipeline 对象把步骤连接起来。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
  name: pipeline1
spec:
  tasks:
  - name: step1
    taskRef:
      name: download
  - name: step2
    runAfter: [step1]
    taskRef:
      name: display
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里的定义，使用 Pipeline 对象把两个步骤串联起来，其中使用 &lt;code&gt;taskRef&lt;/code&gt; 对我们定义的 &lt;code&gt;download&lt;/code&gt; 和 &lt;code&gt;display&lt;/code&gt; 两个 Task 对象进行引用，并且使用 &lt;code&gt;runAfter&lt;/code&gt; 数组定义先后顺序。&lt;/p&gt;

&lt;p&gt;和 &lt;code&gt;TaskRun&lt;/code&gt; 类似，Pipeline 定义之后，还需要用 PipelineRun 对象来执行一次，上面的 Task 中只定义了 &lt;code&gt;volumeMounts&lt;/code&gt;，具体的 Volume 就要在 PipelineRun 中定义：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
  name: pprun1
spec:
  pipelineRef:
    name: pipeline1
  podTemplate:
    volumes:
      - name: trans
        persistentVolumeClaim:
          claimName: trans
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;把 PipelineRun 提交到集群之后，就可以看到，Pipeline 开始运行，可以使用 &lt;code&gt;kubectl get&lt;/code&gt; 和 &lt;code&gt;kubectl logs&lt;/code&gt; 来查看运行情况。&lt;/p&gt;

&lt;h2 id=&#34;结果&#34;&gt;结果&lt;/h2&gt;

&lt;p&gt;这个项目还是很符合它的名字的描述的，真的只有 Pipeline 而已，它的最重要职责就是用 CRD 进行解耦，用 Step-&amp;gt;Task-&amp;gt;Pipeline 的三级形式对 CICD 中的动作进行抽象和分离；用 Task/TaskRun 以及 Pipeline/PipelineRun/Resource 的组合，把运行环节和输入输出内容进行分离。这样一来，就提供了一个稳定、可重构和组合的过程引擎，以及可定制的执行能力。&lt;/p&gt;

&lt;p&gt;Tekton 还提供了一些其它周边项目，例如 Dashboard、Trigger 等，能给 Pipeline 项目提供一定的帮助。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>马后炮：Operator for Spark 之后</title>
      <link>/post/operator-between-dev-and-ops/</link>
      <pubDate>Fri, 01 Feb 2019 21:12:34 +0800</pubDate>
      <guid>/post/operator-between-dev-and-ops/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.fleeto.us/post/google-announces-k8s-operator-for-spark/&#34; target=&#34;_blank&#34;&gt;Google 宣布 Kubernetes Operator for Spark&lt;/a&gt; 之后，朋友们的评价主要集中在 GCP 对大数据的浓厚兴趣上；我觉得还有一个解读就是，我以前可能低估了 Operator 的重要地位，因此有了本文。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;背景&#34;&gt;背景&lt;/h2&gt;

&lt;p&gt;CoreOS 最初在 2016 年底发布 Operator 概念时，称其主旨为：&lt;a href=&#34;https://coreos.com/blog/introducing-operators.html&#34; target=&#34;_blank&#34;&gt;Putting Operational Knowledge into Software&lt;/a&gt;，也就是将运维技能融入软件，在翻译该声明时，也只是觉得这一说法很有趣，但是在 GCP 发布了 Spark Operator 之后，我觉得似乎有必要回顾一下，Operator 到底是要用来做什么的。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;我们的团队正在 Kubernetes 社区进行一个概念的设计和实现，这一概念就是：在 Kubernetes 基础之上，可靠的创建、配置和管理复杂应用的方法。
我们把这种软件称为 Operator。一个 Operator 指的是一个面向特定应用的控制器，这一控制器对 Kubernetes API 进行了扩展，使用 Kubernetes 用户的行为方式，创建、配置和管理复杂的有状态应用的实例。他构建在基础的 Kubernetes 资源和控制器概念的基础上，但是包含了具体应用领域的运维知识，实现了日常任务的自动化。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;上面一篇文字来自我对原文的译稿：&lt;a href=&#34;https://blog.fleeto.us/post/operator-for-kubernetes/&#34; target=&#34;_blank&#34;&gt;Operator：固化到软件中的运维技能&lt;/a&gt;，这一段文字分析一下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;复杂应用：一般来说，Kubernetes 上的复杂应用，指的主要是两种：有状态或者有协作。&lt;/li&gt;
&lt;li&gt;创建、配置和管理：在软件的开发阶段之后，就进入了 Operator 的管理范围了。&lt;/li&gt;
&lt;li&gt;使用 Kubernetes 用户的行为方式：Kubectl、API Server、声明式的 API、资源、YAML。。。&lt;/li&gt;
&lt;li&gt;特定应用的控制器：在软件的“本体”之外，还需要实现一个控制单元，用来完成对专属资源的解释和执行。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;粗看上来，这东西有点多余，多学东西、多写东西，为的就是在 Kubernetes 上用 Kubectl 操作 YAML 的方式来装软件配置软件？老夫早已熟悉各种 ini xml json toml 等乌七八糟的配置方式。要这东西有什么用呢？&lt;/p&gt;

&lt;p&gt;为了示范 Operator 的功能，CoreOS 特意开放了两个 Operator：&lt;a href=&#34;https://github.com/coreos/etcd-operator&#34; target=&#34;_blank&#34;&gt;ETCD&lt;/a&gt; 和 &lt;a href=&#34;https://github.com/coreos/prometheus-operator&#34; target=&#34;_blank&#34;&gt;Prometheus&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;例如 ETCD Operator，通过一定的 YAML 定义，可以完成以下功能：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;创建集群&lt;/li&gt;
&lt;li&gt;集群伸缩&lt;/li&gt;
&lt;li&gt;故障应对&lt;/li&gt;
&lt;li&gt;集群升级&lt;/li&gt;
&lt;li&gt;备份和恢复&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;同时 CoreOS 还提供了 &lt;a href=&#34;https://github.com/operator-framework&#34; target=&#34;_blank&#34;&gt;Operator Framework&lt;/a&gt; 进行 Operator 的开发。&lt;/p&gt;

&lt;h2 id=&#34;当运维遇上-operator&#34;&gt;当运维遇上 Operator&lt;/h2&gt;

&lt;p&gt;Operator 的功能，稍微理解一下，就看得出它提出了一个新的运维方式：使用 Kubernetes 原生 API 或者 Kubectl 等基于这种 API 的工具来替换原本各走各路的运维方式。把原有的各种系统的部署和配置方式，转换为 Kubernetes 世界中的 CRD，利用 CRD 的资源对象来完成各种运维任务。&lt;/p&gt;

&lt;p&gt;这实际上是将运维操作进行了一次抽象，用一致的界面来完成各种不同的运维动作，在理想情况下，一个软件系统提供的 Operator 丰富到覆盖其所有应用场景，那么他的所有运维操作都是可以通过 API Server 接口来进行控制，这给运维工作带来很大的便利：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;避免学习该软件的配置方言，降低上手难度。&lt;/li&gt;
&lt;li&gt;使用模板渲染的方式，能够迅速的将该软件的运维需要转换为流程化、自动化操作。&lt;/li&gt;
&lt;li&gt;增强的控制能力，能够方便的进行 CI/CD 集成。&lt;/li&gt;
&lt;li&gt;声明式 API，对运维过程的管理，提供了更高的透明、可控、版本化等优势。&lt;/li&gt;
&lt;li&gt;现有的控制门户等运维设施，也能完成新系统的快速接入。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;上述种种优势，对运维工作来说都是很有帮助的，然而面对现实，还是有一些限制的：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;平台限制：很明显，几乎只有 Kubernetes 上的应用才能享受 Operator 的优势。&lt;/li&gt;
&lt;li&gt;数量稀少：目前有提供 Operator 的软件还是九牛一毛，未能产生规模效应，配置方言的学习并无法避免。&lt;/li&gt;
&lt;li&gt;设计困难：Operator Controller 定义 CRD，然后使用 API 提交 CRD 资源对象的方式看上去很不错，但是要用 CRD 定义一个系统的所有场景，谈何容易，官方的 Prometheus Operator 基本无法生产应用就是明证。&lt;/li&gt;
&lt;li&gt;Operator 失败的情况下，其原始的方言配置未必能够在 Kubernetes + Operator 环境中奏效。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;最大的一个问题，Operator 是需要开发的，谁来负责他的工作量呢？&lt;/p&gt;

&lt;h2 id=&#34;当开发遇上-operator&#34;&gt;当开发遇上 Operator&lt;/h2&gt;

&lt;p&gt;对开发来说，Operator 如果流行，可能不是一个好消息。&lt;/p&gt;

&lt;p&gt;目前的企业系统开发中，通常对于最终用户的界面、以及应用之间的 API 管理都有详尽的需求、设计和测试等文档要求，然而在&lt;strong&gt;运维是自己人&lt;/strong&gt;的情况下，因为&lt;strong&gt;并不影响交付&lt;/strong&gt;，很多&lt;strong&gt;中间、自用系统&lt;/strong&gt;的运维工作设计，往往就糊弄了事了&lt;/p&gt;

&lt;p&gt;如果 Operator 落地开花，就产生了一个副作用——需要修改交付标准：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;把运维当成用户&lt;/li&gt;
&lt;li&gt;运维用户自然也应该有针对性的需求调研分析&lt;/li&gt;
&lt;li&gt;要有详尽的运维场景设计&lt;/li&gt;
&lt;li&gt;对于 Operator CRD 无法完整覆盖的情况下，要有降级的措施准备。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;

&lt;p&gt;通过上面粗浅的分析，可以看出要落地使用 Operator，对 DevOps 的两端都需要有一点点的变化：Dev 的交付标准，和 Ops 的工作方式。&lt;/p&gt;

&lt;p&gt;带来的好处也不太醒目：声明化、标准化和自动化。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>为什么持续改进是持续交付的基础</title>
      <link>/post/what-is-key-to-continuous-delivery/</link>
      <pubDate>Tue, 15 May 2018 17:45:22 +0800</pubDate>
      <guid>/post/what-is-key-to-continuous-delivery/</guid>
      <description>

&lt;p&gt;原文：&lt;a href=&#34;http://blog.wercker.com/what-is-key-to-continuous-delivery&#34; target=&#34;_blank&#34;&gt;Why Continuous Improvement is Key to Continuous Delivery&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;作者：&lt;a href=&#34;https://twitter.com/HoardingInfo&#34; target=&#34;_blank&#34;&gt;Chris Riley&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DevOps 的最大难题就是，DevOps 是永无止境的。并不存在一个（确切的）DevOps指南，也没有什么最终标志能够证明一个组织完成了 DevOps 的漫长旅途。&lt;/p&gt;

&lt;p&gt;如果有人恰巧觉得，本人/组织当前的 DevOps 实践已经达到了自身应用发布过程的终极需要，那么可能一年以后，这一环境就可能变成了新版本的瀑布。以不变应万变，是难以应对各种来自客户、来自基础设施以及部署方式的更迭的。所以我们要说，没有持续改进的持续交付，是没有前途的。&lt;/p&gt;

&lt;p&gt;下面详细的解释一下我们的看法。&lt;/p&gt;

&lt;h2 id=&#34;主动改进&#34;&gt;主动改进&lt;/h2&gt;

&lt;p&gt;自动化工具链是 DevOps 团队的制胜法宝，这一点毋庸置疑。然而这一切通常都是事出有因的，有时是有新技术发布，有时是组织机构改革等等。不管是什么在主导着变化，其实都不是主动发生的。变化只会在有条件的时候被触发，每一两年，都会出现这种机会。&lt;/p&gt;

&lt;p&gt;持续改进则正好相反。持续改进意味着一种对改进的主动投入。这是一种对现状的改进意愿（和不满）。金无足赤，环境也是始终会有其弱点。DevOps 团队应避免故步自封，对现有的大好形势保持怀疑，不错过其中出现的任何微小缺陷。&lt;/p&gt;

&lt;p&gt;但是文化和改进方面的管理焦点是很难贯彻始终的。一个 DevOps 工程师所实现的改进工作是很难量化的。一种文化究竟做出了什么贡献，也不是非常容易分辨的。有些组织认为自己是持续改进的牺牲品，但技术人员应该注意的是，一些看上去很美的新玩具，往往都会引入很多的额外问题，因此应该慎重考虑，而不是想上就上。&lt;/p&gt;

&lt;h2 id=&#34;管线即应用&#34;&gt;管线即应用&lt;/h2&gt;

&lt;p&gt;时至今日，CI 已经成为应用交付的内在需要，因此 Pipeline 理应得到跟其他应用一样的重视程度。应用开发过程是围绕 Backlog 进行的，所有的任务都是向其中添加功能或者修复其中的问题。那么如果将 Pipeline 视为应用的话，那么就有了持续改进的基础。为了达成这一目标，所有工作都应该进行脚本化，所有重复工作都应该自动化，Backlog 中随时反应了我们对交付链条的优化努力。Pipeline 应用也应该有自己的功能和 Bug。Pipeline 的客户就是开发人员和生产环境。在这样的视角之下，就能对 Pipeline 的变更和改进了然于心。&lt;/p&gt;

&lt;p&gt;这里有个潜在的要求就是，要有专职人员负责 Pipeline 的开发，并在生产环境上进行维护。要实施这一方法的组织，必须做好这种准备。&lt;/p&gt;

&lt;h2 id=&#34;重在结果&#34;&gt;重在结果&lt;/h2&gt;

&lt;p&gt;第三个问题是，如何判断当前的做法是正确的？必须做点什么来体现结果和指标。跟生产环境上的其他应用一样，我们的 Pipeline 也应该有各种 KPI。持续改进需要反映出随着时间的推移，各种指标的变化。例如：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;本年度开始之后，发布过程变快了多少？&lt;/li&gt;
&lt;li&gt;发布过程需要多少步骤？精简掉了多少？&lt;/li&gt;
&lt;li&gt;有多少应用是 100% 自动部署的？&lt;/li&gt;
&lt;li&gt;跟去年相比，发布活动多了多少？&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;有时候，改进是一种直觉。团队成员应该大致了解，Pipeline 是否减轻了压力并提高了部署能力。但是对持续改进的审慎态度，要求我们必须对过程中的得失进行量化，并作出汇报。&lt;/p&gt;

&lt;p&gt;持续交付现在已经是开发活动的重要组成部分，但是如果不持续作出改进，那么整个环境都会逐渐变得过时。通过上面讲述的三个原则，来确保当下和未来的 DevOps 过程能够一以贯之的持续下去。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Monitor as Code 的一点尝试</title>
      <link>/post/monitor-as-code/</link>
      <pubDate>Tue, 23 May 2017 02:53:05 +0800</pubDate>
      <guid>/post/monitor-as-code/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;这篇的真实名字应该是：Grafana 也是有 API 的&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在项目的 CI/CD 实践过程中，XX as code 是一个很重要的方法，利用代码的方式，对软件的构建、发布、测试等环节进行表达，一方面极大的提高了自动化程度；另一方面，将这些代码纳入版本管理范围，使其同软件代码同步更新和迭代，更好的体现了系统的整体性，提高了系统的可维护性。&lt;/p&gt;

&lt;p&gt;前面的文章中我也多次提到了监控的内容，业务和系统的运行状况可视化是系统运行的重要支撑。甚至监控本身就应该是软件的一部分。得益于各种开源软件的支持，我们可以做一番 Monitor as Code 的尝试。&lt;/p&gt;

&lt;p&gt;监控过程本身一般由数据的产生和展示两个部分组成，对于系统数据，例如 Kubernetes 或者主机数据，我们可以使用 Zabbix、Heapster 或者 cAdvisor 以及 Prometheus 进行获取；而业务的数据则需要借助业务应用自身的代码或者数据库来转换为指标数据，注入到 InfluxDB 等时间序列数据库中。本文中暂不介绍数据生成部分的内容。&lt;/p&gt;

&lt;p&gt;最终我们继续选择 Grafana 进行数据的展示。这是这一篇里面唯一有用的内容了。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;实际操作中，本文过程都应该在 Jenkins Pipeline 中，从版本库拉取代码完成，为叙述方便，使用 Shell 脚本代替。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;步骤说明&#34;&gt;步骤说明&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;代码准备&lt;/li&gt;
&lt;li&gt;Grafana 准备&lt;/li&gt;
&lt;li&gt;创建、更新 Grafana Dashboard&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;代码准备&#34;&gt;代码准备&lt;/h2&gt;

&lt;p&gt;代码目录结构大致如下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;codebase&lt;/li&gt;
&lt;li&gt;build

&lt;ul&gt;
&lt;li&gt;docker&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;ops

&lt;ul&gt;
&lt;li&gt;monitor&lt;/li&gt;
&lt;li&gt;view&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;code-base&#34;&gt;code base&lt;/h3&gt;

&lt;p&gt;一般用于存放业务代码。&lt;/p&gt;

&lt;h3 id=&#34;build&#34;&gt;build&lt;/h3&gt;

&lt;p&gt;该目录用于存放构建代码，例如&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jenkins Pipeline code&lt;/li&gt;
&lt;li&gt;构建过程中的支持脚本&lt;/li&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;li&gt;Kubernetes yaml&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;ops&#34;&gt;ops&lt;/h3&gt;

&lt;p&gt;这里用于放置运维相关的一些内容，本文将要使用的代码也在此存放。&lt;/p&gt;

&lt;p&gt;实际上，这里除了 Grafana 的内容之外，还可以包含一些其他代码例如&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus Exporter&lt;/li&gt;
&lt;li&gt;Zabbix User Script&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;grafana-准备&#34;&gt;Grafana 准备&lt;/h2&gt;

&lt;p&gt;首先在 Grafana 的管理菜单中创建一个权限为 Editor 的 API Token：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/api-keys.png&#34; alt=&#34;API Keys&#34; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;注意这里生成的 Key 只显示一次&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;创建或者更新-grafana-dashboard&#34;&gt;创建或者更新 Grafana Dashboard&lt;/h2&gt;

&lt;p&gt;生成了 API Token 之后的事情就很简单了，准备一个 Grafana 的 JSON 文件，用 CURL 进行 POST 即可&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;POST /api/dashboards/db HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;dashboard&amp;quot;: {
    &amp;quot;id&amp;quot;: null,
    &amp;quot;title&amp;quot;: &amp;quot;Production Overview&amp;quot;,
    &amp;quot;tags&amp;quot;: [ &amp;quot;templated&amp;quot; ],
    &amp;quot;timezone&amp;quot;: &amp;quot;browser&amp;quot;,
    &amp;quot;rows&amp;quot;: [
      {
      }
    ],
    &amp;quot;schemaVersion&amp;quot;: 6,
    &amp;quot;version&amp;quot;: 0
  },
  &amp;quot;overwrite&amp;quot;: false
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;ldquo;id&amp;rdquo; 部分为 NULL 代表新建 Dahsboard。如果是从 Grafana 导出的内容，则沿用旧有取值进行更新即可。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;可以利用模板+变量的方式来使用 Dashboard 导出文件，用于适应不同环境的部署下，不同的数据源名称，不同的细节调整。&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title>Docker DevOps：数据容器和网络</title>
      <link>/post/data-container-network-in-docker-world/</link>
      <pubDate>Mon, 04 Jul 2016 08:57:38 +0800</pubDate>
      <guid>/post/data-container-network-in-docker-world/</guid>
      <description>

&lt;blockquote&gt;
&lt;p&gt;Matt Saunders 具有企业和创业的双重背景，&lt;a href=&#34;http://contino.io/&#34; target=&#34;_blank&#34;&gt;Contino&lt;/a&gt; 的高级工程师和首席 DevOps 顾问。Matt 还是 [伦敦 DevOps 会议]（超过 3000 成员的月度会议）的组织者之一。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;docker-眼中数据容器的未来是怎样的-针对数据容器不应使用在复制系统上的批评-docker-如何回应呢&#34;&gt;Docker 眼中数据容器的未来是怎样的？针对数据容器不应使用在复制系统上的批评，Docker 如何回应呢？&lt;/h2&gt;

&lt;p&gt;Docker 建议持久化数据应该存储到具名卷中，现在和未来的创新会提高这一技术的稳定性和容错性。我相信多数针对数据容器的批评的焦点在于，数据容器无法在主机间迅速转移，这就意味着随 Docker 建立的数据容器只能存在于一个主机上。然而随着 Docker 1.9 的出现， &lt;a href=&#34;https://clusterhq.com/2015/10/27/flocker-plugin-for-docker/&#34; target=&#34;_blank&#34;&gt;Flocker&lt;/a&gt;、&lt;a href=&#34;https://github.com/rancher/convoy&#34; target=&#34;_blank&#34;&gt;Convoy&lt;/a&gt; 以及 &lt;a href=&#34;http://glusterfs/&#34; target=&#34;_blank&#34;&gt;GlusterFS&lt;/a&gt; 这些的插件让 Docker 能够在这些存储集群上建立卷了。&lt;/p&gt;

&lt;h2 id=&#34;docker-的网络模型-针对目前的需要-做了哪些增强呢&#34;&gt;Docker 的网络模型，针对目前的需要，做了哪些增强呢？&lt;/h2&gt;

&lt;p&gt;Docker 1.12 带来了很多改进，包括无缝的利用独立网络来启动整个应用栈的巨大进步。同样受益于插件系统，Docker 能够使用第三方的网络插件。Docker 1.12 还增强了网络安全性，利用软件定义网络，为应用提供了隔离良好的能跨越多个 Docker 主机的网络堆栈。负载均衡得到了显著增强，这是这一版本的主要特性之一。&lt;/p&gt;

&lt;h2 id=&#34;你认为最近启动的-docker-安全扫描-对企业云用户有效果么-docker-对安全的态度是怎样的&#34;&gt;你认为最近启动的 Docker 安全扫描，对企业云用户有效果么？Docker 对安全的态度是怎样的？&lt;/h2&gt;

&lt;p&gt;Docker 最大的好处，也是企业用户最大的担心。把整个应用的依赖打包在一个镜像之中，就获得了让容器有了被迁移的能力，但是与此同时也带来了透明性的损失。&lt;/p&gt;

&lt;p&gt;Docker 的安全扫描，在 DockerHub 上根据已知的软件缺陷进行评估，降低了这一风险，在 Docker Hub 上建立了私有仓库的企业将从中获益。在私有云中运行 Docker 受信仓库的用户同样也具有这方面的担忧。，我们正准备更进一步的把这一特性带给 Docker 数据中心的用户。&lt;/p&gt;

&lt;p&gt;安全是 Docker 第一优先考虑的问题，过去发行的版本在这一方面进行了持续的增强，去年还发布了 Docker 内容信任（机制？）。这使得基于 Docker 的安装越来越好的同现有安全策略进行写作。&lt;/p&gt;

&lt;h2 id=&#34;it-团队是如何看待这一新兴技术的投资回报率的&#34;&gt;IT 团队是如何看待这一新兴技术的投资回报率的？&lt;/h2&gt;

&lt;p&gt;可以用多种途径来度量投资回报率 —— 最显而易见的就是缩减了虚拟化层造成的性能浪费。Docker 能够更快的进行代码的测试和发布，也大大的加速了软件的交付过程。&lt;/p&gt;

&lt;h2 id=&#34;你认为哪些行业更愿意拥抱容器技术&#34;&gt;你认为哪些行业更愿意拥抱容器技术？&lt;/h2&gt;

&lt;p&gt;容器技术对于 Web 应用有很好的支撑能力，因此在线商务最乐于进行这方面的投入。不过这并不是排他的，任何想要提高交付速度的行业都会跟进。&lt;/p&gt;

&lt;h2 id=&#34;在初步接触容器技术的过程中-最容易犯下什么错误&#34;&gt;在初步接触容器技术的过程中，最容易犯下什么错误？&lt;/h2&gt;

&lt;p&gt;很多公司会尝试用（过去的）虚拟化同样的思路来运行容器，这当然还是会有一定的好处，但是也有其局限性。这种做法会造出肥胖的容器，是一种买椟还珠的行为。&lt;/p&gt;

&lt;h2 id=&#34;是否存在不适合-docker-的场景&#34;&gt;是否存在不适合 Docker 的场景？&lt;/h2&gt;

&lt;p&gt;目前还局限于 Linux。&lt;/p&gt;

&lt;p&gt;Windows 支持目前还比较幼稚，但是今年会有显著的增强。另外不希望迎合技术变革的企业也不应该选择 Docker —— 这一新技术对软件的生命周期会造成巨大变化，对身处其中的企业和雇员来说，都会带来很大挑战。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
