helm介绍与使用
简介
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安装、升级、回滚过程
安装过程
- helm从指定的目录或者TAR文件解析出Chart结构信息
- helm将指定的Chart结构和Values信息通过gRPC传递给Tiller
- Tiller根据Chart和Values生成一个Release
- Tiller将Release发送给k8s用于生成Release
升级过程
- Helm从指定的目录或者TAR文件中解析出Chart结构信息
- Helm将需要更新的Release的名称、Chart结构和Values信息传递给Tiller
- Tiller生成Release并更新指定名称的Release的History
- Tiller将Release发送给k8s用于更新Release
回滚过程
- Helm将要回滚的Release的名称传递给Tiller
- Tiller根据Release的名称查找History
- Tiller从History中获取上一个Release
- Tiller将上一个Release发送给k8s用于替换当前的Release
helm简单使用
创建一个chart
helm create myapp
查看目录结构
# 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把改目录映射出去即可
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
初始化操作
helm init --client-only
打包应用
前面创建了一个myapp的应用,现在需要将他打包
# 需要进到myapp的同级目录
helm package myapp
打包完成会生成一个tar包,将此tar包拷贝到helm仓库中
cp myapp-0.1.0.tgz /data/helm/repository/
拷贝完成后可以通过访问192.168.0.130:8879
看到我们的myapp这个应用包
添加远程仓库并启动一个release
添加远程仓库
在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对象中又包含了几个子对象:
Release
Release.Name release的名称
Release.Time release的时间
Release.Namespace release的namespace
Release.Revision 此release的修订版本号,从1开始,每helm upgrade一次,就会增加1
Values对象是从values.yaml文件中读取或者命令行传入的值里传入模板中,而Values中我们可以自定义一些类似于变量的东西,类似于下面的示例:
replicaCount: 1
image:
repository: harbor.devilf.cc
tag: latest
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
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 }}
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文件,来满足我们模板中定义的一些对象
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参考
cat myapp/Chart.yaml
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: myapp
version: 0.1.0
整体的一个目录结构如下
# tree myapp
myapp
├── Chart.yaml
├── templates
│ ├── app-deployment.yaml
│ ├── app-svc.yaml
│ └── _helpers.tpl
└── values.yaml
可以把多余的一些文件或者目录删除掉
打包应用
进入到myapp的同级目录执行
helm package myapp
cp myapp-0.1.0.tgz /data/helm/repository/
k8s主机上安装应用
添加远程仓库地址
helm repo add cicd http://192.168.0.130:8879/charts
helm repo update
配置values.yaml文件,也可以通过--set
进行指定
我们先测试指定一个镜像地址
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:
安装应用
# 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
下面再测试下两个镜像地址
# 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:
安装方式是一样的,这里先把之前的给删除掉
# helm delete --purge test-helm
删除完成后,添加一个镜像地址,然后再次运行
# helm upgrade -i -f values.yaml test-helm cicd/myapp
这里我请求另一个服务的健康检查接口
也是没有问题的
到这里,基本上helm就可以结合Jenkins完成CD工作了,只需要创建一个values.yaml文件即可。
- Github 与 Bitbucket 的互助协作
- JavaScript 基础(七) 箭头函数 generator Date JSON
- 初体验 Ghost : yet another WordPress?
- 浅谈MySQL的事务隔离级别
- 国内环境下前端网页开发的几个“中国特色”代码
- 从源码的角度再看 React JS 中的 setState
- Sass 与Compass 在WordPress 主题开发中的运用
- Python爬虫Scrapy入门看这篇就够了
- Clef:为你的WordPress 站点添加两步验证
- JavaScript 基础(六) 数组方法 闭包
- 【译】WordPress 中的50个过滤器(4):第21-30个过滤器
- 【译】WordPress 中的50个过滤器(3):第11-20个过滤器
- 【译】WordPress 中的50个过滤器(2):先介绍10个过滤器
- 【译】WordPress 中的50个过滤器(1):何为过滤器?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于JDK命令行工具的监控
- 基于JVisualVM的可视化监控
- 基于Btrace的监控调试
- 大数据框架—Flink与Beam
- Mybatis动态SQL
- Mybatis-Generator插件的使用与Spring集成Mybatis的配置
- Mybatis的缓存机制详解
- zookeeper基本特性与基于Linux的ZK客户端命令行学习
- Apache Curator操作zookeeper的API使用
- 使用Java API操作zookeeper的acl权限
- 使用ZooKeeper提供的原生Java API操作ZooKeeper节点
- CountDownLatch类的使用
- Spring-如何给静态变量注入值
- ZooKeeper的伪分布式集群搭建以及真分布式集群搭建
- zookeeper权限acl与四字命令