Helm知识总结

一、Helm介绍

在Kubernetes中部署容器云应用(容器或微服务编排)是一项有挑战性的工作,Helm就是为了简化在Kubernetes中安装部署容器云应用的一个客户端工具。通过Helm能够帮助开发者定义、安装和升级Kubernetes中的容器云应用。同时,也可以通过Helm进行容器云应用的分享。

Helm架构图:

Helm有三个重要概念:

  • chart:包含了创建Kubernetes的一个应用实例的必要信息
  • config:包含了应用发布配置信息
  • release:是一个chart及其配置的一个运行实例

二、Helm client/Tiller server 的安装

  • Helm 包下载:

wget  https://storage.googleapis.com/kubernetes-helm/helm-v2.8.2-linux-amd64.tar.gz
tar xzf helm-v2.8.2-linux-amd64.tar.gz
mv linux-amd64/helm /usr/local/bin
  • Helm 配置:

由于Tiller server需要跟K8S api server通信,所以Tiller需要知道K8S的信息,默认Tiller是在目录 ~/.kube/或者读 KUBECONFIG 这个环境变量目录底下的配置文件来获取k8s集群信息.

[apps@gd13-001-noah-helm-proxy-api-prod-342295-0 ~]$ cat /apps/conf/helm/kubeconfig
apiVersion: v1
clusters:
- cluster:
    server: http://10.199.175.65:8080
  name: k8s
contexts:
- context:
    cluster: k8s
    user: ""
  name: k8s
current-context: k8s
kind: Config
preferences: {}
users: []

如果Tiller连接的集群开启了RBAC,那么连接K8S api server时需要使用Https的方式,请参考以 > https://www.cnblogs.com/ericte/p/13692545.html

[apps@gd13-001-noah-helm-proxy-api-prod-342295-0 logs]$ cat /apps/conf/helm/kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS.....LS0tCg==
    server: https://10.199.175.65:6443
  name: k8s
contexts:
- context:
    cluster: k8s
    user: noah-sa
  name: k8s
current-context: k8s
kind: Config
preferences: {}
users:
- name: noah-sa
  user:
    as-user-extra: {}
    token: eyJhbG....wg4Pc
  • Tiller启动:

  1. Easy In-Cluster Installation
    helm init
    可选参数:
    --kube-context
    --tiller-image
    --tiller-namespace
    --service-account

如果没有任何的参数指定,那么Helm将会在k8s集群的namespace=kube-system以service的方式创建一个Tiller server容器,镜像为默认的Tiller镜像(image: gcr.io/kubernetes-helm/tiller:v2.13.1),由于大多数时候我们是在线拿不到镜像,原因你懂的,所以这一步很可能会失败;所以可以提前拿到Tiller image并放在自己的集群上,然后启动时带上--tiller-image来指定image文件;亦或者可以采用以下方式启动Tiller server。

  1. Running Tiller Locally
    在本地启动一个Tiller 进程,默认Tiller GRPC会监听在 localhost:44134上,Probes(healthcheck)会监听在localhost:44135。helm client在不指定--host的情况下按默认方式去找Tiller server(默认方式为连接Tiller server的 service cluster IP),所以用local的方式启动的话一定要告诉helm client Tiller server的地址,一种是在命令行中用--host的方式指定,另一种就是设置环境变量$HELM_HOME (例如: export HELM_HOME=localhost:44134)。
$ bin/tiller
Tiller running on :44134

常用可选参数:

-listen string
      address:port to listen on (default ":44134")
-log_backtrace_at value
      when logging hits line file:N, emit a stack trace
-log_dir string
      If non-empty, write log files in this directory
-log_file string
      If non-empty, use this log file
-logtostderr
      log to standard error instead of files
-tls
      enable TLS
-tls-ca-cert string
      trust certificates signed by this CA (default "ca.crt")
-tls-cert string
      path to TLS certificate file (default "tls.crt")
-tls-key string
      path to TLS private key file (default "tls.key")
-tls-verify
      enable TLS and verify remote certificate
-trace
      enable rpc tracing
-v value
      log level for V logs

由于是用local方式启动Tiller,~/.helm目录是不会被helm主动创建(helm init命令会帮助创建该目录),于是为了能够正常使用helm命令,我们必须提前创建好helm的工作目录。

[apps@gd13-001-noah-helm-proxy-api-prod-342295-0 templates]$ /apps/svr/helm/bin/helm init --client-only
Creating localhost:44134
Creating localhost:44134/repository
Creating localhost:44134/repository/cache
Creating localhost:44134/repository/local
Creating localhost:44134/plugins
Creating localhost:44134/starters
Creating localhost:44134/cache/archive
Creating localhost:44134/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com

但由于网络是无法连通 https://kubernetes-charts.storage.googleapis.com,这一步会超时失败,尽管失败后最后helm的工作目录还是会创建成功;如果想快速让这一步通过则需要指定一个stable-repo-url (这一步noah是在moana_extend_start里做的)。

例如: /apps/svr/helm/bin/helm init --client-only --stable-repo-url http://10.199.175.65:8879

Tiller默认是将所有的资源默认是放在configmap(default namespace=kube-system),但如果Tiller是以容器发布且namespace不为kube-system,那么所有数据将存在容器的namespace里的configmap,可以通过环境变量 TILLER_NAMESPACE来更改数据存放namespace。

  1. 开了RBAC的集群启动方式
    如果k8s集群开通了RBAC,那么必须提前给Tiller给与一个role,所以需要在k8s上提前设置好clusterRole和clusterRoleBinding;并同时还得带上TLS证书。
    在RBAC集群内需要提前配置好serviceAccount并绑定上相应的clusterRole。
    ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system

ClusterRoleBinding:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system

或者用local方式启动tiller的话那就指定在KUBECONFIG文件里指定证书文件,tiller会取证书里的O 字段做用户为role。
openssl x509 -in /apps/conf/ssl/admin.pem -text
C=CN, ST=BeiJing, L=BeiJing, O=system:masters, OU=System, CN=kubernetes-core
在 kubectl get clusterrolebinding --all-namespaces -oyaml | grep system:masters 就能找到该用户所绑定的role和权限。

  1. Chart repo启动:
    在没有设置–repo的时候去做helm install,默认helm会去本地的 ~/.helm/repository/local目录读取index.yaml文件并寻找Chart package,从而进行helm install来发布release;但是如果是使用了远程repo的方式来存储Chart package的话Helm会先去repo拉取index.html文件和对应的package放在本地目录/root/.helm/repository/local下。
  • 开发方式启动Chart repo:
    Helm serve命令会启动一个本地的http web server。默认的Chart package目录为~/.helm/repository/local,
[root@qa-k8s-1-master helm-test]# helm serve --address 10.199.175.65:8879
Regenerating index. This may take a moment.
Now serving you on 10.199.175.65:8879
Options:
    --address string     address to listen on (default "127.0.0.1:8879")
    -h, --help               help for serve
    --repo-path string   local directory path from which to serve charts
    --url string         external URL of chart repository
  • Chart museum:
    ChartMuseum为一个开源的用来管理Chart包的Go语言程序,通过后端各种云存储来实现对Chart的管理,功能上包括Chart包的上传,下载,删除,list,listAll和describe chart

支持的后端云存储包括: Google Cloud Storage, Amazon S3, Microsoft Azure Blob Storage, Alibaba Cloud OSS Storage, Openstack Object Storage, Oracle Cloud Infrastructure Object Storage, and Baidu Cloud BOS Storage.

museum启动:
chartmuseum --debug --port=8080 --storage="amazon" --storage-amazon-bucket="my-s3-bucket" --storage-amazon-prefix="" --storage-amazon-region="us-east-1"

并同时设置云存储的Account和Key:
export AWS_ACCESS_KEY_ID=""
export AWS_SECRET_ACCESS_KEY=""

更多云存储厂商配置请看:https://github.com/helm/chartmuseum

Museum API:

GET /index.yaml - retrieved when you run helm repo add chartmuseum http://localhost:8080/
GET /charts/mychart-0.1.0.tgz - retrieved when you run helm install chartmuseum/mychart
GET /charts/mychart-0.1.0.tgz.prov - retrieved when you run helm install with the --verify flag
POST /api/charts - upload a new chart version
POST /api/prov - upload a new provenance file
DELETE /api/charts/<name>/<version> - delete a chart version (and corresponding provenance file)
GET /api/charts - list all charts
GET /api/charts/<name> - list all versions of a chart
GET /api/charts/<name>/<version> - describe a chart version
GET / - HTML welcome page
GET /health - returns 200 OK

三、Helm 命令

  • helm create
    在当前目录创建一个mychart目录。
    Chart.yaml — Chart名称、描述和版本号
    Values.yaml — Template中各变量的默认值
    Template folder — 存放Chart的template文件,Tiller server会根据template里面的文件对里面的变量值进行渲染生成最后供k8s可用的resource yaml文件。
    deployment.yaml/service.yaml/ingress.yaml — k8s resouce文件,里面有大量的chart语法
    _helpers.tpl — 存放chart语法的变量值
    NOTES.txt — 类似README,以供他人了解该chart的用途和介绍,纯文本文件,会在helm install时候作为output输出给用户看。
[apps@gd13-001-noah-helm-proxy-api-prod-342295-0 ~]$ tree mychart/
mychart/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml
3 directories, 8 files
  • helm package
    在当前同名目录生成tgz格式压缩包,同时将压缩包放到/root/.helm/repository/local并同时更新index.yaml文件。

  • helm install
    利用已有的chart发布一个release

helm install --name --repo --namespace --host --version --set-string

注意:这里的releaseName和namespace不一定会是最后在k8s上面创建的resource里的名称和namespace,只有在chart里引用了这里的namespace才行,不然release和k8s的namespace会有不一致的情况。

小技巧:如果加上" --dry-run --debug ", Tiller server会渲染template但是不会发送给k8s创建resource,用这种方法可以检查chart文件是否正确。

  • helm upgrade
    升级某个已发布的release,一般是通过--set-string来更新镜像或更新replicasCount等。

helm upgrade <releaseName> <chartName> --repo <repoName> --namespace <nameSpace> --host <Tiller server> --version <chart Version> --reset-values|--reuse-values --set-string <ValuesStringList>

  • helm rollback
    回滚release至某个版本。

helm rollback $releaseName $revision --host localhost:44134 --force

  • helm delete
    删除某个处于DEPLOYED状态的release;如果想从release list中彻底清除则需要加上 --purge。

helm delete $releaseName --host localhost:44134

  • helm status
    查看某个release的状态,可以查看该release发布的所有k8s resource的状态。
[apps@gd13-001-noah-helm-proxy-api-prod-342295-0 ~]$ /apps/svr/helm/bin/helm status noah-php-demo
LAST DEPLOYED: Tue Apr 30 18:52:03 2019
NAMESPACE: eric
STATUS: DEPLOYED
RESOURCES:
==> v1/Deployment
NAME                     READY  UP-TO-DATE  AVAILABLE  AGE
noah-php-demo-helm-test  3/3    3           3          22h
==> v1/Pod(related)
NAME                                     READY  STATUS   RESTARTS  AGE
noah-php-demo-helm-test-546958457-bb98x  1/1    Running  0         22h
noah-php-demo-helm-test-546958457-bsl9z  1/1    Running  0         22h
noah-php-demo-helm-test-546958457-k65zz  1/1    Running  0         22h
  • helm list
    list出release列表;可按status,date,chart name分别列出所有的release

helm list --output json --host localhost:44134 --all --offset xxx --max 10

Flags:
  -a, --all                   show all releases, not just the ones marked DEPLOYED
  -c, --chart-name            sort by chart name
      --col-width uint        specifies the max column width of output (default 60)
  -d, --date                  sort by release date
      --deleted               show deleted releases
      --deleting              show releases that are currently being deleted
      --deployed              show deployed releases. If no other is specified, this will be automatically enabled
      --failed                show failed releases
  -m, --max int               maximum number of releases to fetch (default 256)
      --namespace string      show releases within a specific namespace
  -o, --offset string         next release name in the list, used to offset from start value
      --output string         output the specified format (json or yaml)
      --pending               show pending releases
  -r, --reverse               reverse the sort order
  • helm lint
    检查chart文件可能存在的问题,跟helm install --name --dry-run --debug效果差不多。
    helm lint <chartName>
  • helm history
    列出某个release所有的历史版本

/apps/svr/helm/bin/helm history noah-php-demo --output table

[apps@gd13-001-noah-helm-proxy-api-prod-342295-0 ~]$ /apps/svr/helm/bin/helm history noah-php-demo --output table
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION
1               Tue Apr 30 16:44:15 2019        SUPERSEDED      helm-test-0.1.5 Install complete
2               Tue Apr 30 18:00:50 2019        SUPERSEDED      helm-test-0.1.5 Upgrade complete
3               Tue Apr 30 18:41:36 2019        SUPERSEDED      helm-test-0.1.5 Rollback to 1
4               Tue Apr 30 18:47:38 2019        SUPERSEDED      helm-test-0.1.5 Upgrade complete
5               Tue Apr 30 18:49:58 2019        SUPERSEDED      helm-test-0.1.5 Upgrade complete
6               Tue Apr 30 18:52:03 2019        DEPLOYED        helm-test-0.1.5 Upgrade complete
  • helm search
    在所有的helm list中找出想找的release,关键字一般为release name。

helm search <keyword>


更多Helm命令请查询Helm官方文档(https://helm.sh/docs/helm/#helm)。


四、Chart语法

在前面我们已经简单介绍了Chart的文件结构,包括Chart.yaml,values.yaml,templates/deployment.yaml,templates/_helpers.tpl,templates/NOTES.txt。

大家都知道template文件里会引用很多变量,而这些变量值来自何处,该用何种语法来写才能达到我们想要的引用效果,下面我们一起来看看如何写一份template文件。

以下是一份最简单的configmap文件,里面的configmap的名称引用了{{ .Release.Name }}-configmap。注意{{ 、}}两边的空格和点 " . "

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  • Build-in 对象
    注意所有的build-in对象首字母都必须大写(Release, Values, Chart等)。
    • Release对象
      从release里拿到release的信息并渲染template文件生成k8s resource文件。
Release.Name: The release name
Release.Time: The time of the release
Release.Namespace: The namespace to be released into (if the manifest doesn’t override)
Release.Service: The name of the releasing service (always Tiller).
Release.Revision: The revision number of this release. It begins at 1 and is incremented for each helm upgrade.
Release.IsUpgrade: This is set to true if the current operation is an upgrade or rollback.
Release.IsInstall: This is set to true if the current operation is an install.
  • Values对象
    从values.yaml里读取对应的key并渲染,{{ .Values.replicasCount }} 、 {{ .Values.image.imageName }}
Values.yaml
replicasCount: 1
business_domain: noah-php-demo.vip.vip.com
namespace: eric
name: noah-php-demo-helm-test
image:
  imageRepo: vipdocker-f9nub.vclound.com/citest
  imageName: 1.0.0_1243_b4a48dd1bf153d5fe62397566bd34e5d1d64fe01
  • Chart对象
    从Chart.yaml文件里引用Chart name和Version。 {{ .Chart.name}} \ {{ .Chart.version }}

  • Capabilities
    获取k8s cluster info

Capabilities
Capabilities.APIVersions is a set of versions.
Capabilities.APIVersions.Has $version indicates whether a version (batch/v1) is enabled on the cluster.
Capabilities.KubeVersion provides a way to look up the Kubernetes version. It has the following values: Major, Minor, GitVersion, GitCommit, GitTreeState, BuildDate, GoVersion, Compiler, and Platform.
Capabilities.TillerVersion provides a way to look up the Tiller version. It has the following values: SemVer, GitCommit, and GitTreeState.
  • 删除某个key值
    只需要在helm install/upgrade 时将某个key值设成null。
    helm install stable/drupal --set image=my-registry/drupal:0.1.0 --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] --set livenessProbe.httpGet=null
    以上命令会更改image,同时将liveness probe由原来的http get改成cat docroot/CHANGELOG.txt来判断。

  • Function/Pipeline
    函数/管道,跟shell命令中的管道是一样的作用,通过一些命令来实现对输出进行格式化,比如 {{ .Values.favorite.food | upper | quote }},会将values 文件里的food值pizza用upper函数全部转成大写PIZZA。

常用的一些函数/工具有:
quote : 引用,一般不做任何事,直接原样输出。
upper : 小写转大写 {{ .Values.favorite.food | upper | quote }}
repeat 5 : 重复5次。{{ .Values.favorite.drink | repeat 5 | quote }}
title: 将首字母大写
nindent 2:缩进2个字母,用于yaml文件格式化
b64enc:转换成base-64
now:当前时间
htmlDate: 格式化时间为2016-11-02
default: default函数,设置默认值,{{ .Values.favorite.drink | default "tea" | quote }},如果vaules文件里不存在drink值,将采用默认值 “ tea ”。

  • 操作表达式函数
    eq,ne,lt,gt,and,or,not,跟shell中的含义差不多,结果返回一个boolean值(true/false)。
eq:相等
ne:不等
lt:小于
gt:大于
and :是否存在,存在则为true,否则为false
or : 不懂啥意思........ (Eric)
not: 非
  • Flow control
    • if/else
{{ if PIPELINE }}
  # Do something
{{ else if OTHER PIPELINE }}
  # Do something else
{{ else }}
  # Default case
{{ end }}

例子:
{{ if and .Values.favorite.drink (eq .Values.favorite.drink "coffee") }}mug: true{{ end }},表达式含义为当 .Values.favorite.drinkc存在并且等于“coffee时”,在template里加入key值mug: true。

注意: 上面的例子是将一条语句放在一行里处理,如果需要将上面的语句进行格式化显得更好看,就必须要注意由此而带来的空格行。

{{if and .Values.favorite.drink (eq .Values.favorite.drink "coffee")}}
  mug: true
{{end}}

此时渲染时就会发现报错并且mug: true前后多出两个空白行,正确处理方式为在大括号内加入一个 “ - ”,那么渲染时将会跳过该行。

{{- if and .Values.favorite.drink (eq .Values.favorite.drink "coffee")}}
  mug: true
{{- end}}
  • with
    利用with函数来更改范围,如果我们一直在values.yaml里取值,我们是不是一直要加上 ".Values.favorite"前缀给每一个值,为了能简化这个步骤我们引入了with来处理相对路径和绝对路径。下面的例子就是在前面设置了scope为 .Values.favorite, 那么在 end 之前的左右值都会在 .Values.favorite 里取得所有值。
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
{{- end }}
  • range
    foreach操作,以下例子就是从 Values.pizzaToppings里顺序取出所有值并将首字母大写。" toppings: |- "里的 " |- " 在yaml文件里表示有多行string值。range也可以用于map,dict,list,tuples等。
  toppings: |-
    {{- range .Values.pizzaToppings }}
    - {{ . | title | quote }}
    {{- end }}
  
渲染结果:
  toppings: |-
    - "Mushrooms"
    - "Cheese"
    - "Peppers"
    - "Onions"
  
另外一种用法:
  sizes: |-
    {{- range tuple "small" "medium" "large" }}
    - {{ . }}
    {{- end }}
  
渲染结果:
  sizes: |-
    - small
    - medium
    - large
  • 变量
    我们当然也可以在template文件里定义变量供文件后面使用
  {{- $relname := .Release.Name -}}
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  release: {{ $relname }}
  {{- end }}
  
或可以:
  toppings: |-
    {{- range $index, $topping := .Values.pizzaToppings }}
      {{ $index }}: {{ $topping }}
    {{- end }}
  • Named templates
    一般是以下划线 _ 开头和以tpl为后缀作为我们的文件,类似于_helpers,tpl
我们在_helpers,tpl里定义了一个mychart.labels
{{/* Generate basic labels */}}
{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
{{- end }}
  
在template里我们就可以直接引用
metadata:
  name: {{ .Release.Name }}-configmap
  {{- template "mychart.labels" }}
  
渲染后的结果:
metadata:
  name: running-panda-configmap
  labels:
    generator: helm
    date: 2016-11-02
posted @ 2020-10-19 15:31  无知是恶  阅读(1628)  评论(0编辑  收藏  举报