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启动:
- 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。
- 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。
- 开了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和权限。
- 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
注意:这里的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对象
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
- 更多高级用法
从其他File中引用,在chart文件里建subchart等功能请见helm官方chart developing文档(https://helm.sh/docs/chart_template_guide/#the-chart-template-developer-s-guide)。