虚拟化运维--容器云--Helm(十九)

一、Helm简介

  Helm 是 Deis 开发的一个用于 Kubernetes 应用的包管理工具,主要用来管理 Charts。有点类似于 Ubuntu 中的 APT 或 CentOS 中的 YUM。
  Helm 是 Kubernetes 生态系统中的一个软件包管理工具。Helm就是为了简化在Kubernetes中安装部署容器云应用的一个客户端工具。通过helm能够帮助开发者定义、安装和升级Kubernetes中的容器云应用,同时,也可以通过helm进行容器云应用的分享。在Kubeapps Hub中提供了包括Redis、MySQL和Jenkins等参见的应用,通过helm可以使用一条命令就能够将其部署安装在自己的Kubernetes集群中。
  Helm Chart 是用来封装 Kubernetes 原生应用程序的一系列 YAML 文件。可以在你部署应用的时候自定义应用程序的一些 Metadata,以便于应用程序的分发。
  对于应用发布者而言,可以通过 Helm 打包应用、管理应用依赖关系、管理应用版本并发布应用到软件仓库。
  对于使用者而言,使用 Helm 后不用需要编写复杂的应用部署文件,可以以简单的方式在 Kubernetes 上查找、安装、升级、回滚、卸载应用程序。
官网:https://helm.sh/docs/

二、基本概念

Helm(客户端):Helm 是一个命令行下的客户端工具。主要用于 Kubernetes 应用程序 Chart 的创建、打包、发布以及创建和管理本地和远程的 Chart 仓库。
Tiller(服务器):Tiller 是 Helm 的服务端,部署在 Kubernetes 集群中。Tiller 用于接收 Helm 的请求,并根据 Chart 生成 Kubernetes 的部署文件( Helm 称为 Release ),然后提交给 Kubernetes 创建应用。Tiller 还提供了 Release 的升级、删除、回滚等一系列功能。
Repository(Chart 软件仓库):Helm 的软件仓库,Repository 本质上是一个 Web 服务器,该服务器保存了一系列的 Chart 软件包以供用户下载,并且提供了一个该 Repository 的 Chart 包的清单文件以供查询。Helm 可以同时管理多个不同的 Repository。
Chart(软件包):Helm 的软件包,采用 TAR 格式。类似于 APT 的 DEB 包或者 YUM 的 RPM 包,其包含了一组定义 Kubernetes 资源相关的 YAML 文件。
Release:使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release。

注:需要注意的是:Helm 中提到的 Release 和我们通常概念中的版本有所不同,这里的 Release 可以理解为 Helm 使用 Chart 包部署的一个应用实例。


Helm工作原理

Chart Install 过程:
Helm从指定的目录或者tgz文件中解析出Chart结构信息
Helm将指定的Chart结构和Values信息通过gRPC传递给Tiller
Tiller根据Chart和Values生成一个Release
Tiller将Release发送给Kubernetes用于生成Release

Chart Update过程:
Helm从指定的目录或者tgz文件中解析出Chart结构信息
Helm将要更新的Release的名称和Chart结构,Values信息传递给Tiller
Tiller生成Release并更新指定名称的Release的History
Tiller将Release发送给Kubernetes用于更新Release
Chart Rollback过程:

Helm将要回滚的Release的名称传递给Tiller
Tiller根据Release的名称查找History
Tiller从History中获取上一个Release
Tiller将上一个Release发送给Kubernetes用于替换当前Release

二、部署 Helm

  1. Helm 客户端安装
    下载地址:https://github.com/helm/helm/releases
# 下载安装
[root@localhost ~]# wget https://get.helm.sh/helm-v3.0.0-rc.1-linux-amd64.tar.gz
# 解压
[root@localhost ~]#  tar -zxvf helm-v3.0.0-rc.1-linux-amd64.tar.gz 

# 复制客户端执行文件到 bin 目录下
[root@localhost ~]# ls
anaconda-ks.cfg  harbor-offline-installer-v1.9.1.tgz  helm-v3.0.0-rc.1-linux-amd64.tar.gz  jdk-12.0.2_linux-x64_bin.tar.gz  linux-amd64  solr-8.2.0.tgz
[root@localhost ~]#  cp linux-amd64/helm /usr/local/bin/

  1. 安装 Helm 服务器端 Tiller
    Tiller 是以 Deployment 方式部署在 Kubernetes 集群中的,只需使用以下指令便可简单的完成安装。
[root@localhost ~]# helm init

由于 Helm 默认会去 storage.googleapis.com拉取镜像,如果你当前执行的机器不能访问该域名的话可以使用以下命令来安装:

# 使用阿里云镜像安装并把默认仓库设置为阿里云上的镜像仓库
[root@localhost ~]# helm init --client-only --stable-repo-url https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts/
[root@localhost ~]# helm repo add incubator https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts-incubator/
[root@localhost ~]# helm repo update

# Tiller 授权(因为 Helm 的服务端 Tiller 是一个部署在 Kubernetes 中 Kube-System Namespace 下 的 Deployment,它会去连接 Kube-Api 在 Kubernetes 里创建和删除应用。)
# 创建 Kubernetes 的服务帐号和绑定角色
kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
# 为 Tiller 设置帐号
# 使用 kubectl patch 更新 API 对象
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
deployment.extensions "tiller-deploy" patched
# 查看是否授权成功
kubectl get deploy --namespace kube-system   tiller-deploy  --output yaml|grep  serviceAccount

# 验证 Tiller 是否安装成功
[root@localhost ~]# kubectl -n kube-system get pods|grep tiller
# 卸载 Helm 服务器端 Tiller
[root@localhost ~]# helm reset

  1. Helm仓库管理
    1)更换仓库
# 先移除原先的仓库
helm repo remove stable
# 添加新的仓库地址
helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
# 更新仓库
helm repo update

2)查看在存储库中可用的所有 Helm charts:

helm search

3)更新charts列表

helm repo update
  1. Chart

Monocular是一个开源软件,用于管理kubernetes上以Helm Charts形式创建的服务,可以通过它的web页面来安装helm Charts
安装Nginx Ingress controller,安装的k8s集群启用了RBAC,则一定要加rbac.create=true参数

helm install stable/nginx-ingress --set controller.hostNetwork=true,rbac.create=true

安装Monocular:

# 添加新的源
helm repo add monocular https://kubernetes-helm.github.io/monocular
# 安装
helm install monocular/monocular -f custom-repos.yaml
 
# custom-repos.yaml 内容
cat custom-repos.yaml
 
api:
  config:
    repos:
      - name: stable
        url: https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts
        source: https://github.com/kubernetes/charts/tree/master/stable
      - name: incubator
        url: https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts-incubator
        source: https://github.com/kubernetes/charts/tree/master/incubator
      - name: monocular
        url: https://kubernetes-helm.github.io/monocular
        source: https://github.com/kubernetes-helm/monocular/tree/master/charts

查看K8S中已安装的charts

helm list

删除安装的charts

# 删除:helm delete xxx
helm delete amber-seal
  1. Helm Chart 结构
    Chart 目录结构:
examples/
  Chart.yaml          # Yaml文件,用于描述Chart的基本信息,包括名称版本等
  LICENSE             # [可选] 协议
  README.md           # [可选] 当前Chart的介绍
  values.yaml         # Chart的默认配置文件
  requirements.yaml   # [可选] 用于存放当前Chart依赖的其它Chart的说明文件
  charts/             # [可选]: 该目录中放置当前Chart依赖的其它Chart
  templates/          # [可选]: 部署文件模版目录,模版使用的值来自values.yaml和由Tiller提供的值
  templates/NOTES.txt # [可选]: 放置Chart的使用指南

Chart.yaml 文件


name: [必须] Chart的名称
version: [必须] Chart的版本号,版本号必须符合 SemVer 2:http://semver.org/
description: [可选] Chart的简要描述
keywords:
  -  [可选] 关键字列表
home: [可选] 项目地址
sources:
  - [可选] 当前Chart的下载地址列表
maintainers: # [可选]
  - name: [必须] 名字
    email: [可选] 邮箱
engine: gotpl # [可选] 模版引擎,默认值是gotpl
icon: [可选] 一个SVG或PNG格式的图片地址

requirements.yaml 和 charts目录
requirements.yaml 文件内容:


dependencies:
  - name: example
    version: 1.2.3
    repository: http://example.com/charts
  - name: Chart名称
    version: Chart版本
    repository: 该Chart所在的仓库地址

Chart支持两种方式表示依赖关系,可以使用requirements.yaml或者直接将依赖的Chart放置到charts目录中。
templates 目录
templates目录中存放了Kubernetes部署文件的模版。


# db.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: deis-database
  namespace: deis
  labels:
    heritage: deis
spec:
  replicas: 1
  selector:
    app: deis-database
  template:
    metadata:
      labels:
        app: deis-database
    spec:
      serviceAccount: deis-database
      containers:
        - name: deis-database
          image: {{.Values.imageRegistry}}/postgres:{{.Values.dockerTag}}
          imagePullPolicy: {{.Values.pullPolicy}}
          ports:
            - containerPort: 5432
          env:
            - name: DATABASE_STORAGE
              value: {{default "minio" .Values.storage}}

模版语法扩展了 golang/text/template的语法:


# 这种方式定义的模版,会去除test模版尾部所有的空行
{{- define "test"}}
模版内容
{{- end}}
 
# 去除test模版头部的第一个空行
{{- template "test" }}

用于yaml文件前置空格的语法:

# 这种方式定义的模版,会去除test模版头部和尾部所有的空行
{{- define "test" -}}
模版内容
{{- end -}}
 
# 可以在test模版每一行的头部增加4个空格,用于yaml文件的对齐
{{ include "test" | indent 4}}

  1. 自定义chart
    我们创建一个名为mongodb的chart,看一看chart的文件结构。

$ helm create mongodb
$ tree mongodb
mongodb
├── Chart.yaml #Chart本身的版本和配置信息
├── charts #依赖的chart
├── templates #配置模板目录
│   ├── NOTES.txt #helm提示信息
│   ├── _helpers.tpl #用于修改kubernetes objcet配置的模板
│   ├── deployment.yaml #kubernetes Deployment object
│   └── service.yaml #kubernetes Serivce
└── values.yaml #kubernetes object configuration

模板
Templates目录下是yaml文件的模板,遵循Go template语法。使用过Hugo的静态网站生成工具的人应该对此很熟悉。
我们查看下deployment.yaml文件的内容

# Default values for mychart.
# This is a yaml-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent
service:
  name: nginx
  type: ClusterIP
  externalPort: 80
  internalPort: 80
resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi

比如在Deployment.yaml中定义的容器镜像image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"其中的:
.Values.image.repository就是nginx
.Values.image.tag就是stable
以上两个变量值是在create chart的时候自动生成的默认值。
我们将默认的镜像地址和tag改成我们自己的镜像harbor-001.jimmysong.io/library/nginx:1.9。
检查配置和模板是否有效
当使用kubernetes部署应用的时候实际上讲templates渲染成最终的kubernetes能够识别的yaml格式。
使用helm install --dry-run --debug <chart_dir>命令来验证chart配置。该输出中包含了模板的变量配置与最终渲染的yaml文件。

$ helm install --dry-run --debug mychart
Created tunnel using local port: '58406'
SERVER: "localhost:58406"
CHART PATH: /Users/jimmy/Workspace/github/bitnami/charts/incubator/mean/charts/mychart
NAME:   filled-seahorse
REVISION: 1
RELEASED: Tue Oct 24 18:57:13 2017
CHART: mychart-0.1.0
USER-SUPPLIED VALUES:
{}
 
COMPUTED VALUES:
image:
  pullPolicy: IfNotPresent
  repository: harbor-001.jimmysong.io/library/nginx
  tag: 1.9
replicaCount: 1
resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi
service:
  externalPort: 80
  internalPort: 80
  name: nginx
  type: ClusterIP
 
HOOKS:
MANIFEST:
 
---
# Source: mychart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: filled-seahorse-mychart
  labels:
    chart: "mychart-0.1.0"
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: nginx
  selector:
    app: filled-seahorse-mychart
 
---
# Source: mychart/templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: filled-seahorse-mychart
  labels:
    chart: "mychart-0.1.0"
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: filled-seahorse-mychart
    spec:
      containers:
      - name: mychart
        image: "harbor-001.jimmysong.io/library/nginx:1.9"
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        livenessProbe:
          httpGet:
            path: /
            port: 80
        readinessProbe:
          httpGet:
            path: /
            port: 80
        resources:
            limits:
              cpu: 100m
              memory: 128Mi
            requests:
              cpu: 100m
              memory: 128Mi

可以看到Deployment和Service的名字前半截由两个随机的单词组成,最后才是我们在values.yaml中配置的值。
部署到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

删除部署的release

helm delete eating-hound

打包分享
我们可以修改Chart.yaml中的helm chart配置信息,然后使用下列命令将chart打包成一个压缩文件。

helm package .

参考资料:
https://www.hi-linux.com/posts/21466.html

https://blog.csdn.net/bbwangj/article/details/81087911#Tiller