开发模板

1. 模板语法

为什么使用Go的模板引擎?

当Helm在开发过程中需要一个模板引擎时,Go标准库中提供的模板引擎是最成熟、最稳定的选择。此外,这个模板引擎有一个安全模型,由Google使用安全策略进行维护。这是最好的选择。

Go模板语法与其他系统的语法相似,能够满足Helm用户的需求。

在模板中有一百多个函数(https://oreil.ly/Xtoya)可供使用。这些函数包括处理数学、字典和列表、反射、散列生成、日期函数等。

参考:

https://helm.sh/zh/docs/chart_template_guide/builtin_objects/

http://www.leiyawu.com/2020/10/04/Helm-Template%E8%AF%AD%E6%B3%95/#%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1

2. 命名模板

参考

https://helm.sh/zh/docs/chart_template_guide/named_templates/

3. 为可维护性构建模板

在templates目录中的模板上执行的结构有限。多个Kubernetes清单可以在同一个YAML文件中,这意味着多个Kubernetes清单的模板也可以在同一个文件中。命名模板可以存在于任何模板文件中,也可以在其他模板文件中引用。NOTES.txt文件模板是向用户显示的特殊文件,测试 。以特殊的方式处理。除此之外,它还是一个空白画布,供你创建模板。

为了帮助创建易于浏览的可维护模板,Helm维护人员推荐了几种模式。推荐这些模式有以下几个原因:

  • 你可能有很长时间不对chart中的模板进行结构修改,然后再回过头来修改。能够快速重新发现布局将使修改过程更快。

  • 其他人将查看chart中的模板。这里的其他人可能是创建chart或使用chart的团队成员。使用者可以(有时也确实会)在安装chart之前先打开它进行检查,或者将检查作为分叉过程的一部分来执行。

  • 调试chart时,使用模板中的某些结构更容易调试。

第一条准则是每个Kubernetes清单应该在它自己的模板文件中,并且该文件应该有一个描述性的名称。

例如,如果只有一个部署,则把模板命名为deployment.yaml。如果你有相同类型的多个清单的情况,例如使用主库和副本库部署数据库的情况,则命名为statefulset-primary.yaml和statefulset-replica.yaml。

第二条准则是将(包含在自己的模板中的)命名模板放入名为_helpers.tpl的文件中,因为这些基本上是其他模板的辅助模板,所以名称是描述性的。

如前所述,名称开头的“_”会使它上升到目录列表的顶部,因此你可以在模板中轻松找到它。

当你使用helm create命令启动一个新chart时,默认情况下,它启动的模板的内容将已经遵守这些准则。

4. 调试模板

4.1 试运行

用于安装、升级、回滚和卸载Helm chart的命令都有一个标志,用于启动试运行和模拟进程,但没有在该进程上完全执行。

这是通过在这些命令上使用–dry-run标志来完成的。例如,如果在anvil chart上的install命令上使用–dry-run标志,则可以使用命令helm install myanvil anvil–dry-run。Helm将渲染模板,检查模板以确保发送给Kubernetes的内容格式是正确的,然后将其发送到输出。输出看起来与正常安装时的输出类似,但会有两个额外的部分:

NAME: mysapp
LAST DEPLOYED: Sat May  7 04:25:50 2022
NAMESPACE: default
STATUS: pending-install
REVISION: 1
HOOKS:

.....

NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=anvil,app.kubernetes.io/instance=mysapp" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace default port-forward $POD_NAME 8080:80

两个新部分是HOOKS和MANIFEST,它们将包含Helm通常会传递给Kubernetes的YAML。不过,它被发送到输出。为了简洁起见,不包括完全生成的YAML,因为那将有一页。

在使用–dry-run如果出现错误,可以根据提示进行排查错误。

利用试运行并不是使用此功能的唯一方法。helm template命令提供了类似的体验,但没有完整的调试功能集。template命令会将template命令转换为YAML。此时,如果无法解析生成的YAML,它将提供一个错误。

它不会根据Kubernetes模式验证YAML。如果apiVersion被转换为foo,template命令不会发出警告。这是因为在使用template命令时,Helm没有与Kubernetes集群通信以获取要验证的模式。

总结: –dry-run比template 排查错误更加严谨,能校验yaml的可执行性,template只是渲染成yaml格式

4.2 获取已安装清单

检索anvil chart实例的清单

$ helm get manifest myapp
---
# Source: anvil/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: myapp-anvil
  labels:
    helm.sh/chart: anvil-0.1.0
    app.kubernetes.io/name: anvil
    app.kubernetes.io/instance: myapp
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
---
# Source: anvil/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-anvil
  labels:
    helm.sh/chart: anvil-0.1.0
    app.kubernetes.io/name: anvil
    app.kubernetes.io/instance: myapp
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: anvil
    app.kubernetes.io/instance: myapp
---
# Source: anvil/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-anvil
  labels:
    helm.sh/chart: anvil-0.1.0
    app.kubernetes.io/name: anvil
    app.kubernetes.io/instance: myapp
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: anvil
      app.kubernetes.io/instance: myapp
  template:
    metadata:
      labels:
        app.kubernetes.io/name: anvil
        app.kubernetes.io/instance: myapp
    spec:
      serviceAccountName: myapp-anvil
      securityContext:
        {}
      containers:
        - name: anvil
          securityContext:
            {}
          image: "nginx:1.16.0"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
            {}

输出将包括所有的清单,在每个新清单的开始处都带有—。

4.3 校验chart代码

$ helm lint anvil/
==> Linting anvil/
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, 0 chart(s) failed

helm lint将向你指出一个问题,并告诉你问题发生在哪里。