wangbo123855842 / Learning

15 stars 2 forks source link

Helm #42

Open wangbo123855842 opened 4 years ago

wangbo123855842 commented 4 years ago
スクリーンショット 2020-10-16 13 17 14

Helm

Helm 类似于 Linux 系统下的包管理器,如yum ,apt等,可以方便快捷的 将之前打包好的 yaml 文件快速部署进 kubernetes 内,方便管理维护。

Helm 的一些名字

一个命令行的客户端工具,主要用于 kubernetes 应用 chart 的 创建/打包/发布。

helm 的服务端,部署于 kubernetes 内,Tiller 接受 helm 的请求,并根据 chart 生成 kubernetes 部署文件(helm称为release),然后提交给 Kubernetes 创建应用Tiller 还提供了 Release 的升级、删除、回滚等一系列功能。

helm 的软件包,采用 tar 格式,其中包含运行一个应用所需的 所有镜像/依赖/资源定义 等。 还可能包含 kubernetes 集群中服务定义。

在 kubernetes 中集群中运行的一个 Chart 实例,在同一个集群上,一个 Chart 可以安装多次,每次安装均会生成一个新的release。

用于发布和存储 Chart 的仓库,Helm 客户端通过 HTTP 协议来访问仓库中 Chart 的索引文件和压缩包

スクリーンショット 2020-10-16 13 31 21

工作流程

  1. Helm 从指定的目录或者 tgz 文件中解析出 Chart 结构信息

  2. Helm 将指定的Chart结构和Values信息通过 gRPC 传递给 Tiller

  3. Tiller 根据 Chart 和 Values 生成一个Release

  4. Tiller 将 Release 发送给 Kubernetes 运行。

  1. Helm 从指定的目录或者tgz文件中解析出 Chart 结构信息

  2. Helm 将要更新的 Release 的名称和 Chart 结构,Values 信息传递给 Tiller

  3. Tiller 生成 Release 并更新指定名称的 Release 的 History

  4. Tiller 将 Release 发送给 Kubernetes 运行

  1. Helm 将回滚的 release 名称传递给 Tiller

  2. Tiller 根据 Release 名称查找 History

  3. Tiller 从 History 中获取到上一个 Release

  4. Tiller 将上一个 Release 发送给 Kubernetes 用于替换当前 Release

helm v3 安装部署

brew install helm

Helm3 不需要安装tiller,不需要执行 helm init。 需要提前准备一个 kubernetes 集群,在 kubectl 可以运行的机器上安装 Helm

Helm 采用 客户端/服务器 架构

スクリーンショット 2020-10-16 14 00 16

Chart 文件结构

myapp/                               # Chart 目录
├── charts                           # 这个 charts 依赖的其他 charts,始终被安装
├── Chart.yaml                       # 描述这个 Chart 的相关信息、包括名字、描述信息、版本等
├── templates                        # 模板目录
│   ├── deployment.yaml              # deployment 控制器的 Go 模板文件
│   ├── _helpers.tpl                 # 以 _ 开头的文件不会部署到 k8s 上,可用于定制通用信息
│   ├── ingress.yaml                 # ingress 的模板文件
│   ├── NOTES.txt                    # Chart 部署到集群后的一些信息,例如:如何使用、列出缺省值
│   ├── service.yaml                 # service 的 Go 模板文件
│   └── tests
│       └── test-connection.yaml
└── values.yaml                      # 模板的值文件,这些值会在安装时应用到 GO 模板生成部署文件

Chart.yaml

用于描述 Chart 的基本信息,包括名称,版本

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

常见配置

description: A Helm chart for Kubernetes
name: mychart
version: 0.1.0
apiVersion: v1
appVersion: "1.0"

values.yaml

Deployment 等 yaml 配置文件,其中的双大括号包扩起来的部分是Go template。 这个值就是在 values.yaml 文件中定义的。

比如 ,Deployment 的 yaml 配置文件

spec:
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        app: {{ template "fullname" . }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}

values.yaml

replicaCount: 1
image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent

操作

[root@master mychart]# helm create mychart
Creating mychart

[root@master mychart]# ls
mychart

[root@master mychart]# tree mychart/
mychart/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml                     # 部署相关资源
│   ├── _helpers.tpl                            # 模版助手
│   ├── ingress.yaml                            # ingress资源
│   ├── NOTES.txt                           # chart的帮助文本,运行helm install展示给用户
│   ├── service.yaml                            # service端点
│   └── tests
│       └── test-connection.yaml
└── values.yaml

创建自己的 Chart 之后,可以删除 template 下的所有文件,并创建自己的 YAML 比如,创建一个 mychart/templates/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

由于创建的 yaml 文件在 template 下,安装,Tiller 就读取此文件,会将其发送给kubernetes。

helm install my-release ./mychart/

其中,my-release 是 release 名称。Releases 也是 Helm 的概念之一。每次安装都会产生新的 release更新时则会产生新的 release revision。你可以使用 helm list 命令查看当前命名空间下的所有 releases

helm list
NAME          NAMESPACE    REVISION    UPDATED                                 STATUS      CHART            APP VERSION
my-release    staging      1           2020-03-23 22:24:12.345011 +0800 CST    deployed    redis-10.5.11    5.0.8

查看 configMap

[root@master mychart]# kubectl get cm mychart-configmap
NAME                DATA   AGE
mychart-configmap   1      2m6s

使用 模板指令{{.Release.Name}} 将 release 名称注入模板。 Release 对象是 Helm 的内置对象之一

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-configmap
data:
  myvalue: "Hello World"

Chart 打包

helm package mychart
Successfully packaged chart and saved it to: /root/Downloads/charts/mychart-0.1.0.tgz

用 tgz 包安装

helm install mychart-0.1.0.tgz --namespace test -n mychart
NAME:   mychart
LAST DEPLOYED: Thu Nov  8 15:03:19 2018
NAMESPACE: test
STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME                       AGE
message-service-of-mychart  1s

==> v1beta2/Deployment
message-service-of-mychart  1s

==> v1/Pod(related)

NAME                                       READY  STATUS   RESTARTS  AGE
message-service-of-mychart-b545dfc84-fthg9  0/1    Pending  0         1s

查看部署

helm ls
NAME            REVISION    UPDATED                     STATUS      CHART               APP VERSION NAMESPACE
mychart         3           Thu Nov  8 15:09:29 2018    DEPLOYED    mychart-0.1.0           1.0         test

下线部署

helm delete mychart

更新部署 在更新chart后,编辑 mychart/Chart.yaml 种的 version 信息。 例如,我更新 version 为 version: 0.1.1。然后重新打包 helm package mychart

helm upgrade course ./mychart-0.1.1.tgz

helm Release "mychart" has been upgraded. Happy Helming!
LAST DEPLOYED: Thu Nov  8 15:52:17 2018
NAMESPACE: test
STATUS: DEPLOYED

回滚部署 回滚一个版本。

helm rollback course 1

helm rollback

helm rollback my-release # 回滚到上一个 revision
helm rollback my-release n # 回滚到第 n 个 revision

事例

做一个 go2cloud-api-doc 应用。

Charts 目录

[root@master go2cloud-api-doc]# tree 
.
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── NOTES.txt
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "go2cloud-api-doc.fullname" . }}
  labels:
{{ include "go2cloud-api-doc.labels" . | indent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "go2cloud-api-doc.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ include "go2cloud-api-doc.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}
    spec:
      imagePullSecrets: 
        - name: {{ .Values.imagePullSecrets }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: {{ .Values.service.port }}
              protocol: TCP
          livenessProbe:
            {{- toYaml .Values.livenessProbe | nindent 12  }}
          readinessProbe:
            {{- toYaml .Values.readinessProbe | nindent 12  }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
    {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
    {{- end }}
    {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
    {{- end }}
apiVersion: v1
kind: Service
metadata:
  name: {{ include "go2cloud-api-doc.fullname" . }}
  labels:
{{ include "go2cloud-api-doc.labels" . | indent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.port }}
      protocol: TCP
      name: http
      nodePort: {{ .Values.service.nodePort }}      
  selector:
    app.kubernetes.io/name: {{ include "go2cloud-api-doc.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
replicaCount: 1
image:
  repository: 10.234.2.218/go2cloud/go2cloud-api-doc
  tag: latest
  pullPolicy: Always
imagePullSecrets: registry-secret
nameOverride: ""
fullnameOverride: ""
service:
  type: NodePort
  port: 4567
  nodePort: 30567
ingress:
  enabled: false
  annotations: {}
  hosts:
    - host: chart-example.local
      paths: []
  tls: []
resources: 
  requests:
    cpu: 1000m
    memory: 1280Mi
  limits:
    cpu: 1000m
    memory: 1280Mi
livenessProbe:
  tcpSocket:
    port: 4567
  initialDelaySeconds: 10
  failureThreshold: 2 
  timeoutSeconds: 10
readinessProbe:
  httpGet:
    path: /#introduction
    port: http
  initialDelaySeconds: 5
  failureThreshold: 2 
  timeoutSeconds: 30
nodeSelector: {}
tolerations: []
affinity: {}
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: go2cloud-api-doc
version: 0.1.0
helm install -n go2cloud-api-doc -f go2cloud-api-doc/values.yaml go2cloud-api-doc/

NAME:   go2cloud-api-doc
LAST DEPLOYED: Wed Jul 31 14:34:21 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Deployment
NAME              READY  UP-TO-DATE  AVAILABLE  AGE
go2cloud-api-doc  0/1    1           0          0s

==> v1/Pod(related)
NAME                               READY  STATUS             RESTARTS  AGE
go2cloud-api-doc-7cfb7bb795-clrz8  0/1    ContainerCreating  0         0s

==> v1/Service
NAME              TYPE      CLUSTER-IP     EXTERNAL-IP  PORT(S)         AGE
go2cloud-api-doc  NodePort  10.96.228.251  <none>       4567:30567/TCP  0s
helm ls go2cloud-api-doc
NAME                    REVISION        UPDATED                         STATUS          CHART                   APP VERSION     NAMESPACE
go2cloud-api-doc        1               Wed Jul 31 14:34:21 2019        DEPLOYED        go2cloud-api-doc-0.1.0  1.0             default  

升级副本数量

helm upgrade go2cloud-api-doc --set replicaCount=2 go2cloud-api-doc/

Helmfile

Helm 不提供 apply 命令,因此在 CI/CD 场景中必须考虑到判断是 install 还是 upgrade。

Helmfile 的文档非常简明、直接,例如

repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: my-release     # Release name
    namespace: staging   # Release namespace
    chart: bitnami/redis # Chart name
    values:              # 等效于 helm 的 --values 选项
      - foo.yaml
    set:                 # 等效于 helm 的 --set 选项
      - name: cluster.enabled
        value: "false"

将以上内容保存为 helmfile.yaml 文件,随后执行 helmfile apply 即可。Helmfile 将会帮我们:

  1. 添加 repositories 中声明的 Helm chart repo。
  2. 根据 release 小节内的配置,安装或更新 chart。

因此,上面提到的操作

helm repo add ...
helm install ...
helm upgrade ...

可直接被简化为

helmfile apply

同时,如果你安装了 helm-diff 插件,Helmfile 还会在执行操作前输出清晰的 diff。

スクリーンショット 2020-10-17 19 43 28