k8s 通过helm发布应用

198 阅读6分钟

什么是helm?


Helm 是 Kubernetes 的包管理器。Helm 是查找、分享和使用软件构建 Kubernetes 的最优方式。

在红帽系的Linux中我们使用yum来管理RPM包,类似的,在K8s中我们可以使用helm来管理资源对象(Deployment、Service、Ingress...)实现K8s中应用的快速发布、升级、维护和分享。helm官方文档

helm中的几个关键概念


  • Chart 是Helm 中的包。包含一组用于部署应用程序的 K8s 资源对象定义(即资源清单的集合)。
  • Repository 即chart图表的仓库。我们可以从网络仓库中搜索、下载和安装chart。
  • Release 即chart部署后的实例。通过helm install命令,在 Kubernetes 集群上安装该chart的新版本。

helm实现哪些功能?


Helm (v3版本)为 K8s 提供的功能包括:

  1. 通过单个 CLI 命令部署 Kubernetes 应用(chart)。实现本地chart的创建、管理和发布。
  2. Helm 将chart中资源对象配置文件模板化,实现在多个集群环境中重用一个 Helm chart,同时可打包进行网络共享。
  3. Helm 通过自动维护发布的所有版本来简化 Kubernetes 应用程序的回滚,防止部署问题。
  4. 通过helm轻松实现 Kubernetes 中工作负载的 CI/CD 管道。

helm 基本使用


Helm可以用源码或构建的二进制版本安装。参考:安装Helm

Artifact Hub 是一个开源项目,我们通过它来查找、安装或发布k8s应用。image-20220213193213721

除了通过web搜索,也可以通过helm命令行方式:

#helm search hub redis
URL                                                 CHART VERSION   APP VERSION         DESCRIPTION
https://hub.helm.sh/charts/bitnami/redis            16.4.0          6.2.6               Redis(TM) is an opensource, advanced key-value...
https://hub.helm.sh/charts/wenerme/redis            16.4.0          6.2.6               Redis(TM) is an opensource, advanced key-value...
...

找到redis版本为6.2.6,chart版本16.4.0的包,访问 url https://hub.helm.sh/charts/bitnami/redis 新版本已被重定向到artifacthub.io

image-20220213195117548

由图上信息可以知redis是一个来自Bitnami仓库(由VMware主导的开源软件仓库),通过验证的版本,仓库地址https://charts.bitnami.com/bitnami

要安装这个应用我们应先将Bitnami仓库添加到本地配置中。

#helm repo add bitnami https://charts.bitnami.com/bitnami

安装redis,release名称为redis-dev

# helm install redis-dev bitnami/redis
NAME: redis-dev
LAST DEPLOYED: Sun Feb 13 20:09:30 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: redis
CHART VERSION: 16.4.0
APP VERSION: 6.2.6

这样我们可以轻松发布一个一主三从的redis集群到k8s中

# helm list
NAME                            NAMESPACE   REVISION    UPDATED                                 STATUS      CHART   APP VERSION
redis-dev                       default     1           2022-02-13 20:09:30.755534484 +0800 CST deployed    redis-16.4.0

Helm 通过向资源对象中添加标签来跟踪安装在 Kubernetes 集群上的chart。这些标签看起来像app.kubernetes.io/managed-by=Helmapp.kubernetes.io/instance: myapp

#  kubectl get all -l app.kubernetes.io/instance=redis-dev
NAME                       READY   STATUS    RESTARTS   AGE
pod/redis-dev-master-0     1/1     Running   0          27m
pod/redis-dev-replicas-0   1/1     Running   0          27m
pod/redis-dev-replicas-1   1/1     Running   0          24m
pod/redis-dev-replicas-2   1/1     Running   0          23m
​
NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/redis-dev-headless   ClusterIP   None            <none>        6379/TCP   27m
service/redis-dev-master     ClusterIP   10.96.52.104    <none>        6379/TCP   27m
service/redis-dev-replicas   ClusterIP   10.96.230.162   <none>        6379/TCP   27m
​
NAME                                  READY   AGE
statefulset.apps/redis-dev-master     1/1     27m
statefulset.apps/redis-dev-replicas   3/3     27m

删除redis-dev的发布,将会移除标签跟踪的所有资源对象。

# helm uninstall redis-dev
release "redis-dev" uninstalled

创建自己的helm chart


显然大多数时候我们更想发布自己的应用到K8s中或者需要对将要发布的开源软件做一些配置上的修改,所以我们可以通过helm自己构建一个chart或者使用helm pull下载一个chart做修改后再上传的内部或外部仓库中。

下面来创建一个简易的nginx chart

# helm create chart-nginx
Creating chart-nginx

chart的目录结构,你可以删除模板中的所有文件自建或使用默认模板

# tree chart-nginx/
chart-nginx/
├── charts  #依赖的chart目录
├── Chart.yaml #chart版本信息
├── templates #资源对象模板目录
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt #提示信息
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml #模板值
​
3 directories, 10 files

Chart.yaml声明了版本信息,我们可以进行自定义

# Chart.yaml
apiVersion: v2
name: chart-nginx
description: A Helm chart for Kubernetes
type: application
version: 0.1.0 #chart版本
appVersion: 1.0.0 #app版本

helm默认创建的模板文件deployment.yaml如下:

image-20220213233227742

helm 采用go模板,官方文档Chart模板

通过deployment模板中可以看到image的值会引用value文件中定义的image.repository和tag,如果tag值为空则返回默认引用Chart.appVersion的值。

接着根据需要更新value.yaml文件中imageservice等相关信息,同时关闭serviceAccount、ingress、hpa的创建。

image-20220214001633434

模板文件service.yaml定义好了type和pod的引用。

image-20220214001344997

一个基本的nginx chart创建好了。通过helm template 命令渲染模板查看一下

# helm template chart-nginx
---
# Source: chart-nginx/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: RELEASE-NAME-chart-nginx
  labels:
    helm.sh/chart: chart-nginx-0.1.0
    app.kubernetes.io/name: chart-nginx
    app.kubernetes.io/instance: RELEASE-NAME
    app.kubernetes.io/version: "1.0.0"
    app.kubernetes.io/managed-by: Helm
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: chart-nginx
    app.kubernetes.io/instance: RELEASE-NAME
---
# Source: chart-nginx/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: RELEASE-NAME-chart-nginx
  labels:
    helm.sh/chart: chart-nginx-0.1.0
    app.kubernetes.io/name: chart-nginx
...

再通过helm lint检查语法

==> Linting chart-nginx
[INFO] Chart.yaml: icon is recommended
​
1 chart(s) linted, 0 chart(s) failed

ok,通过helm install发布到k8s,参照NOTES说明可进行访问。

# helm install chart-nginx --generate-name
NAME: chart-nginx-1644771770
LAST DEPLOYED: Mon Feb 14 01:02:50 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services chart-nginx-1644771770)
  export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT

查看资源正常。

# kubectl get all -l app.kubernetes.io/name=chart-nginx
NAME                                          READY   STATUS    RESTARTS   AGE
pod/chart-nginx-1644771770-69bbb4fdf8-gqdk7   1/1     Running   0          3m59s
pod/chart-nginx-1644771770-69bbb4fdf8-wwxw2   1/1     Running   0          3m59s
​
NAME                             TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
service/chart-nginx-1644771770   NodePort   10.96.231.61   <none>        80:32631/TCP   3m59s
​
NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/chart-nginx-1644771770   2/2     2            2           3m59s
​
NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/chart-nginx-1644771770-69bbb4fdf8   2         2         2       3m59s

通过仓库分发应用


首先通过helm packge将chart-nginx打包

# helm package chart-nginx
Successfully packaged chart and saved it to: .../../chart-nginx-0.1.0.tgz

建立chart私有仓库,可参考开源项目chartmuseum,如有必要你也可将仓库提交至artifacthub发布到互联网。

chart-nginx-0.1.0.tgz上传至仓库后,通过curl列出chart信息如下:

# curl http://192.168.1.123:8088/api/charts |python -m json.tool
{
    "chart-nginx": [
        {
            "apiVersion": "v2",
            "appVersion": "1.0.0",
            "created": "2022-02-13T17:37:43.653117345Z",
            "description": "A Helm chart for Kubernetes",
            "digest": "58a687be62a2a2a2b1dd177675bbc5aa49ac754df2219149bb4798636662b57c",
            "name": "chart-nginx",
            "type": "application",
            "urls": [
                "charts/chart-nginx-0.1.0.tgz"
            ],
            "version": "0.1.0"
        }
    ]
}

将仓库添加到你的其他k8s集群helm中,实现应用共享和发布。

# helm repo add chartmuseum http://192.168.1.123:8088
"chartmuseum" has been added to your repositories

搜索chart-nginx

# helm search repo chart-nginx
NAME                    CHART VERSION   APP VERSION DESCRIPTION
chartmuseum/chart-nginx 0.1.0           1.0.0       A Helm chart for Kubernetes

通过仓库发布chart-nginx

# helm install my-chart-nginx chartmuseum/chart-nginx
NAME: my-chart-nginx
LAST DEPLOYED: Mon Feb 14 01:54:34 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
...

以上我们对helm进行了基本介绍以及如何创建一个自己的helm chart,如何结合私有仓库chartmuseum在K8s中发布应用。

希望小作文对你有些许帮助,如果内容有误请指正。