<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>kustomize | 伪架构师</title>
    <link>/tags/kustomize/</link>
      <atom:link href="/tags/kustomize/index.xml" rel="self" type="application/rss+xml" />
    <description>kustomize</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Fri, 06 Sep 2019 01:50:43 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>kustomize</title>
      <link>/tags/kustomize/</link>
    </image>
    
    <item>
      <title>Kustomize Fomulas</title>
      <link>/post/kustomize-formulas/</link>
      <pubDate>Fri, 06 Sep 2019 01:50:43 +0800</pubDate>
      <guid>/post/kustomize-formulas/</guid>
      <description>

&lt;p&gt;项目地址 &lt;a href=&#34;https://github.com/fleeto/kustomize-patch-formulas&#34; target=&#34;_blank&#34;&gt;Kustomize-patch-formulas&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这个项目有两个目的。&lt;/p&gt;

&lt;p&gt;第一点就是，既然有了 &lt;a href=&#34;https://github.com/kubernetes-sigs/kustomize&#34; target=&#34;_blank&#34;&gt;Kustomize&lt;/a&gt;，使用碎片来拼接复杂的 YAML 就很方便了，设想以下情况：&lt;/p&gt;

&lt;p&gt;一个只会写简单 Deployment 的小白，随时要去翻书，查查如何加入资源限制，如何加载存储卷，如何设置环境变量&amp;hellip;.，翻完用完，俩月之后同样的痛苦再来一次，周而复始。。好吧我就是那个小白。&lt;/p&gt;

&lt;p&gt;Kustomize 能不能让这个过程舒服一点？&lt;/p&gt;

&lt;p&gt;开始摸索 Kustomize 之后，我觉得有救了，只要我把需要的配置碎片积累下来，用的时候稍作修改，然后用 Kustomize 渲染出来，是不是就省了不少麻烦了？另外对一些巨型的 YAML，比如多个 Deployment 和 Service 和 VirtualService 什么的混成一个文件的情况，直接上手修改是很辛苦的，用这种方式也可以方便快捷的进行一些变更。&lt;/p&gt;

&lt;p&gt;更近一步的，这些补丁都很小，如果稍稍做点模板处理，用个小脚本加工成正式的 Patch，复用能力会进一步增强。&lt;/p&gt;

&lt;p&gt;第二点就是，就算不考虑这些问题，把常见的配置碎片搜集起来也是对 Kubernetes 运维工作很有帮助的。&lt;/p&gt;

&lt;h2 id=&#34;用法&#34;&gt;用法&lt;/h2&gt;

&lt;p&gt;例如我们有一个简单的 Deployment， &lt;code&gt;/tmp/deploy.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
        version: v1
    spec:
      containers:
        - name: flaskapp
          image: dustise/flaskapp
          imagePullPolicy: IfNotPresent
          env:
            - name: version
              value: v1
          ports:
            - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;克隆本项目之后，我们希望借助其中的补丁，为这个对象加入资源限制和 ServiceAccount：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ ./gen_kustomize.py -i /tmp/deploy.yaml -o kust
$ tree kust
kust
├── base
│   ├── deploy.yaml
│   └── kustomization.yaml
└── overlay
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这个命令会为该文件创建一个 Kustomization。其中的 &lt;code&gt;-i&lt;/code&gt; 参数可以加入多个文件，都会被复制到目标目录（&lt;code&gt;kust&lt;/code&gt;）的 &lt;code&gt;base&lt;/code&gt; 之中。&lt;/p&gt;

&lt;p&gt;接下来向其中加入补丁：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ ./add_patch.py kubernetes/deployment/resource-patch.yaml \
    --set container_name=flaskapp deployment_name=flaskapp \
    limit_cpu=100m limit_memory=100Mi request_cpu=100m \
    request_memory=100Mi \
    -t kust
$ ./add_patch.py kubernetes/deployment/serviceaccount-patch.yaml \
    --set container_name=flaskapp \
    deployment_name=flaskapp service_account=default \
    -t kust
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里的第一个参数是补丁文件的位置，&lt;code&gt;--set&lt;/code&gt; 后面以 &lt;code&gt;key=value&lt;/code&gt; 的形式为模板进行赋值。模板的写法也很简单，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: $deployment_name
spec:
  replicas: 1
  template:
    spec:
      serviceAccount: $service_account
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;使用的是 Python 模板，只要简单的在变量前加入 &lt;code&gt;$&lt;/code&gt; 即可，因为对 Helm 深感疲惫，暂时不准备接入太复杂的模板方式，毕竟补丁本身越小越精确就越好。&lt;/p&gt;

&lt;p&gt;加入补丁之后，使用 &lt;code&gt;kustomize build kust/overlay&lt;/code&gt; 进行渲染：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
        version: v1
    spec:
      containers:
      - env:
        - name: version
          value: v1
        image: dustise/flaskapp
        imagePullPolicy: IfNotPresent
        name: flaskapp
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 100m
            memory: 100Mi
      serviceAccount: default
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到，这里生成了完整的目标文件。&lt;/p&gt;

&lt;h2 id=&#34;需要贡献&#34;&gt;需要贡献&lt;/h2&gt;

&lt;p&gt;这个项目还非常低级，不堪一用，觉得这个小东西有意思的朋友可以提供：&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;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Kustomize 中的增删改查</title>
      <link>/post/crud-with-kustomize/</link>
      <pubDate>Sat, 17 Aug 2019 23:12:56 +0800</pubDate>
      <guid>/post/crud-with-kustomize/</guid>
      <description>

&lt;p&gt;在之前的文章中，我曾经说过，相对于 Helm Chart，Kustomize 具有更平缓的学习曲线，更灵活的派生方式，当然这也不是没有代价的，Kustomize 的分享方式和规范性都弱于 Helm Chart，而且上游对下游也是相当缺乏控制能力的。&lt;/p&gt;

&lt;p&gt;本文会从实际出发，列出一系列的场景，看看拿到一个上游应用的标准 YAML 之后，如何使用 Kustomize 对其进行增删改查，形成新的 Kubernetes 资源组，完成对派生应用的定义。&lt;/p&gt;

&lt;h2 id=&#34;准备工作&#34;&gt;准备工作&lt;/h2&gt;

&lt;p&gt;首先我们创建实验目录 &lt;code&gt;lab/base&lt;/code&gt;，在其中生成一组 YAML 文件，作为后续实验的基础（&lt;code&gt;base&lt;/code&gt;），这是一个很简单的应用，只有一个 Deployment：&lt;/p&gt;

&lt;p&gt;deploy.yaml：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
        version: v1
    spec:
      containers:
        - name: flaskapp
          image: dustise/flaskapp
          imagePullPolicy: IfNotPresent
          env:
            - name: version
              value: v1
          ports:
            - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果使用 Kubectl 提交，会在当前命名空间中新建一个 Deployment 和一个 Pod，当然我们暂时不会这么做。&lt;/p&gt;

&lt;p&gt;接下来是创建一个 Kustomize 的定义，作为后续实验的基础，基础定义很简单，它甚至可能不会由上游应用的开发者编写，而是下游的定制者用它来做一个基础。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kustomization.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;resources:
- deploy.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;对它进行渲染，会毫无意外的出现一个和 &lt;code&gt;deploy.yaml&lt;/code&gt; 一样的输出内容：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kubectl kustomize base
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
...
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;增&#34;&gt;增&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;创建一个新的工作目录，&lt;code&gt;lab/overlays/c&lt;/code&gt;，本节的内容都会使用这个目录来完成。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在继承上游应用的 YAML 时，经常需要向其中加入定制元素，比如加入新的 Ingress、Service、Configmap 等，还有可能新增一些对象内的定义。下面的两个例子分别展示了 Kustomize 完成这类任务的方法。&lt;/p&gt;

&lt;h3 id=&#34;加入新对象&#34;&gt;加入新对象&lt;/h3&gt;

&lt;p&gt;上面的 Base 中，有了一个孤零零的 Deployment，多数的业务应用还是需要有个 Service 提供服务的，我们就给它加入一个新对象。&lt;/p&gt;

&lt;p&gt;在 &lt;code&gt;c&lt;/code&gt; 目录中，新建一个 &lt;code&gt;service.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Service
metadata:
  name: flaskapp
  labels:
    app: flaskapp
spec:
  selector:
    app: flaskapp
    version: v1
  ports:
    - name: http
      port: 80
      targetPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后新建一个 &lt;code&gt;kustomization.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../../base
resources:
- service.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;执行命令 &lt;code&gt;kustomize build overlays/c&lt;/code&gt;，可以看到，在原有 &lt;code&gt;Deployment&lt;/code&gt; 的基础上，新增了一个服务。&lt;/p&gt;

&lt;h3 id=&#34;新增字段&#34;&gt;新增字段&lt;/h3&gt;

&lt;p&gt;很多应用都会声明运行时的资源需求，但是我们的 &lt;code&gt;base&lt;/code&gt; 中并没有这个字段，Kustomize 可以用补丁的方式加入这个字段。&lt;/p&gt;

&lt;p&gt;首先创建一个补丁文件 &lt;code&gt;overlays/c/resource-patch.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: flaskapp
        resources:
          requests:
            memory: &amp;quot;64Mi&amp;quot;
            cpu: &amp;quot;250m&amp;quot;
          limits:
            memory: &amp;quot;64Mi&amp;quot;
            cpu: &amp;quot;250m&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;上面的补丁文件用最简单的字段赋值标识出了要打补丁的位置，并加入了资源限制。&lt;/p&gt;

&lt;p&gt;修改 &lt;code&gt;overlays/c/kustomization.yaml&lt;/code&gt;，加入补丁：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../../base
resources:
- service.yaml
patchesStrategicMerge:
- resource-patch.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再次使用 &lt;code&gt;kustomize build overlays/c&lt;/code&gt;，或者直接使用 &lt;code&gt;kubectl apply -k overlays/c&lt;/code&gt;，都能看到，资源限制已经应用。&lt;/p&gt;

&lt;h3 id=&#34;创建-configmap-并加载&#34;&gt;创建 Configmap 并加载&lt;/h3&gt;

&lt;p&gt;在 &lt;code&gt;overlays/c&lt;/code&gt; 下面新建一个配置文件 &lt;code&gt;config.ini&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ini&#34;&gt;key=value
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;新增的 &lt;code&gt;configMapGenerator&lt;/code&gt; 要求使用 &lt;code&gt;config.ini&lt;/code&gt; 生成一个 ConfigMap。&lt;/p&gt;

&lt;p&gt;然后再做一个补丁文件 &lt;code&gt;env-patch.yaml&lt;/code&gt;，用来加载 Config：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: flaskapp
        env:
        - name: CONFIG
          valueFrom:
            configMapKeyRef:
              name: config-ini
              key: config.ini
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;修改 &lt;code&gt;kustomization.yaml&lt;/code&gt;，加入我们的 Configmap 和补丁，结果为如下内容：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../../base
resources:
- service.yaml
configMapGenerator:
- name: config-ini
  files:
    - config.ini
patchesStrategicMerge:
- resource-patch.yaml
- env-patch.yaml
generatorOptions:
  disableNameSuffixHash: true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;kubectl apply -k overlays/c&lt;/code&gt; 之后，会看到 Pod 中加入了对 Configmap 的引用，进入 Pod 也能看到新增的环境变量，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl exec -it flaskapp-5b886b8dfc-qq68w env | grep CONFIG
CONFIG=key=value
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;删&#34;&gt;删&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;创建一个新的工作目录，&lt;code&gt;lab/overlays/d&lt;/code&gt;，本节的内容都会使用这个目录来完成。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;使用 &lt;code&gt;patchesStrategicMerge&lt;/code&gt; 的特定语法，可以删除指定内容。&lt;/p&gt;

&lt;h3 id=&#34;删除一个对象&#34;&gt;删除一个对象&lt;/h3&gt;

&lt;p&gt;在 &lt;code&gt;c&lt;/code&gt; 案例中新建的 Service 对象，我并不想要，如何通过 &lt;code&gt;Kustomize&lt;/code&gt; 删掉？同样也使用打补丁的方式来解决。首先创建一个继承自 &lt;code&gt;overlays/c&lt;/code&gt; 的 Kustomization，在 &lt;code&gt;overlays/d&lt;/code&gt; 中创建 &lt;code&gt;kustomization.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../c
patchesStrategicMerge:
- remove-svc.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;以及 &lt;code&gt;remove-svc.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: Service
apiVersion: v1
metadata:
  name: flaskapp
$patch: delete
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;运行 &lt;code&gt;kustomize build overlays/d&lt;/code&gt;，可以看到，输出内容中的 Service 不见了。&lt;/p&gt;

&lt;h3 id=&#34;删除一个字段&#34;&gt;删除一个字段&lt;/h3&gt;

&lt;p&gt;接下来我们用类似的方法，删除前面设置的环境变量：&lt;/p&gt;

&lt;p&gt;新建一个 &lt;code&gt;remove-field.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
        version: v1
    spec:
      containers:
        - name: flaskapp
          image: dustise/flaskapp
          env:
          - name: CONFIG
            $patch: delete
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再把补丁加入 &lt;code&gt;kustomization.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../c
patchesStrategicMerge:
- remove-svc.yamlƒ
- remove-field.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再次 &lt;code&gt;kustomize build overlays/d&lt;/code&gt;，可以看到新的环境变量已经被删除。&lt;/p&gt;

&lt;h2 id=&#34;改&#34;&gt;改&lt;/h2&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;创建一个新的工作目录，&lt;code&gt;lab/overlays/u&lt;/code&gt;，本节的内容都会使用这个目录来完成。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;除了 &lt;code&gt;patchesStrategicMerge&lt;/code&gt; 之外，&lt;code&gt;kustomize&lt;/code&gt; 还提供了一些方便快捷的方式能够对特定内容进行修改。&lt;/p&gt;

&lt;h3 id=&#34;修改名字&#34;&gt;修改名字&lt;/h3&gt;

&lt;p&gt;可以用 namePrefix 和 nameSuffix 修改对象的名字，例如我们要给&lt;strong&gt;所有&lt;/strong&gt;名字加上 &lt;code&gt;overlay-u&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kustomization.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../c
namePrefix: overlay-u
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;接下来可以看看结果：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl apply -k overlays/u --dry-run -o yaml | grep -E &amp;quot;^\s+name:&amp;quot;
    name: overlay-u-config-ini
    name: overlay-u-flaskapp
    name: overlay-u-flaskapp
                name: overlay-u-config-ini
          name: flaskapp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;输出内容中，前三个分别是 ConfigMap、Service 以及 Deployment，第四行中对 Configmap 的引用也修改成了新的名字。&lt;/p&gt;

&lt;p&gt;除了修改名字之外，还有以下几个暴力的修改功能：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;命名空间：namespaces&lt;/li&gt;
&lt;li&gt;注解：commonAnnotations&lt;/li&gt;
&lt;li&gt;标签：commonLabels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;说这几个东西比较野蛮的原因是：他们的应用范围是整个 Kustomization，例如下面的定制：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../c
namePrefix: overlay-u
commonLabels:
    auto: label
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;生成之后会发现，从 Service、Deployment、Configmap 一直到 Pod，都会打上新标签。&lt;/p&gt;

&lt;h3 id=&#34;修改镜像&#34;&gt;修改镜像&lt;/h3&gt;

&lt;p&gt;修改镜像也是个常见任务，相对上面的几个暴力修改，镜像的修改相对精确一点——从一种镜像修改为另一种，例如我们把 flaskapp 的镜像更换为 &lt;code&gt;nginx:alpine&lt;/code&gt;：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kustomization.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../c
namePrefix: overlay-u
commonLabels:
    auto: label
images:
- name: dustise/flaskapp
  newName: nginx
  newTag: alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;修改副本数量&#34;&gt;修改副本数量&lt;/h3&gt;

&lt;p&gt;修改副本数量，指定资源名称以及副本数量即可：&lt;/p&gt;

&lt;p&gt;例如如下的 &lt;code&gt;kustomization.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../c
replicas:
- name: flaskapp
  count: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;使用 &lt;code&gt;kustomize build overlays/u&lt;/code&gt;，会看到 Deployment 的该字段已经改为 2。&lt;/p&gt;

&lt;h2 id=&#34;查&#34;&gt;查&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;创建一个新的工作目录，&lt;code&gt;lab/overlays/r&lt;/code&gt;，本节的内容都会使用这个目录来完成。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;前面提到，&lt;code&gt;namePrefix&lt;/code&gt; 修改了 ConfigMap 的名称之后，加载这个 CM 的 Deployment 也会修改引用的名称，然而如果在其它位置，例如命令行参数或者环境变量中引用的服务名称之类，就无法完成修改了。假设我们给 Deployment 中加入一个新的环境变量，叫 &lt;code&gt;deploy&lt;/code&gt;，用如下的 &lt;code&gt;kustomization.yaml&lt;/code&gt; 实现：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;bases:
- ../../base
namePrefix: overlay-r-
patchesStrategicMerge:
- env-patch.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其中引用的 &lt;code&gt;env-patch.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: flaskapp
        env:
        - name: deploy
          value: flaskapp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;kustomize build overlays/r&lt;/code&gt; 渲染出来之后，很明显的 value 已经无法对应：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: overlay-r-flaskapp
...
      - env:
        - name: svc
          value: flaskapp
        - name: version
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在 &lt;code&gt;kustomization.yaml&lt;/code&gt; 中加入 &lt;code&gt;vars&lt;/code&gt;，用一系列条件选择一个对象来进行引用，为变量赋值：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;...
vars:
- name: DEPLOY_NAME
  objref:
    kind: Deployment
    name: flaskapp
    apiVersion: extensions/v1beta1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;把 &lt;code&gt;env-patch.yaml&lt;/code&gt; 中的环境变量定义修改为引用新变量：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;...
        - name: deploy
          value: $(DEPLOY_NAME)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;再次 &lt;code&gt;kustomize build overlays/r&lt;/code&gt;，会看到符合预期的输出内容：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: overlay-r-flaskapp
...
        - name: deploy
          value: overlay-r-flaskapp

&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;命令行&#34;&gt;命令行&lt;/h2&gt;

&lt;p&gt;除了上面说的这些声明式的用法之外，&lt;code&gt;kustomize&lt;/code&gt; 还提供了更为即兴的 &lt;code&gt;edit&lt;/code&gt; 命令，可以进行现场修改，进一步的提高了灵活（混乱）程度，有兴趣的读者可以自行摸索。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Helm 和 Kustomize：不只是含谷量的区别</title>
      <link>/post/helm-vs-kustomize/</link>
      <pubDate>Thu, 08 Aug 2019 00:57:37 +0800</pubDate>
      <guid>/post/helm-vs-kustomize/</guid>
      <description>

&lt;p&gt;Kustomize 问世的时候，我是比较鄙视的——非要造个谷歌的轮子么？不过最近抽出时间熟悉了一下 Kustomize，发现我还是带了有色眼镜。二者功能虽然有所重叠，但是工作思路的差别还是很大的，下面就简单做一点比较，权当引玉之砖。&lt;/p&gt;

&lt;h2 id=&#34;helm&#34;&gt;Helm&lt;/h2&gt;

&lt;p&gt;Helm 是 Kubernetes 中的第一个对应用程序进行管理的支撑工具，经常会拿来同 Yum、apt 等工具进行类比。Helm 由几个不同的组件构成：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLI：客户端工具，有几大功能

&lt;ul&gt;
&lt;li&gt;从 Chart 服务器获取列表、搜索 Chart 项目&lt;/li&gt;
&lt;li&gt;安装 Chart&lt;/li&gt;
&lt;li&gt;构建 Chart&lt;/li&gt;
&lt;li&gt;充当 Chart 服务器&lt;/li&gt;
&lt;li&gt;和 Tiller 协同管理应用生命周期&lt;/li&gt;
&lt;li&gt;渲染 Chart 为 Kubernetes 生成 YAML&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Tiller：需要用特定授权和 API Server 进行通信，Kubernetes 集群内外部署都可以。

&lt;ul&gt;
&lt;li&gt;它是 Helm 的内鬼，负责接收来自 Cli 的指令，完成对集群内应用生命周期的控制。&lt;/li&gt;
&lt;li&gt;3.0 中将取消 Tiller。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Repository：

&lt;ul&gt;
&lt;li&gt;是存储 Helm Chart 的仓库，可以被 Cli 工具缓存、检索，CLI 也可以获取 Chart 进行后续操作。&lt;/li&gt;
&lt;li&gt;和 Tiller 一样，Repository 也不是必要组件，CLI 完全可以仅在本地工作。&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;helm-chart&#34;&gt;Helm Chart&lt;/h3&gt;

&lt;p&gt;Helm 使用 Chart 对应用程序进行描述，它使用 Go Template 对应用部署所需的 YAML 进行抽象，形成应用部署模板，在需要进行部署时，可以编写 yaml 为模板中的变量进行赋值，也可以在 Helm CLI 的命令行中使用 &lt;code&gt;--set name=value&lt;/code&gt; 的方式来对简单变量进行赋值，完成赋值之后，可以选择使用 &lt;code&gt;helm template&lt;/code&gt; 指令将 Chart + Value 的组合渲染成为 YAML 供 &lt;code&gt;kubectl&lt;/code&gt; 使用，也可以使用 &lt;code&gt;helm install&lt;/code&gt; 直接通过 Tiller 进行安装。&lt;/p&gt;

&lt;h3 id=&#34;helm-的特色&#34;&gt;Helm 的特色&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;强大的生命周期管理：有 Tiller 的帮助，可以实现对应用程序实例（Release）的查询、安装、卸载、升级、回滚等复杂操作。&lt;/li&gt;
&lt;li&gt;严格的基础版本管控：Chart 是一种模板，Chart 的用户仅能通过对 &lt;code&gt;values&lt;/code&gt; 的控制来定制应用的部署行为，模板中没有提供变量的位置，是无法在下游直接进行变更的。&lt;/li&gt;
&lt;li&gt;方便的命令行：对于简单变量，可以在部署的同时直接指定内容，方便部署。&lt;/li&gt;
&lt;li&gt;插件和工具：Helm 拥趸众多，提供了不少用于 CICD 或者其它方面辅助功能的插件和工具。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;kustomize&#34;&gt;Kustomize&lt;/h2&gt;

&lt;p&gt;Kustomize 是一个新晋选手，只有一个 CLI 工具，在 Kubernetes 1.14 之后，甚至这唯一的工具也成为 kubectl 的一部分，可以说是很轻量级了。&lt;/p&gt;

&lt;h3 id=&#34;base-overlay&#34;&gt;Base + Overlay&lt;/h3&gt;

&lt;p&gt;在 Kustomize 的文档中明确说明：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;kustomize is a command line tool supporting template-free, structured customization of declarative configuration targetted to k8s-style objects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;它放弃了对模板的要求，改用 Base + Overlay 的方式对应用的原始 YAML 进行&lt;code&gt;派生&lt;/code&gt;。&lt;code&gt;Overlay&lt;/code&gt;，顾名思义，就是覆盖。Kustomize 的 Overlay 可以在 Base 的基础上，通过对 &lt;code&gt;resource&lt;/code&gt;、&lt;code&gt;generator&lt;/code&gt;、&lt;code&gt;transformer&lt;/code&gt; 等的定义，形成新的应用定义，不论 Base
还是 Overlay，都可以通过 &lt;code&gt;kustomize build&lt;/code&gt; 生成有效的 YAML。&lt;/p&gt;

&lt;h3 id=&#34;kustomize-的特色&#34;&gt;Kustomize 的特色&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;功能简单清晰，kubectl 直接支持。&lt;/li&gt;
&lt;li&gt;不考虑派生，仅作为应用的 YAML 组织方式也很有帮助。&lt;/li&gt;
&lt;li&gt;也有自己的插件系统。例如可以用简单的 YAML 定义，使用文件生成 Configmap/Secret。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;比较&#34;&gt;比较&lt;/h2&gt;

&lt;p&gt;Kustomize 自称因为去掉了模板语法，更易使用，对此我保留看法，如果仅就入门使用来看，二者差异并不大。&lt;/p&gt;

&lt;p&gt;Tiller 和 Repository 都并非必须，因此在部署上，Kustomize 的优势也不是很大。&lt;/p&gt;

&lt;p&gt;我认为他们的区别主要在工作流程上：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Helm 的基础流程比较&lt;code&gt;瀑布&lt;/code&gt;：定义 Chart-&amp;gt;填充-&amp;gt;运行，在 Chart 中没有定义的内容是无法更改的；&lt;/li&gt;
&lt;li&gt;Kustomize 的用法比较&lt;code&gt;迭代&lt;/code&gt;：Base 和 Overlay 都是可以独立运作的，增加新对象，或者对编写 Base 时未预料的内容进行变更，都不在话下。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;例如我们定义了一个很基础的应用，由 Deployment + Service 组成，如果后续部署中需要完成两个变更：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;新建 Ingress 对象&lt;/li&gt;
&lt;li&gt;修改镜像地址/名称/TAG&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在 Helm 中需要：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;在 Chart 中加入对 Ingress 的定义&lt;/li&gt;
&lt;li&gt;用变量控制 Ingress 是否进行渲染&lt;/li&gt;
&lt;li&gt;Ingress 模板应该包含特定的主机名、注解等变量&lt;/li&gt;
&lt;li&gt;把镜像也定义成变量&lt;/li&gt;
&lt;li&gt;在 Values.yaml 中对这些变量进行赋值。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;而在 Kustomize 中：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;无需对 Base 进行修改&lt;/li&gt;
&lt;li&gt;直接在新的 Overlay 中写入 Ingress Resource&lt;/li&gt;
&lt;li&gt;使用内置的 &lt;code&gt;image transformer&lt;/code&gt; 替换原有镜像&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;要公开发布一个较为复杂的应用，例如 &lt;code&gt;Istio&lt;/code&gt;，编写良好的 Chart 能给用户很大帮助，用户在缺失一点发挥空间的情况下，通过对 &lt;code&gt;values.yaml&lt;/code&gt; 的阅读，就能对这种复杂的部署产生一个较为深入的认识。&lt;/p&gt;

&lt;p&gt;如果是常见的业务应用，因为不同部署之间的差异不大，但是未必可以提前做好变化限制，用 Kustomize 可能会是一个更好的选择。&lt;/p&gt;

&lt;h2 id=&#34;相关链接&#34;&gt;相关链接&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Helm：&lt;code&gt;https://helm.sh/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Kustomize：&lt;code&gt;https://github.com/kubernetes-sigs/kustomize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Helm 3.0：&lt;code&gt;https://helm.sh/blog/helm-3-preview-pt1/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Helm 工具：&lt;code&gt;https://www.infoq.cn/article/UemPsPu_AlzemkGEqb4Z&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Awesome Helm：&lt;code&gt;https://github.com/cdwv/awesome-helm&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
