前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 Helmfile 解放你的 Helm Chart

使用 Helmfile 解放你的 Helm Chart

原创
作者头像
郭旭东
修改2020-12-24 10:05:48
6.7K0
修改2020-12-24 10:05:48
举报
文章被收录于专栏:云原生工具箱

前言

Helm 作为 Kubernetes 的包管理工具和 CNCF 毕业项目,在业界被广泛使用。但在实际使用场景中的一些需求 helm 并不能很好的满足,需要进行一些修改和适配,如同时部署多个 chart、不同部署环境的区分以及 chart 的版本控制。Helmfile 就是一个能够很好解决这些问题的小工具。

基础介绍

Helmfile 通过 helmfile.yaml 文件帮助用户管理和维护众多 helm chart,其最主要作用是:

  • 集成在 CI/CD 系统中,提高部署的可观测性和可重复性,区分环境,免去各种 --set 造成的困扰。
  • 方便对 helm chart 进行版本控制,如指定版本范围、锁定版本等。
  • 定期同步,避免环境中出现不符合预期的配置。

安装

helmfile 提供了多种安装方式,除了直接在 release 页面下载,还可以通过如下方式安装:

  • macOS (使用 homebrew): brew install helmfile
  • Windows (使用 scoop): scoop install helmfile
  • Archlinux: pacman -S helmfile
  • openSUSE: zypper in helmfile

同时还支持作为容器运行,可以非常方便的集成到 CI/CD 系统中:

代码语言:txt
复制
# helm 2
$ docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.helm:/root/.helm" -v "${PWD}:/wd" --workdir /wd quay.io/roboll/helmfile:v0.135.0 helmfile sync

# helm 3
$ docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.config/helm:/root/.config/helm" -v "${PWD}:/wd" --workdir /wd quay.io/roboll/helmfile:helm3-v0.135.0 helmfile sync

其他依赖

除了安装 helmfile 以外,还需要安装 helmkubectl 以及 helm 插件 helm-diff

helm-diff 安装方式:

代码语言:txt
复制
$ helm plugin install https://github.com/databus23/helm-diff

helmfile.yaml

helmfile.yaml 是 helmfile 的核心文件,其用来声明所有的配置。下面会简要介绍一下,详细内容见官方文档

代码语言:txt
复制
# 声明 repo 配置
repositories:
- name: <repo-name>
  # url: repo url
  # 可以设置基础配置 或 tls 认证
  # certFile: certificate 文件
  # keyFile: key 文件
  # username: 用户名
  # password: 密码

# helm 二进制文件的路径
helmBinary: path/to/helm3

# helm 的一些默认设置,这些配置与 `helm SUBCOMMAND` 相同,可以通过这个配置声明一些,默认的配置
helmDefaults:
  tillerNamespace: tiller-namespace  #dedicated default key for tiller-namespace
  tillerless: false                  #dedicated default key for tillerless
  kubeContext: kube-context          #dedicated default key for kube-context (--kube-context)
  cleanupOnFail: false               #dedicated default key for helm flag --cleanup-on-fail
  # additional and global args passed to helm (default "")
  args:
    - "--set k=v"
  # verify the chart before upgrading (only works with packaged charts not directories) (default false)
  verify: true
  # wait for k8s resources via --wait. (default false)
  wait: true
  # time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks, and waits on pod/pvc/svc/deployment readiness) (default 300)
  timeout: 600
  # performs pods restart for the resource if applicable (default false)
  recreatePods: true
  # forces resource update through delete/recreate if needed (default false)
  force: false
  # when using helm 3.2+, automatically create release namespaces if they do not exist (default true)
  createNamespace: true
  ...

# 为 helmfile 中所有的 release 设置相同的 label,可用于为所有 release 标记相同的版本
commonLabels:
  hello: world

# 设置 release 配置(支持多 release)
releases:
  # 远程 chart 示例(chart 已经上传到 remote 仓库)
  - name: vault                            # name of this release
    namespace: vault                       # target namespace
    createNamespace: true                  # helm 3.2+ automatically create release namespace (default true)
    labels:                                # Arbitrary key value pairs for filtering releases
      foo: bar
    chart: roboll/vault-secret-manager     # the chart being installed to create this release, referenced by `repository/chart` syntax
    version: ~1.24.1                       # the semver of the chart. range constraint is supported
    condition: vault.enabled               # The values lookup key for filtering releases. Corresponds to the boolean value of `vault.enabled`, where `vault` is an arbitrary value
    missingFileHandler: Warn # set to either "Error" or "Warn". "Error" instructs helmfile to fail when unable to find a values or secrets file. When "Warn", it prints the file and continues.
    # Values files used for rendering the chart
    values:
      # Value files passed via --values
      - vault.yaml
      # Inline values, passed via a temporary values file and --values, so that it doesn't suffer from type issues like --set
      - address: https://vault.example.com
      # Go template available in inline values and values files.
      - image:
          # The end result is more or less YAML. So do `quote` to prevent number-like strings from accidentally parsed into numbers!
          # See https://github.com/roboll/helmfile/issues/608
          tag: {{ requiredEnv "IMAGE_TAG" | quote }}
          # Otherwise:
          #   tag: "{{ requiredEnv "IMAGE_TAG" }}"
          #   tag: !!string {{ requiredEnv "IMAGE_TAG" }}
        db:
          username: {{ requiredEnv "DB_USERNAME" }}
          # value taken from environment variable. Quotes are necessary. Will throw an error if the environment variable is not set. $DB_PASSWORD needs to be set in the calling environment ex: export DB_PASSWORD='password1'
          password: {{ requiredEnv "DB_PASSWORD" }}
        proxy:
          # Interpolate environment variable with a fixed string
          domain: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
          scheme: {{ env "SCHEME" | default "https" }}
    # Use `values` whenever possible!
    # `set` translates to helm's `--set key=val`, that is known to suffer from type issues like https://github.com/roboll/helmfile/issues/608
    set:
    # single value loaded from a local file, translates to --set-file foo.config=path/to/file
    - name: foo.config
      file: path/to/file
    # set a single array value in an array, translates to --set bar[0]={1,2}
    - name: bar[0]
      values:
      - 1
      - 2
    # set a templated value
    - name: namespace
      value: {{ .Namespace }}
    # will attempt to decrypt it using helm-secrets plugin
    
  # 本地 chart 示例(chart 保存在本地)
  - name: grafana                            # name of this release
    namespace: another                       # target namespace
    chart: ../my-charts/grafana              # the chart being installed to create this release, referenced by relative path to local helmfile
    values:
    - "../../my-values/grafana/values.yaml"             # Values file (relative path to manifest)
    - ./values/{{ requiredEnv "PLATFORM_ENV" }}/config.yaml # Values file taken from path with environment variable. $PLATFORM_ENV must be set in the calling environment.
    wait: true

# 可以嵌套其他的 helmfiles,支持从本地和远程拉取 helmfile
helmfiles:
- path: path/to/subhelmfile.yaml
  # label 选择器可以过滤需要覆盖的 release
  selectors:
  - name=prometheus
  # 覆盖 value
  values:
  # 使用文件覆盖
  - additional.values.yaml
  # 覆盖单独的 key
  - key1: val1
- # 远程拉取配置
  path: git::https://github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0
# 如果指向不存在路径,则打印告警错误
missingFileHandler: Error

# 多环境管理
environments:
  # 当没有设置 `--environment NAME` 时,使用 default 
  default:
    values:
    # 内容可以是文件路径或者 key:value
    - environments/default/values.yaml
    - myChartVer: 1.0.0-dev
  # "production" 环境,当设置了 `helmfile --environment production sync` 时
  production:
    values:
    - environment/production/values.yaml
    - myChartVer: 1.0.0
    # disable vault release processing
    - vault:
        enabled: false
    ## `secrets.yaml` is decrypted by `helm-secrets` and available via `{{ .Environment.Values.KEY }}`
    secrets:
    - environment/production/secrets.yaml
    # 当占不到 `environments.NAME.values` 时,可以设置为 "Error", "Warn", "Info", "Debug",默认是 "Error"
    missingFileHandler: Error

# 分层管理,可以将所有文件合并,顺序为:environments.yaml < - defaults.yaml < - templates.yaml < - helmfile.yaml
bases:
- environments.yaml
- defaults.yaml
- templates.yaml

# API 功能
apiVersions:
- example/v1

Apply

helmfile apply 是 helmfile 中最常用命令,体验与 kubectl apply 类似,根据 helmfile.yaml 中声明的配置可以一键执行相应的动作,如:添加 repo、安装或更新 release 等。

helmfile.yaml 如下:

代码语言:txt
复制
repositories:
- name: stable
  url: https://charts.helm.sh/stable

releases:
- name: prom-norbac-ubuntu
  namespace: prometheus
  chart: stable/prometheus
  set:
  - name: rbac.create
    value: false

执行 helmfile apply 之后,helmfile 会进行如下操作:

  1. 添加 repositories 中声明的 repo
  2. 运行 helm diff 进行对比
  3. 根据 release中声明的配置,安装或更新 chart

效果如下(由于输出内容过多,这里只节选了部分输出):

代码语言:txt
复制
Adding repo stable https://charts.helm.sh/stable
"stable" has been added to your repositories

Comparing release=prom-norbac-ubuntu, chart=stable/prometheus

...

prometheus, prom-norbac-ubuntu-prometheus-server, ServiceAccount (v1) has been added:
-
+ # Source: prometheus/templates/rbac/server-serviceaccount.yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+   labels:
+     component: "server"
+     app: prometheus
+     release: prom-norbac-ubuntu
+     chart: prometheus-11.12.1
+     heritage: Helm
+   name: prom-norbac-ubuntu-prometheus-server
+   namespace: prometheus
+   annotations:
+     {}

Upgrading release=prom-norbac-ubuntu, chart=stable/prometheus
Release "prom-norbac-ubuntu" does not exist. Installing it now.
NAME: prom-norbac-ubuntu
LAST DEPLOYED: Wed Dec 23 11:23:31 2020
NAMESPACE: prometheus
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:

...

Listing releases matching ^prom-norbac-ubuntu$
prom-norbac-ubuntu	prometheus	1       	2020-12-23 11:23:31.779328 +0800 CST	deployed	prometheus-11.12.1	2.20.1


UPDATED RELEASES:
NAME                 CHART               VERSION
prom-norbac-ubuntu   stable/prometheus   11.12.1

模板化

helmfile 和 helm templete 一样可以使用 Go templates,同时还有一个特殊的功能 requiredEnv,该函数允许声明模板渲染所需的特定环境变量,如果环境变量未设置或为空,则渲染失败返回错误信息。

使用环境变量

可以在 helmfile 中直接使用环境变量,使用方式如下:

代码语言:txt
复制
repositories:
- name: your-private-git-repo-hosted-charts
  url: https://{{ requiredEnv "GITHUB_TOKEN"}}@raw.githubusercontent.com/kmzfs/helm-repo-in-github/master/
releases:
  - name: {{ requiredEnv "NAME" }}-vault
    namespace: {{ requiredEnv "NAME" }}
    chart: roboll/vault-secret-manager
    values:
      - db:
          username: {{ requiredEnv "DB_USERNAME" }}
          password: {{ requiredEnv "DB_PASSWORD" }}
    set:
      - name: proxy.domain
        value: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
      - name: proxy.scheme
        value: {{ env "SCHEME" | default "https" }}

进阶实践

helm 还有一些进阶使用方式,如:版本控制、环境区分、hook、交互式操作、集成 kustomize 等。这里简单介绍几种,更多功能请看官方文档

版本控制

helmfile 支持 Semver 2.0 的版本号,可以锁定主版本,防止误升级导致的错误。

代码语言:txt
复制
releases:
  - name: vault                            
    namespace: vault                      
    version: ~1.24.1   # 限制版本 >=1.24.1 && < 1.25.0

同时还能通过 helmfile deps 命令生成 lock 文件,在 CD 时,除非修改 lock 文件,否无法发布新版本。helmfile.lock 内容如下:

代码语言:txt
复制
version: v0.135.0
dependencies:
- name: prometheus
  repository: https://charts.helm.sh/stable
  version: 11.12.1
digest: sha256:a5158f1361f2bbc4e73a80a22dd92b44538bdebeb2419658c36e31aa603b05fd
generated: "2020-12-23T16:26:57.42503+08:00"

当需要更新时,再次执行 helmfile deps 即可。

区分环境

这也是个使用率较高的功能,使用 environments 配置·。如果不指定 --environment NAME 参数,默认使用 default 配置。

这里假设有三个文件,helmfile.yamlproduction.yamldefault.yaml

代码语言:txt
复制
# helmfile.yaml
environments:
  default:
    values:
    - default.yaml
  production:
    values:
    - production.yaml 

releases:
- name: myapp-{{ .Values.releaseName }} # 根据环境名,可能是 `dev` 或 `prod`
  values:
  - url: { .Values.domain }} # 根据环境名,可能是 `dev.example.com` 或 `prod.example.com`
{{ if eq .Environment.Name "production" }} # 使用 Go template 的
      - values/production-specified-values.yaml
{{ end }}
代码语言:txt
复制
# production.yaml
domain: prod.example.com
releaseName: prod
代码语言:txt
复制
# default.yaml
domain: dev.example.com
releaseName: dev

在执行 helmfile 时,只需使用 --environment 指定需要安装的环境:

代码语言:txt
复制
$ helmfile --environment production apply

Hook

Helmfile hook 是一个每次发布的扩展点,它由以下部分组成:

  • events
  • command
  • args
  • showlogs

helmfile 在运行时,会触发各种事件,一旦事件触发,相关的 hook 就会被执行,目前支持的如下事件:

  • prepare
  • presync
  • preuninstall
  • postuninstall
  • postsync
  • cleanup

下面这个示例,会打印事件触发时的的上下文信息。

代码语言:txt
复制
environments:
  default:
  prod:

releases:
- name: myapp
  chart: mychart
  # *snip*
  hooks:
  - events: ["prepare", "cleanup"]
    showlogs: true
    command: "echo"
    args: ["{{`{{.Environment.Name}}`}}", "{{`{{.Release.Name}}`}}", "{{`{{.HelmfileCommand}}`}}\
"]

执行命令,可以看到 command 执行成功:

代码语言:txt
复制
$ helmfile -e prod sync
helmfile.yaml: basePath=.

hook[prepare] logs | prod myapp sync

这也是个十分好用的功能,可以为不同的事件配置不同的 hook,这样在 CD 出现问题时,通过 hook 可以第一时间收到通知,并快速定位问题。

结语

Helmfile 是一个很不错 Helm 生态工具,很大程度上弥补了 Helm 的不足。提高部署的可观测性和可重复性,提高了效率,最终实现 Release AS Code。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 基础介绍
    • 安装
      • 其他依赖
        • helmfile.yaml
          • Apply
            • 模板化
              • 使用环境变量
              • 进阶实践
                • 版本控制
                  • 区分环境
                    • Hook
                    • 结语
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档