前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >helm介绍与使用

helm介绍与使用

作者头像
dogfei
发布2020-07-31 15:39:08
1.6K0
发布2020-07-31 15:39:08
举报
文章被收录于专栏:devops探索devops探索

简介

helm是k8s的一个包管理工具,可以简化k8s应用的部署和管理,可以理解为yum和或者apt等包管理工具。 helm有几个非常重要的概念

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

Chart安装、升级、回滚过程

安装过程

  1. helm从指定的目录或者TAR文件解析出Chart结构信息
  2. helm将指定的Chart结构和Values信息通过gRPC传递给Tiller
  3. Tiller根据Chart和Values生成一个Release
  4. Tiller将Release发送给k8s用于生成Release

升级过程

  1. Helm从指定的目录或者TAR文件中解析出Chart结构信息
  2. Helm将需要更新的Release的名称、Chart结构和Values信息传递给Tiller
  3. Tiller生成Release并更新指定名称的Release的History
  4. Tiller将Release发送给k8s用于更新Release

回滚过程

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

helm简单使用

创建一个chart

helm create myapp

查看目录结构

代码语言:javascript
复制
# tree myapp/
    myapp/
    ├── charts
    ├── Chart.yaml
    ├── templates
    │   ├── deployment.yaml
    │   ├── _helpers.tpl
    │   ├── ingress.yaml
    │   ├── NOTES.txt
    │   ├── serviceaccount.yaml
    │   ├── service.yaml
    │   └── tests
    │       └── test-connection.yaml
    └── values.yaml

目录结构介绍

  • Chart.yaml 用于描述这个 Chart的相关信息,包括名字、描述信息以及版本等。
  • values.yaml 用于存储 templates 目录中模板文件中用到变量的值。
  • NOTES.txt 用于介绍 Chart 部署后的一些信息,例如:如何使用这个 Chart、列出缺省的设置等。
  • Templates 目录下是 YAML 文件的模板,该模板文件遵循 Go template 语法

创建仓库

可以找一台机器用来作为chart的存储仓库,类似于harbor一样,当然helm也可以使用helm作为仓库来存储chart,但这里还是通过将chart存储到本地目录里,然后通过web把改目录映射出去即可

代码语言:javascript
复制
helm serve --address 192.168.0.130:8879 --repo-path /data/helm/repository/ --url http://192.168.0.130:8879/charts/ &
helm repo index /data/helm/repository --url http://192.168.0.130:8879

–repo-path 指定存储chart的目录 –address 指定仓库地址 这样我们就把仓库创建好了,下面会涉及到打包应用以及将应用放到仓库里的操作。

客户端初始化配置

在本地打包应用之前需要先初始化一下,否则会打包失败报错

Error: open /home/jenkins/.helm/repository/local/index.yaml: no such file or directory

初始化操作

代码语言:javascript
复制
helm init --client-only

打包应用

前面创建了一个myapp的应用,现在需要将他打包

代码语言:javascript
复制
# 需要进到myapp的同级目录
helm package myapp

打包完成会生成一个tar包,将此tar包拷贝到helm仓库中

代码语言:javascript
复制
cp myapp-0.1.0.tgz /data/helm/repository/

拷贝完成后可以通过访问192.168.0.130:8879看到我们的myapp这个应用包

be4828a2ecf358593643b7a79b6bcdda.png
be4828a2ecf358593643b7a79b6bcdda.png

添加远程仓库并启动一个release

添加远程仓库

代码语言:javascript
复制
在k8s的目标主机上执行此命令来完成远程仓库的添加
helm repo add cicd http://192.168.0.130:8879/charts

添加完成后执行下update
helm repo update

安装一个release
helm install -f values.yaml test-helm cicd/myapp  

test-helm即为release的名称

删除release
helm delete --purge test-helm

内置对象

helm内置了一些对象,这些对象可以从模板引擎传递到模板中,这样我们在使用的时候就可以通过传入不通的参数来完成多个应用的部署操作了 下面介绍两个常用的对象

  • Release
  • Values

内置对象一般首字母大写,Release对象描述了release本身,Release对象中又包含了几个子对象:

代码语言:javascript
复制
Release  
Release.Name     release的名称  
Release.Time     release的时间  
Release.Namespace     release的namespace  
Release.Revision     此release的修订版本号,从1开始,每helm upgrade一次,就会增加1

Values对象是从values.yaml文件中读取或者命令行传入的值里传入模板中,而Values中我们可以自定义一些类似于变量的东西,类似于下面的示例:

代码语言:javascript
复制
replicaCount: 1
image:
  repository: harbor.devilf.cc
  tag: latest
代码语言:javascript
复制
cat deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
  labels:
    name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicas}} 
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  selector:
    matchLabels:
      name: {{ .Release.Name }}
  template:
    metadata:
      labels:
        name: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Release.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: IfNotPresent

知道这两个基本上就足够用了,Values这个对象非常的常用和灵活,可以从上面的deployment类型的资源文件里看到,如同变量替换一样方便,我们以后部署的时候再也不会通过使用sed或者其他操作来完成镜像地址的替换了!

示例

通常在k8s里部署一个pod时,需要一个deployment类型的文件,一个service类型的文件,有时还需要ingress类型的文件,如果只有几个应用的话我们可以通过脚本或者手动的方式去写yaml文件来完成部署操作,但如果项目非常多,这个时候对于yaml文件的管理将会非常不便!!! 下面以一个java程序为例,通过制作一个deployment类型的模板和service类型的模板,来完成该项目的部署

准备好Chart

代码语言:javascript
复制
cat myapp/templates/app-deployment.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
  labels:
    name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicas}} 
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  selector:
    matchLabels:
      name: {{ .Release.Name }}
  template:
    metadata:
      labels:
        name: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Release.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              cpu: {{ .Values.resources.limits.cpu }}
              memory: {{ .Values.resources.limits.memory }}
            requests:
              cpu: {{ .Values.resources.requests.cpu }}
              memory: {{ .Values.resources.requests.memory }}
          {{ if .Values.volumeMounts.name }}
          volumeMounts:
          - name: {{ .Values.volumeMounts.name }}
            mountPath: {{ quote .Values.volumeMounts.path }} 
            readOnly: false
            subPath: {{ .Values.volumeMounts.subpath }}
          {{ end }}
        {{ if .Values.imageOther.repository }}
        - name: {{ .Release.Name }}-other
          image: "{{ .Values.imageOther.repository }}:{{ .Values.imageOther.tag }}"
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              cpu: {{ .Values.resources.limits.cpu }}
              memory: {{ .Values.resources.limits.memory }}
            requests:
              cpu: {{ .Values.resources.requests.cpu }}
              memory: {{ .Values.resources.requests.memory }}
        {{ end }}
          {{ if .Values.livenessProbe.path }}
          livenessProbe:
            httpGet:
              path: {{ .Values.livenessProbe.path }}
              port: {{ .Values.livenessProbe.port }}
            initialDelaySeconds: 60
            periodSeconds: 30
            timeoutSeconds: 60
          {{ end }}
      {{ if .Values.volumeMounts.name }}
      volumes:
      - name: {{ .Values.volumeMounts.name }}
        persistentVolumeClaim:
          claimName: {{ .Values.volumeMounts.name }}
      {{ end }}
      imagePullSecrets:
        - name: {{ .Values.imagePullSecrets }}
代码语言:javascript
复制
cat myapp/templates/app-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
  labels:
    name: {{ .Release.Name }}
spec:
  ports:
    - name: {{ .Release.Name }}
      protocol: TCP
      targetPort: {{ .Values.containerPort.inner }}
      port: {{ .Values.containerPort.inner }}
      nodePort: {{ .Values.containerPort.outer }}
    {{ if .Values.containerPortOther.inner }}
    - name: {{ .Release.Name }}-other
      protocol: TCP
      targetPort: {{ .Values.containerPortOther.inner }}
      port: {{ .Values.containerPortOther.inner }}
      {{ if .Values.containerPortOther.outer }}
      nodePort: {{ .Values.containerPortOther.outer }}
      {{ end }}
    {{ end }}
  selector:
    name: {{ .Release.Name }}
  sessionAffinity: None
  type: NodePort

以上用到了一些流程控制,有时候可能一个pod会启动两个容器,或者映射多个端口,这时候我们可以使用简单的if 进行流程控制

然后修改values.yaml文件,来满足我们模板中定义的一些对象

代码语言:javascript
复制
cat myapp/values.yaml

replicaCount: 1
image:
  repository:
  tag:
imageOther:
  repository:
  tag:
containerPort:
  inner:
  outer:
containerPortOther:
  innerPort:
  outerPort:
imagePullSecrets: mima
resources:
  limits:
    cpu: 400m
    memory: 4096Mi
  requests:
    cpu: 100m
    memory: 128Mi
volumeMounts:
  name:
  path:
  subpath:
livenessProbe:
  path: 
  port:

chart.yaml参考

代码语言:javascript
复制
cat myapp/Chart.yaml 

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

整体的一个目录结构如下

代码语言:javascript
复制
# tree myapp
myapp
├── Chart.yaml
├── templates
│   ├── app-deployment.yaml
│   ├── app-svc.yaml
│   └── _helpers.tpl
└── values.yaml

可以把多余的一些文件或者目录删除掉

打包应用

代码语言:javascript
复制
进入到myapp的同级目录执行
helm package myapp
cp myapp-0.1.0.tgz /data/helm/repository/

k8s主机上安装应用

添加远程仓库地址

代码语言:javascript
复制
helm repo add cicd http://192.168.0.130:8879/charts
helm repo update

配置values.yaml文件,也可以通过--set进行指定 我们先测试指定一个镜像地址

代码语言:javascript
复制
cat values.yaml
replicaCount: 1
image:
  repository: harbor.devilf.cc/onair/user-manager
  tag: 202002101644-2.0.0-SNAPSHOT-1ed8d49
imageOther:
  repository: 
  tag: 
containerPort:
  inner: 9999
  outer: 32222
containerPortOther:
  innerPort: 
  outerPort: 
imagePullSecrets: mima
resources:
  limits:
    cpu: 400m
    memory: 4096Mi
  requests:
    cpu: 100m
    memory: 128Mi
volumeMounts:
  name:
  path:
  subpath:
livenessProbe:
  path: 
  port:

安装应用

代码语言:javascript
复制
# helm upgrade -i -f values.yaml test-helm cicd/myapp

Release "test-helm" does not exist. Installing it now.
NAME:   test-helm
LAST DEPLOYED: Thu Feb 13 15:59:12 2020
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Pod(related)
NAME                        AGE
test-helm-7c8b8584cd-w2vk4  0s

==> v1/Service
NAME       AGE
test-helm  0s

==> v1beta1/Deployment
NAME       AGE
test-helm  0s
28c33e73d8f2c7b1e2696ca64d9e346a.png
28c33e73d8f2c7b1e2696ca64d9e346a.png

下面再测试下两个镜像地址

代码语言:javascript
复制
# cat values.yaml 
replicaCount: 1
image:
  repository: alpha-harbor.yunshicloud.com/onair/user-manager
  tag: 202002101644-2.0.0-SNAPSHOT-1ed8d49
imageOther:
  repository: alpha-harbor.yunshicloud.com/onair/user-api
  tag: 202002110943-2.0.0-SNAPSHOT-5c011f4
containerPort:
  inner: 9999
  outer: 32222
containerPortOther:
  innerPort: 8088
  outerPort: 32223
imagePullSecrets: mima
resources:
  limits:
    cpu: 400m
    memory: 4096Mi
  requests:
    cpu: 100m
    memory: 128Mi
volumeMounts:
  name:
  path:
  subpath:
livenessProbe:
  path: 
  port:

安装方式是一样的,这里先把之前的给删除掉

代码语言:javascript
复制
# helm delete --purge test-helm
删除完成后,添加一个镜像地址,然后再次运行
# helm upgrade -i -f values.yaml test-helm cicd/myapp

这里我请求另一个服务的健康检查接口

c19c36399a8a5f011633e688b00be169.png
c19c36399a8a5f011633e688b00be169.png

也是没有问题的

到这里,基本上helm就可以结合Jenkins完成CD工作了,只需要创建一个values.yaml文件即可。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-02-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • Chart安装、升级、回滚过程
    • 安装过程
      • 升级过程
        • 回滚过程
        • helm简单使用
          • 创建一个chart
            • 查看目录结构
              • 目录结构介绍
                • 创建仓库
                  • 客户端初始化配置
                    • 打包应用
                      • 添加远程仓库并启动一个release
                      • 内置对象
                      • 示例
                        • 准备好Chart
                          • 打包应用
                            • k8s主机上安装应用
                            相关产品与服务
                            容器服务
                            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档