什么是helm
Helm 是 Kubernetes 生态系统中的一个软件包管理工具。
基础概念:
Helm:客户端,主要负责管理本地的 Charts、repositories 以及与tiller服务器交互,发送Chart,实例安装、查询、卸载等操作;
Tiller:安装在 k8s 集群中的服务端,是实际用来管理安装在 k8s 中应用的,就是将模板与 values 合并,当然实际开发过程中, 也可以安装在 k8s 集群之外 ;接收helm发来的Charts与Config,合并生产relase;
Chart:是用来管理模板与默认 values 的项目,也可以认为是一个 package,可以发布到专门的 repository;
Repository: Chart仓库,https/http服务器;
Release:特定的Chart部署于目标集群上的一个实例;
Release:使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release。
helm部署
1、安装 Helm 客户端
#下载 Helm
$ wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.0-linux-amd64.tar.gz
#解压 Helm
$ tar -xf helm-v2.13.0-linux-amd64.tar.gz
#复制客户端执行文件到 bin目录下就可以用了
$ cp linux-amd64/helm /usr/local/bin/
2、安装 Tiller
helm init --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.13.0 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts --tiller-namespace myname
镜像默认使用gcr.io/kubernetes-helm/tiller;
仓库默认使用https://kubernetes-charts.storage.googleapis.com。
由于国内无法访问相关域名,可以使用阿里云容器服务提供的镜像和站点,也可以自定义。
可以用--skip-refresh参数跳过stable-repo-url设置
注意镜像版本问题, 要和客户端一致
注:helm install 默认会用到 socat,需要在所有节点上安装 socat 软件包。
3、卸载
如果你需要在 Kubernetes 中卸载已部署的 Tiller,可使用以下命令完成卸载。
$ helm reset
4、验证
# 查看已部署的应用
helm list
如果有如下报错:
从Kubernetes 1.6开始,API Server启用了RBAC授权。
而Tiller部署没有定义授权的ServiceAccount,这会导致访问API Server时被拒绝。
我们可以采用如下方法,为Tiller部署添加授权:
#创建 Kubernetes 的服务帐号和绑定角色 kubectl get deployment --all-namespaces kubectl create serviceaccount --namespace kube-system tiller kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller #使用 kubectl patch 更新 API 对象 kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
#查看是否授权成功
kubectl get deploy --namespace kube-system tiller-deploy --output yaml|grep serviceAccount
构建一个 Helm Chart
Helm安装后可执行helm search查看当前可安装的chart
Helm像apt和yum管理软件包一样管理chart,apt和yum我得软件包放在仓库里,同样的helm也有仓库。
helm repo list
通过一个完整的示例来学习如何使用 Helm 创建、打包、分发、安装、升级及回退Kubernetes应用。
1、创建一个名为 myapp 的 Chart
helm create myapp
该命令创建了一个 myapp 目录,该目录结构如下所示。
Chart.yaml 用于描述这个 Chart的相关信息,包括名字、描述信息以及版本等。 values.yaml 用于存储 templates 目录中模板文件中用到变量的值。 NOTES.txt 用于介绍 Chart 部署后的一些信息,例如:如何使用这个 Chart、列出缺省的设置等。 Templates 目录下是 YAML 文件的模板,该模板文件遵循 Go template 语法。
一旦安装了某个 chart,我们就可以在 ~/.helm/cache/archive 中找到 chart 的 tar 包。
2、检查依赖和模板配置是否正确
helm lint myapp/
语法检测,如果文件格式错误,可以根据提示进行修改。
将应用打包
$ helm package myapp Successfully packaged chart and saved it to: /root/k8s_yaml/helm/myapp-0.1.0.tgz
myapp 目录会被打包为一个 myapp-0.1.0.tgz 格式的压缩包,该压缩包会被放到当前目录下,并同时被保存到了 Helm 的本地缺省仓库目录中。
如果你想看到更详细的输出,可以加上 --debug 参数来查看打包的输出,输出内容应该类似如下:
$ helm package myapp --debug Successfully packaged chart and saved it to: /root/k8s_yaml/helm/myapp-0.1.0.tgz [debug] Successfully saved /root/k8s_yaml/helm/myapp-0.1.0.tgz to /root/.helm/repository/local
3、将应用发布到 Repository
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/
在 Kubernetes 中部署应用
部署一个应用
Chart 被发布到仓储后,就可以通过 helm install 命令部署该 Chart。
在部署前我们可以使用 helm install --dry-run --debug <chart_dir> --name <release_name>命令来验证 Chart 的配置。该输出中包含了模板的变量配置与最终渲染的 YAML 文件。
[root@master ~]# helm install --dry-run --debug local/myapp --name myapp-test [debug] Created tunnel using local port: '21619' [debug] SERVER: "127.0.0.1:21619" [debug] Original chart version: "" [debug] Fetched local/myapp to /root/.helm/cache/archive/myapp-0.1.0.tgz [debug] CHART PATH: /root/.helm/cache/archive/myapp-0.1.0.tgz NAME: myapp-test REVISION: 1 RELEASED: Fri Apr 5 11:17:02 2019 CHART: myapp-0.1.0 USER-SUPPLIED VALUES: {} COMPUTED VALUES: affinity: {} fullnameOverride: "" image: pullPolicy: IfNotPresent repository: nginx tag: stable ingress: annotations: {} enabled: false hosts: - host: chart-example.local paths: [] tls: [] nameOverride: "" nodeSelector: {} replicaCount: 1 resources: {} service: port: 80 type: ClusterIP tolerations: [] HOOKS: --- # myapp-test-test-connection apiVersion: v1 kind: Pod metadata: name: "myapp-test-test-connection" labels: app.kubernetes.io/name: myapp helm.sh/chart: myapp-0.1.0 app.kubernetes.io/instance: myapp-test app.kubernetes.io/managed-by: Tiller annotations: "helm.sh/hook": test-success spec: containers: - name: wget image: busybox command: ['wget'] args: ['myapp-test:80'] restartPolicy: Never MANIFEST: --- # Source: myapp/templates/service.yaml apiVersion: v1 kind: Service metadata: name: myapp-test labels: app.kubernetes.io/name: myapp helm.sh/chart: myapp-0.1.0 app.kubernetes.io/instance: myapp-test app.kubernetes.io/managed-by: Tiller spec: type: ClusterIP ports: - port: 80 targetPort: http protocol: TCP name: http selector: app.kubernetes.io/name: myapp app.kubernetes.io/instance: myapp-test --- # Source: myapp/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-test labels: app.kubernetes.io/name: myapp helm.sh/chart: myapp-0.1.0 app.kubernetes.io/instance: myapp-test app.kubernetes.io/managed-by: Tiller spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: myapp app.kubernetes.io/instance: myapp-test template: metadata: labels: app.kubernetes.io/name: myapp app.kubernetes.io/instance: myapp-test spec: containers: - name: myapp image: "nginx:stable" imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 protocol: TCP livenessProbe: httpGet: path: / port: http readinessProbe: httpGet: path: / port: http resources: {}
验证完成没有问题后,我们就可以使用以下命令将其部署到 Kubernetes 上了。
# 部署时需指定 Chart 名及 Release(部署的实例)名。
[root@master ~]# helm install local/myapp --name myapp-test NAME: myapp-test LAST DEPLOYED: Fri Apr 5 11:19:02 2019 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE myapp-test 0/1 0 0 0s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE myapp-test ClusterIP 10.10.10.3 <none> 80/TCP 0s NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=myapp,app.kubernetes.io/instance=myapp-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