侧边栏壁纸
  • 累计撰写 53 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

K8s Helm 3

zhanjie.me
2020-11-21 / 0 评论 / 0 点赞 / 1 阅读 / 0 字

3.1 Helm Hooks 简介

Helm 提供了 Hook 机制,可以允许 Chart 开发人员在 Release 生命周期中的某些节点进行干预。Hooks 的用途通常有:

  • 加载其它 Charts 之前,在安装过程中加载 ConfigMap 或 Secret。
  • 在安装新 Chart 之前,执行作业来备份数据库;然后在升级后执行第二个作业来恢复数据。
  • 在删除 Release 之前运行作业用于停止服务。

Helm 的工作方式与模板一样,但是它们有特殊的注释,可以使 Helm 以不同的方式使用它们。

Helm 的基本用法是在 metadata 中以 annotations 的方式声明,示例如下:

---
metadata:
  annotations:
    "helm.sh/hook": "pre-upgrade"

可用的 Hooks 值

有如下已经定义好了的 Hooks 供我们使用,列表如下:

annotations 的值 描述
pre-install 预安装。在模板渲染后,kubernetes 创建资源之前执行
post-install 安装后。kubernetes 创建资源后执行
pre-delete 预删除。在 kubernetes 删除任何资源之前执行删除请求
post-delete 删除后。删除所有 release 资源后执行
pre-upgrade 升级前。在模板渲染后,但在任何资源升级之前执行
post-upgrade 升级后。在所有资源升级后执行
pre-rollback 预回滚。在模板渲染后,任何资源回滚前执行
post-rollback 回滚后。在修改所有资源后执行

生命周期

Hooks 允许开发人员在 release 生命周期的关键节点执行操作。比如,我们执行 helm install 安装命令时 release 的生命周期如下所示:

  • 用户运行命令 helm install foo。
  • 调用 Helm 仓库的安装 API。
  • 经过验证后,仓库渲染 foo 模板。
  • 仓库加载渲染后的模板到 kubernetes 中。
  • 仓库返回 release 资源对象(和其他数据)到客户端。
  • 客户端退出。

Helm 为 install 生命周期定义了两个 Hooks:pre-install 和 post-install。如果对于 foo Chart 使用这两个 Hooks,那么生命周期就变成如下所示:

  • 用户运行命令 helm install foo。
  • 调用 Helm 仓库的安装 API。
  • 安装 crds/ 文件夹中定义的资源对象。
  • 经过验证后,仓库渲染 foo 模板。
  • 仓库准备执行 pre-install hook(加载 hook 资源到 kubernetes 中)。
  • 仓库根据权重对 hooks 进行排序(默认权重为 0,相同权重的 hooks 会按照升序进行排序)。
  • 仓库首先加载最低权重的 hooks(从负到正)。
  • 仓库等待,直到 hook 准备就绪(除了 CRDs)。
  • 仓库加载渲染后的模板到 kubernetes 中。如果设置了 --wait 标志,仓库将等待直到所有资源都处于就绪状态,在就绪之前不会运行 post-upgrade hook。
  • 仓库执行 post-upgrade hook(加载 hook 资源到 kubernetes 中)。
  • 仓库等待,直到 hook 准备就绪。
  • 仓库返回 release 资源对象(和其他数据)到客户端。
  • 客户端退出。

等到 hook 准备就绪的特性,取决于 hook 中声明的资源对象类型,比如是 Job 或是 Pod 资源类型,Helm 将会等待直到作业完成。如果这个 hook 失败,那么 Release 的发布也是失败的。

Hook 创建的资源不作为 Release 的一部分进行跟踪或管理。当 Helm 验证 Hook 达到了就绪状态,就不会再管该 Hook 资源了。换句话说,如果使用 Hook 创建资源,无法使用 helm uninstall 删除资源,如果想要销毁这类资源,需要将 helm.sh/hook-delete-policy 注释添加到 hook 模板文件。


3.2 Hook 用例

Hook 的写法和普通模板是一样的,可以使用模板函数和对象,比如:.Values、.Release、.Template等,唯一和普通模板有区别的地方是在 metadata 部分包含一些特殊的注释 annotations。

比如需要在安装后 post-install 执行 hook 运行一个 job,向 templates/post-install-job.yaml 文件中写入如下内容:

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}"
  labels:
    app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
  annotations:
    # 通过添加 annotations,这个资源会被视为 hook。如果没有这行注释,这个 Job 资源只会当做 Release 的一部分。
    "helm.sh/hook": post-install  # hook 的类型
    "helm.sh/hook-weight": "-5"   # hook 的权重
    "helm.sh/hook-delete-policy": hook-succeeded   # hook 的删除方式
spec:
  template:
    metadata:
      name: "{{ .Release.Name }}"
      labels:
        app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
        app.kubernetes.io/instance: {{ .Release.Name | quote }}
        helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    spec:
      restartPolicy: Never
      containers:
      - name: post-install-job
        image: "alpine:3.3"
        command: ["/bin/sleep","{{ default "10" .Values.sleepyTime }}"]

一个资源可以部署多个 hook,写法如下:

annotations:
  "helm.sh/hook": post-install,post-upgrade

为 hook 设置权重可以帮助确定执行顺序,权重可以是正数或是负数,但是必须是字符串。当 Helm 开始执行某个特定类型的 hook 时(比如:pre-install hooks、post-install hooks),会按升序对这些 hook 进行排序:

annotations:
  "helm.sh/hook-weight": "5"

还可以定义 hook 的删除策略:

annotations:
  "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded

与删除策略有关的注释值有:

  • before-hook-creation:在新 hook 创建之前删除以前的 hook。这是默认的删除策略。
  • hook-succeeded:在 hook 成功执行后删除 hook 资源。
  • hook-failed:如果 hook 在执行期间失败就删除该 hook 资源。

比如现在使用 Helm 部署一个 nginx Pod,并且干扰正常的安装过程,设置 pre-install 和 post-install。先创建一个 Chart:

$ helm create nginx-helm
Creating nginx-helm

然后在 nginx-helm/templates 目录下新建 pre-install-HookPod.yaml 文件,并向其中写入如下内容:

apiVersion: v1
kind: Pod
metadata:
  name: pre-install-hook-pod
  annotations:
    "helm.sh/hook": "pre-install"
spec:
  containers:
    - name: hook1-container
      image: busybox
      imagePullPolicy: IfNotPresent
      command:
        ["sh", "-c", "echo The pre-install hook Pod is running && sleep 10"]
  restartPolicy: Never
  terminationGracePeriodSeconds: 0

然后在该目录下新建 post-install-HookPod.yaml 文件,并向其中写入如下内容:

apiVersion: v1
kind: Pod
metadata:
  name: post-install-hook-pod
  annotations:
    "helm.sh/hook": "post-install"
spec:
  containers:
    - name: hook1-container
      image: busybox
      imagePullPolicy: IfNotPresent
      command: ["sh", "-c", "echo post-install hook Pod is running && sleep 10"]
  restartPolicy: Never
  terminationGracePeriodSeconds: 0

现在执行安装:

$ helm install mynginx ./nginx-helm
NAME: mynginx
LAST DEPLOYED: Sat Nov 21 11:13:02 2020
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace kube-system -l "app.kubernetes.io/name=nginx-helm,app.kubernetes.io/instance=mynginx" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace kube-system $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace kube-system port-forward $POD_NAME 8080:$CONTAINER_PORT

现在查看所有的 Pod 状态:

$ kubectl get pods
NAME                                       READY   STATUS      RESTARTS   AGE
mynginx-nginx-helm-84f8bc846d-jht9k        1/1     Running     0          57s
post-install-hook-pod                      0/1     Completed   0          57s
pre-install-hook-pod                       0/1     Completed   0          69s

当不需要的时候,执行删除 nginx:

$ helm uninstall mynginx
release "mynginx" uninstalled

但hook需要手动删除:

$ kubectl get pods
NAME                                       READY   STATUS      RESTARTS   AGE
post-install-hook-pod                      0/1     Completed   0          3m15s
pre-install-hook-pod                       0/1     Completed   0          3m27s
$ kubectl delete pod post-install-hook-pod pre-install-hook-pod
pod "post-install-hook-pod" deleted
pod "pre-install-hook-pod" deleted

3.3 Chart 仓库

下面介绍如何创建和使用 Helm Chart repo。仓库的主要用途是存储和分享 chart 包。

创建 Chart 仓库

Chart 仓库是带有一个 index.yaml 文件和任意个打包文件并能回答 GET 请求的 HTTP 服务器。如果想要分享 Chart 包,最好是先将其上传到仓库中。

当选择托管 Chart 仓库时可以有多种选择,比如:Google 云端存储,Amazon S3 存储桶,Github Pages,或者是搭建自己的服务器。

Chart 仓库结构

一个 Chart 仓库由两部分组成:

  • index.yaml 文件:包含 Chart 仓库中所有 Chart 的索引。
  • Chart 包:这些打包文件通常都是在 index.yaml 文件中列出的。

比如,https://example.com/charts 仓库的文件结构如下所示:

charts/
|
|- index.yaml
|
|- alpine-0.1.2.tgz
|
|- alpine-0.1.2.tgz.prov

在这个例子中,index.yaml 文件中只包含一个 Chart 的信息。即:Alpine Chart,对应的下载链接地址为 https://example.com/charts/alpine-0.1.2.tgz。

index.yaml 索引文件

index.yaml 索引文件中包含关于包的元数据。使用 helm repo index 命令根据包含打包文件的本地目录生成索引文件。

下面是 index.yaml 文件的一个示例:

apiVersion: v1
entries:
  alpine:
    - created: 2016-10-06T16:23:20.499814565-06:00
      description: Deploy a basic Alpine Linux pod
      digest: 99c76e403d752c84ead610644d4b1c2f2b453a74b921f422b9dcb8a7c8b559cd
      home: https://helm.sh/helm
      name: alpine
      sources:
        - https://github.com/helm/helm
      urls:
        - https://technosophos.github.io/tscharts/alpine-0.2.0.tgz
      version: 0.2.0
    - created: 2016-10-06T16:23:20.499543808-06:00
      description: Deploy a basic Alpine Linux pod
      digest: 515c58e5f79d8b2913a10cb400ebb6fa9c77fe813287afbacf1a0b897cd78727
      home: https://helm.sh/helm
      name: alpine
      sources:
        - https://github.com/helm/helm
      urls:
        - https://technosophos.github.io/tscharts/alpine-0.1.0.tgz
      version: 0.1.0
  nginx:
    - created: 2016-10-06T16:23:20.499543808-06:00
      description: Create a basic nginx HTTP server
      digest: aaff4545f79d8b2913a10cb400ebb6fa9c77fe813287afbacf1a0b897cdffffff
      home: https://helm.sh/helm
      name: nginx
      sources:
        - https://github.com/helm/charts
      urls:
        - https://technosophos.github.io/tscharts/nginx-1.1.0.tgz
      version: 1.1.0
generated: 2016-10-06T16:23:20.499029981-06:00

托管 Chart 库

这里介绍两种常用的方式,一种是使用 GitHub Pages 托管,另一种是使用普通的 Web 服务器。

方法一:使用 GitHub Pages 托管

GitHub 可以使用两种不同的方式提供静态 web 页面:

  1. 通过配置项目来提供 docs/ 目录下的文件。
  2. 通过配置项目为特定分支提供服务。

这里采用第二种方式提供演示。在仓库中新建名为 gh-pages 的分支。

image-mjskppqr.png

然后将 gh-pages 分支设置为 Github Pages,点击 repo Settings,向下滚动到 GitHub Pages,并按照如下方式进行设置:

image-qjfemgwy.png

方法二:使用普通的 Web 服务器

如果配置普通的 Web 服务器存储 Helm Chart,需要确保:

  • index.yaml 文件和 Chart 都处于服务器目录中。
  • 无需认证就可以访问 index.yaml 文件。
  • yaml 文件格式是正确的。

管理 Chart 库

准备好打包 Chart,创建一个新目录,然后将打包 Chart 移动到该目录下:

# 打包
$ helm package docs/examples/alpine/
# 创建新目录
$ mkdir fantastic-charts
# 将打包好的文件移动到新目录下
$ mv alpine-0.1.0.tgz fantastic-charts/
# helm repo index 命令为 fantastic-charts 目录生成 index.yaml 文件,https://xxx.com 表示的是远程库的 URL
$ helm repo index fantastic-charts --url https://xxx.com

如果在 fantastic-charts 目录下添加了新文件,可以使用 helm repo index 命令重新生成新的索引,或是使用 --merge 参数向 index.yaml 文件增量添加新 Chart 索引。

如果要分享 Chart,只需要提供仓库 URL 即可,完整命令为 helm repo add [NAME] [URL]。比如:

$ helm repo add fantastic-charts https://xxx.com
$ helm repo list
fantastic-charts    https://xxx.com

3.4 配置 Harbor 为 Helm 的存储仓库

介绍

Harbor 也是 CNCF 基金会托管的开源项目,它主要是作为 kubernetes 的云原生存储库。之前用于镜像管理,在 V1.6 版本中增加了对于 Helm Charts 的管理功能。

本次挑战需要完成如下的步骤:

1.在集群中使用 Helm 安装 Harbor。

添加harbor库

$ helm repo add goharbor https://helm.goharbor.io
"goharbor" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "goharbor" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm search repo goharbor
NAME                                            CHART VERSION   APP VERSION DESCRIPTION
goharbor/harbor                                     1.5.1           2.1.1       An open source trusted cloud native registry th...

查看harbor安装文件:

$ helm install --dry-run --debug testHarbor goharbor/harbor >> harborHelmInstall.out
$ ls ~/.cache/helm/repository/harbor-1.5.1.tgz
$ tar zxf ~/.cache/helm/repository/harbor-1.5.1.tgz
$ tree harbor
harbor
├── cert
│   ├── tls.crt
│   └── tls.key
├── Chart.yaml
├── conf
│   ├── clair.yaml
│   ├── notary-server.json
│   └── notary-signer.json
├── LICENSE
├── README.md
├── templates
│   ├── chartmuseum
│   │   ├── chartmuseum-cm.yaml
│   │   ├── chartmuseum-dpl.yaml
│   │   ├── chartmuseum-pvc.yaml
│   │   ├── chartmuseum-secret.yaml
│   │   ├── chartmuseum-svc.yaml
│   │   └── chartmuseum-tls.yaml
│   ├── clair
│   │   ├── clair-dpl.yaml
│   │   ├── clair-secret.yaml
│   │   ├── clair-svc.yaml
│   │   └── clair-tls.yaml
│   ├── core
│   │   ├── core-cm.yaml
│   │   ├── core-dpl.yaml
│   │   ├── core-secret.yaml
│   │   ├── core-svc.yaml
│   │   └── core-tls.yaml
│   ├── database
│   │   ├── database-secret.yaml
│   │   ├── database-ss.yaml
│   │   └── database-svc.yaml
│   ├── _helpers.tpl
│   ├── ingress
│   │   ├── ingress.yaml
│   │   └── secret.yaml
│   ├── internal
│   │   └── auto-tls.yaml
│   ├── jobservice
│   │   ├── jobservice-cm-env.yaml
│   │   ├── jobservice-cm.yaml
│   │   ├── jobservice-dpl.yaml
│   │   ├── jobservice-pvc.yaml
│   │   ├── jobservice-secrets.yaml
│   │   ├── jobservice-svc.yaml
│   │   └── jobservice-tls.yaml
│   ├── nginx
│   │   ├── configmap-https.yaml
│   │   ├── configmap-http.yaml
│   │   ├── deployment.yaml
│   │   ├── secret.yaml
│   │   └── service.yaml
│   ├── notary
│   │   ├── notary-secret.yaml
│   │   ├── notary-server.yaml
│   │   ├── notary-signer.yaml
│   │   └── notary-svc.yaml
│   ├── NOTES.txt
│   ├── portal
│   │   ├── configmap.yaml
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── tls.yaml
│   ├── redis
│   │   ├── service.yaml
│   │   └── statefulset.yaml
│   ├── registry
│   │   ├── registry-cm.yaml
│   │   ├── registry-dpl.yaml
│   │   ├── registry-pvc.yaml
│   │   ├── registry-secret.yaml
│   │   ├── registry-svc.yaml
│   │   └── registry-tls.yaml
│   └── trivy
│       ├── trivy-secret.yaml
│       ├── trivy-sts.yaml
│       ├── trivy-svc.yaml
│       └── trivy-tls.yaml
└── values.yaml

这里为了方便使用,需要对官方提供的 Chart 进行一定的修改,包括:

  • 关闭持久存储。 --set persistence.enabled=false
  • 关闭 TLS 认证。--set expose.tls.enabled=false
  • 配置服务类型为 NodePort,并指定外部访问地址为 http://192.168.0.32:30002 Shell --set expose.type=nodePort # 上面已经关闭TLS认证了,这行执行时也不采用 --set expose.nodePort.ports.https=null # 以下两行设置与默认值相同,执行时不采用 --set expose.nodePort.ports.http.port=80 --set expose.nodePort.ports.http.nodePort=30002 # 设置externalURL, --set externalURL=http://192.168.0.32:30002

执行创建:

$ helm install --set persistence.enabled=false --set expose.tls.enabled=false --set expose.type=nodePort --set externalURL=http://192.168.0.32:30002 harbor goharbor/harbor
NAME: harbor
...
NOTES:
Please wait for several minutes for Harbor deployment to complete.
Then you should be able to visit the Harbor portal at http://192.168.0.32:30002
For more details, please visit https://github.com/goharbor/harbor

2.登录 Harbor 页面,创建测试仓库。

当 Harbor 部署完成后,在浏览器访问http://192.168.0.32:30002,登录时默认的账号名为 admin,密码为 Harbor12345。

image-prwktfov.png

创建测试仓库,创建测试用户

image-krertcqj.png

image-wmoilmay.png

3.配置本地 Helm 推送 Chart 到 Harbor。

在 Helm 中添加远端仓库

$ helm repo add repo_test http://192.168.0.32:30002/chartrepo/chart_repo
"repo_test" has been added to your repositories

安装 helm-push 插件

$ helm plugin install https://github.com/chartmuseum/helm-push
Downloading and installing helm-push v0.9.0 ...
https://github.com/chartmuseum/helm-push/releases/download/v0.9.0/helm-push_0.9.0_linux_amd64.tar.gz
Installed plugin: push

从标准仓库中获取一个 MySQL Chart 包

$ helm fetch stable/mysql
$ ls mysql-1.6.9.tgz
mysql-1.6.9.tgz

将打包好的chart包推送到远端仓库中,需要制定user和password。

$ helm push mysql-1.6.9.tgz repo_test -u admin -p Harbor12345
Pushing mysql-1.6.9.tgz to repo_test...
Done.
0

评论区