Helm介绍
Helm是Kubernetes的包管理器,主要用来管理 Charts。Helm Chart是用来封装Kubernetes原生应用程序的一系列YAML文件。可以在你部署应用的时候自定义应用程序的一些Metadata,以便于应用程序的分发。
对于应用发布者而言,可以通过Helm打包应用、管理应用依赖关系、管理应用版本并发布应用到软件仓库。对于使用者而言,使用Helm后不用需要编写复杂的应用部署文件,可以以简单的方式在Kubernetes上查找、安装、升级、回滚、卸载应用程序。
Helm和Kubernetes之间的关系可以如下类比。
- Helm <–> Kubernetes
- Yum <–> CentOS
Kubernetes的应用编排存在着一些问题,Helm可以用来解决这些问题。
1:管理、编辑与更新大量的Kubernetes配置文件
2:部署一个含有大量配置文件的复杂Kubernetes应用
3:分享和复用Kubernetes配置和应用
4:参数化配置模板支持多个环境
5:管理应用的发布:回滚、diff 和查看发布历史
6:控制一个部署周期中的某一些环节
7:发布后的测试验证
Helm原理
下面两张图描述了 Helm 的几个关键组件 Helm(客户端)、Tiller(服务器)、Repository(Chart 软件仓库)、Chart(软件包)之间的关系以及它们之间如何通信
helm 组件通信:
helm 架构
创建release
- helm 客户端从指定的目录或本地tar文件或远程repo仓库解析出chart的结构信息
- helm 客户端指定的 chart 结构和 values 信息通过 gRPC 传递给 Tiller
- Tiller 服务端根据 chart 和 values 生成一个 release
- Tiller 将install release请求直接传递给 kube-apiserver
删除release
- helm 客户端从指定的目录或本地tar文件或远程repo仓库解析出chart的结构信息
- helm 客户端指定的 chart 结构和 values 信息通过 gRPC 传递给 Tiller
- Tiller 服务端根据 chart 和 values 生成一个 release
- Tiller 将delete release请求直接传递给 kube-apiserver
更新release
- helm 客户端将需要更新的 chart 的 release 名称 chart 结构和 value 信息传给 Tiller
- Tiller 将收到的信息生成新的 release,并同时更新这个 release 的 history
- Tiller 将新的 release 传递给 kube-apiserver 进行更新
chart基本结构
Helm的打包格式叫做chart,所谓chart就是一系列文件, 它描述了一组相关的 k8s 集群资源。Chart中的文件安装特定的目录结构组织, 最简单的chart 目录如下所示:
./
├── charts
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── serviceaccount.yaml
│ ├── service.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
- charts 目录存放依赖的chart
- Chart.yaml 包含Chart的基本信息,包括chart版本,名称等
- templates 目录下存放应用一系列 k8s 资源的 yaml 模板
- _helpers.tpl 此文件中定义一些可重用的模板片断,此文件中的定义在任何资源定义模板中可用
- NOTES.txt 介绍chart 部署后的帮助信息,如何使用chart等
- values.yaml 包含了必要的值定义(默认值), 用于存储 templates 目录中模板文件中用到变量的值
Helm安装
下载helm v3.0.2,地址 https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz
上传并解压。
tar zxvf helm-v3.0.2-linux-amd64.tar.gz
将helm拷贝到系统path路径下,以下为 /usr/local/bin/helm
mv linux-amd64/helm /usr/local/bin/helm
查看helm版本
helm version
version.BuildInfo{Version:"v3.0.0", GitCommit:"e29ce2a54e96cd02ccfce88bee4f58bb6e2a28b6", GitTreeState:"clean", GoVersion:"go1.13.4"}
使用
增加常用chart源。helm提供了常用的chart源,可以在helm的hub库:https://hub.helm.sh/charts
查看提供的各种应用的chart库,左边是各种官方chart库,右边是chart库中的应用chart。
#除了阿里云应该都需要科学,stable是官方的,aliyuncs最快
helm repo add stable https://kubernetes-charts.storage.googleapis.com
helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add aliyuncs https://apphub.aliyuncs.com
helm repo add aliyun-stable https://acs-k8s-ingress.oss-cn-hangzhou.aliyuncs.com/charts
#查看chart列表
helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com
incubator https://kubernetes-charts-incubator.storage.googleapis.com
bitnami https://charts.bitnami.com/bitnami
aliyuncs https://apphub.aliyuncs.com
aliyun-stable https://acs-k8s-ingress.oss-cn-hangzhou.aliyuncs.com/charts
#更新依赖源
helm repo update
采用Deployment+多Replica的部署形式安装ingress
修改对应的镜像源:image:quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.31.1
kubectl apply -f ingress.yaml
查看对应的ingress pod是否有启动成功
kubectl get po -n ingress-nginx
kubectl describe pod pod_id -n ingress-nginx
#查看ingress服务是否正常
kubectl get svc -n ingress-nginx
#删除辅助的POD
kubectl delete pod xxxxx -n ingress-nginx
查看对应的节点端口
kubectl get svc -n ingress-nginx
浏览器用物理节点IP:31434
访问,看是否正常
用ingress对服务做路由
ingress概述
k8s 对外暴露服务(service)主要有两种方式:NotePort, LoadBalance, 此外externalIPs也可以使各类service对外提供服务
- 但是当集群服务很多的时候,NodePort方式最大的缺点是会占用很多集群机器的端口;
- LB方式最大的缺点则是每个service一个LB又有点浪费和麻烦,并且需要k8s之外的支持;
- 而ingress则只需要一个NodePort或者一个LB就可以满足所有service对外服务的需求。
ingress工作机制大致可以用下图表示:
实际上,ingress相当于一个7层的负载均衡器,是k8s对反向代理的一个抽象。大概的工作原理也确实类似于Nginx,可以理解成在 Ingress 里建立一个个映射规则 , ingress Controller 通过监听 Ingress这个api对象里的配置规则并转化成 Nginx 的配置(kubernetes声明式API和控制循环) , 然后对外部提供服务。ingress包括:ingress controller 和 ingress resources
ingress controller:核心是一个deployment,实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要编写的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是NodePort或者LoadBalancer。
ingress resources:这个就是一个类型为Ingress的k8s api对象了,这部分则是面向开发人员。
Kubernetes给出的方案就是Ingress,Ingress包含了两大主件Ingress Controller和Ingress。
Ingress解决的是新的服务加入后,域名和服务的对应问题,基本上是一个ingress的对象,通过yaml进行创建和更新进行加载。
Ingress Controller是将Ingress这种变化生成一段Nginx的配置,然后将这个配置通过Kubernetes API写到Nginx的Pod中,然后reload.(注意:写入 nginx.conf 的不是service的地址,而是service backend 的 pod 的地址,避免在 service 在增加一层负载均衡转发)
从上图中可以很清晰的看到,实际上请求进来还是被负载均衡器拦截,比如 nginx,然后 Ingress Controller 通过跟 Ingress 交互得知某个域名对应哪个 service,再通过跟 kubernetes API 交互得知 service 地址等信息;综合以后生成配置文件实时写入负载均衡器,然后负载均衡器 reload 该规则便可实现服务发现,即动态映射
了解了以上内容以后,这也就很好的说明了我为什么喜欢把负载均衡器部署为 Daemon Set;因为无论如何请求首先是被负载均衡器拦截的,所以在每个 node 上都部署一下,同时 hostport 方式监听 80 端口;那么就解决了其他方式部署不确定 负载均衡器在哪的问题,同时访问每个 node 的 80 都能正确解析请求;如果前端再 放个 nginx 就又实现了一层负载均衡。
Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。
Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。
ingress-nginx 部署
ingress调度的是后端的service,而不是pod
ingress调度hello-service这个服务
创建对应的hello-ingress.yaml部署文件
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/service-upstream: "true"
spec:
rules:
- host: hello.abc.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-service
port:
number: 80
进行部署
kubectl apply -f hello-ingress.yaml