赞
踩
目前基本的K8s部署方式需要创建yaml文件,文件内容包括deployment、Service、Ingress等;
这种方式只适用于单一或者多个创建,再多就不适用了(多个yaml文件就会造成管理困难)。
helm通过打包的方式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用的部署和管理。
需要安装 Helm 3.0 以上版本,因为 3.0 版本以后,Helm 不再需要在集群里安装 tiller 服务端,可以直接将安装历史记录在 ConfigMap 资源中。
Helm本质就是让k8s的应用管理(Deployment、Service等)可配置,能动态生成。通过动态生成K8S资源清单文件(deployment.yaml、service.yaml)。然后kubectl自动调用K8S资源部署。
对于K8s来说,应用资源配置可以定义为K8s API对象,包括Deployment,Namespace,Service, PV(Persistent Volumes)和PVC(PersistentVolumeClaims)等等。通常一个应用的部署会涉及很多资源的共同协作,用户会定义这些API对象到一系列Yaml文件中,然后通过kubectl来逐一进行部署。
Helm是官方提供类似于YUM的包管理,是部署环境的流程封装,Helm有三个重要的概念:chart、release和Repository。
Helm:Helm 是一个命令行下的客户端工具。主要用于 Kubernetes 应用程序 Chart 的创建、打包、发布以及创建和管理本地和远程的 Chart 仓库。
Tiller:Tiller 是 Helm 的服务端,部署在 Kubernetes 集群中。Tiller 用于接收 Helm 的请求,并根据 Chart 生成 Kubernetes 的部署文件( Helm 称为 Release ),然后提交给 Kubernetes 创建应用。Tiller 还提供了 Release 的升级、删除、回滚等一系列功能。
Chart:Helm 的软件包,采用 TAR 格式。类似于 APT 的 DEB 包或者 YUM 的 RPM 包,其包含了一组定义 Kubernetes 资源相关的 YAML 文件。Chart有特定的文件目录结构,如果开发者想自定义一个新的 Chart,只需要使用Helm create命令生成一个目录结构即可进行开发。
Repoistory:Helm 的软件仓库,Repository 本质上是一个 Web 服务器,该服务器保存了一系列的 Chart 软件包以供用户下载,并且提供了一个该 Repository 的 Chart 包的清单文件以供查询。Helm 可以同时管理多个不同的 Repository, 官方仓库的地址是:https://hub.helm.sh。
Release:使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release。
Helm从指定的目录或者tgz文件中解析出Chart结构信息
Helm将指定的Chart结构和Values信息通过gRPC传递给Tiller
Tiller根据Chart和Values生成一个Release
Tiller将Release发送给Kubernetes用于生成Release
Helm从指定的目录或者tgz文件中解析出Chart结构信息
Helm将要更新的Release的名称和Chart结构,Values信息传递给Tiller
Tiller生成Release并更新指定名称的Release的History
Tiller将Release发送给Kubernetes用于更新Release
Helm将要回滚的Release的名称传递给Tiller
Tiller根据Release的名称查找History
Tiller从History中获取上一个Release
Tiller将上一个Release发送给Kubernetes用于替换当前Release
$: helm search repo mysql
如果找不到相应的资源,可以直接 Google 相应的资源。所谓的 repo
其实就是一个简单的 Helm Charts 的索引。
$: helm repo add jaegertracing https://jaegertracing.github.io/helm-charts
$: helm repo list
找到需要的资源后,在部署之前,需要自行检查资源的默认配置是否满足要求,如果不满足的话还需要进行自定义设置。完成自定义设置后,再部署上线。具体过程如下:
- # 拉取 mysql helm charts 到本地目录
- $: helm pull bitnami/mysql --untar
-
- # 修改定义配置即可
- $: vim mysql/values.yaml
-
- # 更新或安装
- $: helm upgrade --install --namespace=[YOUR NAMESPACE] --atomic --history-max 3 mysql-demo ./mysql/ --values ./mysql/values.yaml
- # 创建一个新的 Helm Charts, 负责管理所有外部资源
- $: helm create external-services
默认创建的 Helm Chart,创建了很多功能模板,可以根据需要自行取舍。对于外部基础设施而言,只需要定义相应的 Service 资源即可,其他没有必要的资源模板均可以直接删除。以阿里 RDS 资源为例, 删除 external-services/templates
下无关的资源模板。直接定义一个 mysql.yaml
模板即可
- apiVersion: v1
- kind: Service
- metadata:
- name: mysql
- spec:
- externalName: {{.Values.mysql.address}}
- sessionAffinity: None
- type: ExternalName
清空 external-services/values.yaml
无关配置,提供一个 mysql.address
设置即可。
通过一个专门的 Helm charts 进行管理。
- # 创建一个新的 Helm Charts, 负责管理集群配置
- $: helm create settings
删除无关的资源模板。开始添加集群配置。通常而言,集群配置也就以下几种配置类型:
以上配置,在 K8S 集群中,可以通过 Secret 资源和 ConfigMap 资源进行配置。
证书类配置,主要是将证书文件自动化配置到集群中,可以通过 Helm 提供模板函数 .Files.Get
读取文件内容. 以常见的域名证书为例:
- apiVersion: v1
- data:
- tls.crt: "{{ .Files.Get "files/example.com.pem" | b64enc }}"
- tls.key: "{{ .Files.Get "files/example.com.key" | b64enc }}"
- kind: Secret
- metadata:
- name: www-example-com-tls
- type: IngressTLS
将证书文件存放到 settings/files
子目录下即可。
密码类配置同样非常简单,如:
- apiVersion: v1
- data:
- ACCESS: {{ .Values.demo.access | b64enc }}
- SECRET: {{ .Values.demo.secret | b64enc }}
- kind: Secret
- metadata:
- name: demo-secret
- type: Opaque
通过将具体的密码信息设置在 settings/values.yaml
即可。
为了让集群在发布服务时,可以取得相应的服务容器镜像,还需要提供服务容器镜像服务器的认证信息。通常,镜像服务器的认证信息可以通过命令行创建。如果需要固化存储,在将命令行创建的认证信息资源下载到本地保存即可。
- # 可以通过命令帮助查询如何创建一个镜像服务的认证信息
- $: kubectl create secret docker-registry -h
通用服务配置,通常是一组业务服务可共用的配置,敏感度不高,则可以通过 ConfigMap 资源的形式进行配置。
- apiVersion: v1
- kind: ConfigMap
- metadata:
- name: your-config
- data:
- [yourKey1]: {{.values.yourValue1}}
- [yourKey2]: {{.values.yourValue2}}
- [yourKey3]: {{.values.yourValue3}}
非常简单。
完成以上各类配置后,直接在 settings
中统一管理,就非常清楚。
业务服务不同于配置,类似与自建基础设施服务,通常需要提供的部署资源可能包括:
所以,业务服务的资源定义类型就会比较多。简单列一下常规服务的配置:
- apiVersion: apps/v1
- kind: StatefulSet
- metadata:
- name: demo
- labels:
- app: demo
- spec:
- serviceName: demo
- replicas: {{ .Values.deployment.replicaCount }}
- selector:
- matchLabels:
- app: demo
- template:
- metadata:
- annotations:
- timstamp: "{{ date "20060102150405" .Release.Time }}"
- labels:
- app: demo
- spec:
- {{- with .Values.imagePullSecrets }}
- imagePullSecrets:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- containers:
- - name: demo
- env:
- - name: DEMO_CONFIG
- valueFrom:
- configMapKeyRef:
- key: CONFIG
- name: demo-config
- - name: DEMO_SECRET
- valueFrom:
- secretKeyRef:
- key: SECRET
- name: demo-secret
- ports:
- - name: http
- containerPort: 8080
- image: "{{ .Values.deployment.image.name }}:{{ .Values.deployment.image.tag }}"
- imagePullPolicy: {{ .Values.deployment.image.imagePullPolicy }}
- command: ["demo", "http"]
提供的 values.yaml
配置:
- deployment:
- replicaCount: 1
- image:
- name: "your.image.registry/group/image.name"
- tag: latest
- imagePullPolicy: Always
-
- imagePullSecrets:
- - name: "image-pull-secret-1"
- - name: "image-pull-secret-2"
- apiVersion: v1
- kind: Service
- metadata:
- name: demo
- labels:
- app: demo
- spec:
- type: ClusterIP
- ports:
- - name: demo
- port: 80
- targetPort: http
- selector:
- app: demo
- apiVersion: networking.k8s.io/v1
- kind: Ingress
- metadata:
- name: demo
- spec:
- tls:
- - hosts:
- - {{.Values.ingress.host.name}}
- secretName: {{.Values.ingress.tls.secretName}}
- rules:
- - host: {{.Values.ingress.host.name}}
- http:
- paths:
- - pathType: Prefix
- path: /v1/api/demo
- backend:
- service:
- name: demo
- port:
- number: 80
部署到kubernetes
在mychart目录下执行下面的命令将nginx部署到kubernetes集群上。
helm install .
NAME: eating-hound
LAST DEPLOYED: Wed Oct 25 14:58:15 2017
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
eating-hound-mychart 10.254.135.68 <none> 80/TCP 0s
==> extensions/v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
eating-hound-mychart 1 1 1 0 0s
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app=eating-hound-mychart" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
现在nginx已经部署到kubernetes集群上,本地执行提示中的命令在本地主机上访问到nginx实例。
export POD_NAME=$(kubectl get pods --namespace default -l "app=eating-hound-mychart" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
在本地访问http://127.0.0.1:8080即可访问到nginx。
查看部署的relaese
$ helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
eating-hound 1 Wed Oct 25 14:58:15 2017 DEPLOYED mychart-0.1.0 default
删除部署的release
$ helm delete eating-hound
release "eating-hound" deleted
打包分享
我们可以修改Chart.yaml中的helm chart配置信息,然后使用下列命令将chart打包成一个压缩文件。
helm package .
打包出mychart-0.1.0.tgz文件。
将应用发布到 Repository
虽然我们已经打包了 Chart 并发布到了 Helm 的本地目录中,但通过 helm search 命令查找,并不能找不到刚才生成的 mychart包。
$ helm search mychart
No results found
这是因为 Repository 目录中的 Chart 包还没有被 Helm 管理。通过 helm repo list 命令可以看到目前 Helm 中已配置的 Repository 的信息。
$ helm repo list
NAME URL
stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
注:新版本中执行 helm init 命令后默认会配置一个名为 local 的本地仓库。
我们可以在本地启动一个 Repository Server,并将其加入到 Helm Repo 列表中。Helm Repository 必须以 Web 服务的方式提供,这里我们就使用 helm serve 命令启动一个 Repository Server,该 Server 缺省使用 $HOME/.helm/repository/local 目录作为 Chart 存储,并在 8879 端口上提供服务。
$ helm serve &
Now serving you on 127.0.0.1:8879
默认情况下该服务只监听 127.0.0.1,如果你要绑定到其它网络接口,可使用以下命令:
$ helm serve --address 192.168.100.211:8879 &
如果你想使用指定目录来做为 Helm Repository 的存储目录,可以加上 --repo-path 参数:
$ helm serve --address 192.168.100.211:8879 --repo-path /data/helm/repository/ --url http://192.168.100.211:8879/charts/
通过 helm repo index 命令将 Chart 的 Metadata 记录更新在 index.yaml 文件中:
# 更新 Helm Repository 的索引文件
$ cd /home/k8s/.helm/repository/local
$ helm repo index --url=http://192.168.100.211:8879 .
完成启动本地 Helm Repository Server 后,就可以将本地 Repository 加入 Helm 的 Repo 列表。
$ helm repo add local http://127.0.0.1:8879
"local" has been added to your repositories
现在再次查找 mychart 包,就可以搜索到了。
$ helm repo update
$ helm search mychart
NAME CHART VERSION APP VERSION DESCRIPTION
local/mychart 0.1.0 1.0 A Helm chart for Kubernetes
依赖
我们可以在requirement.yaml中定义应用所依赖的chart,例如定义对mariadb的依赖:
dependencies:
- name: mariadb
version: 0.6.0
repository: https://kubernetes-charts.storage.googleapis.com
使用helm lint .命令可以检查依赖和模板配置是否正确。
helm升级和回退一个应用
从上面 helm list 输出的结果中我们可以看到有一个 Revision(更改历史)字段,该字段用于表示某一个 Release 被更新的次数,我们可以用该特性对已部署的 Release 进行回滚。
修改 Chart.yaml 文件
将版本号从 0.1.0 修改为 0.2.0, 然后使用 helm package 命令打包并发布到本地仓库。
$ cat mychart/Chart.yaml
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: mychart
version: 0.2.0
$ helm package mychart
Successfully packaged chart and saved it to: /home/k8s/mychart-0.2.0.tgz
查询本地仓库中的 Chart 信息
我们可以看到在本地仓库中 mychart 有两个版本。
$ helm search mychart -l
NAME CHART VERSION APP VERSION DESCRIPTION
local/mychart 0.2.0 1.0 A Helm chart for Kubernetes
local/mychart 0.1.0 1.0 A Helm chart for Kubernetes
升级一个应用
现在用 helm upgrade 命令将已部署的 mike-test 升级到新版本。你可以通过 --version 参数指定需要升级的版本号,如果没有指定版本号,则缺省使用最新版本。
$ helm upgrade mike-test local/mychart
Release "mike-test" has been upgraded. Happy Helming!
LAST DEPLOYED: Mon Jul 23 10:50:25 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
mike-test-mychart-6d56f8c8c9-d685v 1/1 Running 0 9m
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mike-test-mychart ClusterIP 10.254.120.177 <none> 80/TCP 9m
==> v1beta2/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
mike-test-mychart 1 1 1 1 9m
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=mike-test" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
完成后,可以看到已部署的 mike-test 被升级到 0.2.0 版本。
$ helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
mike-test 2 Mon Jul 23 10:50:25 2018 DEPLOYED mychart-0.2.0 default
回退一个应用
如果更新后的程序由于某些原因运行有问题,需要回退到旧版本的应用。首先我们可以使用 helm history 命令查看一个 Release 的所有变更记录。
$ helm history mike-test
REVISION UPDATED STATUS CHART DESCRIPTION
1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete
2 Mon Jul 23 10:50:25 2018 DEPLOYED mychart-0.2.0 Upgrade complete
其次,我们可以使用下面的命令对指定的应用进行回退。
$ helm rollback mike-test 1
Rollback was a success! Happy Helming!
注:其中的参数 1 是 helm history 查看到 Release 的历史记录中 REVISION 对应的值。
最后,我们使用 helm list 和 helm history 命令都可以看到 mychart 的版本已经回退到 0.1.0 版本。
$ helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
mike-test 3 Mon Jul 23 10:53:42 2018 DEPLOYED mychart-0.1.0 default
$ helm history mike-test
REVISION UPDATED STATUS CHART DESCRIPTION
1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete
2 Mon Jul 23 10:50:25 2018 SUPERSEDED mychart-0.2.0 Upgrade complete
3 Mon Jul 23 10:53:42 2018 DEPLOYED mychart-0.1.0 Rollback to 1
删除一个应用
如果需要删除一个已部署的 Release,可以利用 helm delete 命令来完成删除。
$ helm delete mike-test
release "mike-test" deleted
确认应用是否删除,该应用已被标记为 DELETED 状态。
$ helm ls -a mike-test
NAME REVISION UPDATED STATUS CHART NAMESPACE
mike-test 3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 default
也可以使用 --deleted 参数来列出已经删除的 Release
$ helm ls --deleted
NAME REVISION UPDATED STATUS CHART NAMESPACE
mike-test 3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 default
从上面的结果也可以看出,默认情况下已经删除的 Release 只是将状态标识为 DELETED 了 ,但该 Release 的历史信息还是继续被保存的。
$ helm hist mike-test
REVISION UPDATED STATUS CHART DESCRIPTION
1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete
2 Mon Jul 23 10:50:25 2018 SUPERSEDED mychart-0.2.0 Upgrade complete
3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 Deletion complete
如果要移除指定 Release 所有相关的 Kubernetes 资源和 Release 的历史记录,可以用如下命令:
$ helm delete --purge mike-test
release "mike-test" deleted
再次查看已删除的 Release,已经无法找到相关信息。
$ helm hist mike-test
Error: release: "mike-test" not found
# helm ls 命令也已均无查询记录。
$ helm ls --deleted
$ helm ls -a mike-test
使用Helm 部署 Wordpress应用实例
以Wordpress 为例,包括 MySQL、PHP 和 Apache。
由于测试环境没有可用的 PersistentVolume(持久卷,简称 PV),这里暂时将其关闭。
$ helm install --name wordpress-test --set "persistence.enabled=false,mariadb.persistence.enabled=false,serviceType=NodePort" stable/wordpress
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
wordpress-test-mariadb 1 1 1 1 26m
wordpress-test-wordpress 1 1 1 1 26m
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
wordpress-test-mariadb-84b866bf95-n26ff 1/1 Running 1 26m
wordpress-test-wordpress-5ff8c64b6c-sgtvv 1/1 Running 6 26m
==> v1/Secret
NAME TYPE DATA AGE
wordpress-test-mariadb Opaque 2 26m
wordpress-test-wordpress Opaque 2 26m
==> v1/ConfigMap
NAME DATA AGE
wordpress-test-mariadb 1 26m
wordpress-test-mariadb-tests 1 26m
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress-test-mariadb ClusterIP 10.254.99.67 <none> 3306/TCP 26m
wordpress-test-wordpress NodePort 10.254.175.16 <none> 80:8563/TCP,443:8839/TCP 26m
NOTES:
1. Get the WordPress URL:
Or running:
export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services wordpress-test-wordpress)
export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT/admin
2. Login with the following credentials to see your blog
echo Username: user
echo Password: $(kubectl get secret --namespace default wordpress-test-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)
访问 Wordpress
部署完成后,我们可以通过上面的提示信息生成相应的访问地址和用户名、密码等相关信息。
# 生成 Wordpress 管理后台地址
$ export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services wordpress-test-wordpress)
$ export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
$ echo http://$NODE_IP:$NODE_PORT/admin
http://192.168.100.211:8433/admin
# 生成 Wordpress 管理帐号和密码
$ echo Username: user
Username: user
$ echo Password: $(kubectl get secret --namespace default wordpress-test-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)
Password: 9jEXJgnVAY
如何设置 helm 命令自动补全?
为了方便 helm 命令的使用,Helm 提供了自动补全功能,如果使用 ZSH 请执行:
$ source <(helm completion zsh)
如果使用 BASH 请执行:
$ source <(helm completion bash)
如何使用第三方的 Chart 存储库?
随着 Helm 越来越普及,除了使用预置官方存储库,三方仓库也越来越多了(前提是网络是可达的)。你可以使用如下命令格式添加三方 Chart 存储库。
$ helm repo add 存储库名 存储库URL
$ helm repo update
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。