3.chart命名模版及文件访问

发布时间 2023-12-12 13:55:40作者: 老夫聊发少年狂88

1.命名模版

1.1 什么是命名模版

1.2 _helpers.tpl文件

1.3 定义和调用命名模板

2. 内置对象Files

2.1 Files基本介绍

2.2 Files.Get

2.3 Files.Glob

2.4 Files读入TLS文件

3. 为Ingress资源注入TLS

3.1 准备Values配置文件

3.2 准备Secret资源

3.3 准备Ingress资源

3.4 测试并验证资源文件

4. NOTES.txt

=================================================================

1.命名模版
1.1 什么是命名模版
命名模版可以理解为是Chart中的可重复用的代码块。它是在一个命名模版文件中定义的,可以被其他templates模版文件调用。这种机制可以帮助我们避免代码重复,提高代码的可维护性。
假设: 在templates下的模版文件中,需要多次使用app和release这个标签时,我们就可以在命名模版文件中定义这个标签。而后在模版文件中反复调用。
1.define是创建命名模版的关键字,“mychart.labels”是这个模版的名称,app: myapprelease: {{ .Release.Name }}是模版的内容

{{- define "mychart.labels" }}
app: myapp
release: {{ .Release.Name }}
{{- end }}

2.然后,就可以在其他模版中使用include关键字来调用这个模板名称:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    {{- include "mychart.labels" . |nindent 4 }}   #include是调用命名模版的语句   . 是传递给模板的上下文  nindent 4 表示向右缩进4个空格

通过使用命名模版,我们可以将常用的代码块抽取出来,避免在多个地方重复编写相同的代码。
需要注意的是命名模版的名称是全局的,也就是说,如果你在亮哥命名模版中定义了相同的名称,那么后定义的那个命名模版会覆盖前面定义的命名模版。为了避免这种情况,我们通常会在命名模版的名称前面加上chart的名称作为前缀,如“mychart.labels”.

1.2 _helpers.tpl文件
在chart中 helpers.tpl文件通常是定义命名模版。由于_helpers.tpl文件的名称以下划线()开头,因此helm不会将它渲染为Kubernetes对象。因此该文件不会生成kubernetes资源,而是提供辅助功能,帮助我们编写和组织模版。

{{/* 创建默认的app应⽤名称 */}}
{{- define "app.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

逐⾏解析:
1、 {{- define "app.fullname" -}} :这⾏代码定义了⼀个名为"app.fullname" 的命名模板。define 是定义命名模板的关键字。
2、 {{- if .Values.fullnameOverride }} :它检查.Values.fullnameOverride是否被设置。
3、如果 .Values.fullnameOverride 被设置了值,那么这段代码 {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 会被执⾏,它将 .Values.fullnameOverride 的值截断⾄最多 63 个字符,并移除结果字符串后缀的 "-"
4、 {{- else }} :如果 .Values.fullnameOverride 没有被设置值,那么 else分⽀就会被执⾏。
5、 {{- $name := default .Chart.Name .Values.nameOverride }} :这⾏代码声明了⼀个变量 $name ,如果 .Values.nameOverride 被设置了,那么 $name 的值就是 .Values.nameOverride ,否则 $name 的值就是 .Chart.Name
6、 {{- if contains $name .Release.Name }} :再次进⼊判断逻辑,它会检查 .Release.Name 是否包含 $name
7、如果 .Release.Name 包含 $name ,那么 {{- .Release.Name | trunc 63 | trimSuffix "-" }} 这⾏代码就会被执⾏。它将 .Release.Name 的值截断⾄最多63 个字符,并移除结果字符串后缀的 "-"
8、如果 .Release.Name 不包含 $name ,那么会执⾏这段代码 {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} :这⾏代码将 .Release.Name$name 连接起来 ,连接符为 "-" ,然后将结果字符串截断⾄最多 63个字符,并移除结果字符串后缀的 "-"

1.3 定义和调用命名模板
1.编辑app/templates/_helpers.tpl文件,定义命名模板

[root@k8s-master01 helm]# cat app/templates/_helpers.tpl
{{/* 定义标签 */}}
{{- define "app.web.labels" -}}
role: web
version: {{ .Chart.Version }}
{{- end }}

{{/* 定义标签选择器 */}}
{{- define "app.web.selector" -}}
role: web
version: {{ .Chart.Version }}
{{- end }}

2.编辑app/templates/deployment.yaml引用命名模版

cat app/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "app.fullname" . }}
spec:
  replicas: {{ .Values.replicaCount | default 1 }}
  selector:
    matchLabels:
      {{- include "app.web.selector" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "app.web.labels" . | nindent 8 }}
    spec:

3.渲染模版

[root@k8s-master01 helm]# helm install --generate-name ./app/ --dry-run
spec:
  replicas: 5
  selector:
    matchLabels:
      role: web
      version: 0.1.0
  template:
    metadata:
      labels:
        role: web
        version: 0.1.0

2. 内置对象Files
2.1 Files基本介绍
在helm中,我们通常需要再ConfigMaps和Secrets中包含一些文件内容。例如有一个tls的证书,我们需要再secret资源中包含它。但是这些文件的内容并不是有效的yaml和json,所以我们无法直接将它们包含在模版文件进行渲染。但是我们可以使用.Files内置对象将这些文件的内容包含起来。
下面的示例展示了如何使用.Files对象在一个Secret资源中包含TLS证书和私钥:

apiVersion: v1
kind: Secret
metadata:
  name: my-tls-secret
type: kubernetes.io/tls
data:
 tls.crt: {{ .Files.Get "tls/tls.crt" | b64enc }} # Files.Get会获取tls/tls.crt中的内容,然后交给b64enc函数进⾏base64编码
 tls.key: {{ .Files.Get "tls/tls.key" | b64enc }} # Files.Get会获取tls/tls.key中的内容,然后交给b64enc函数进⾏base64编码

总的来说,.Files 对象提供了⼀种灵活的⽅式来包含那些我们⽆法通过模板渲染的⽂件内容。但是在使⽤ .Files 对象时,有⼏个注意事项:

  • 1、⽂件⼤⼩限制:由于Kubernetes对象的限制,整个 HelmChart 的⼤⼩必须⼩于1M。因此,我们不能将⼤⽂件添加到 Chart 中。
  • 2、⽂件访问限制:出于安全考虑,有些⽂件不能通过 .Files 对象访问,例如:templates/ ⽬录中的⽂件、.helmignore 排除的⽂件等。
  • 3、⽂件权限:Helm Chart 不会保留 UNIX ⽂件模式信息。因此当⽂件被.Files 对象访问时,⽂件的权限设置不会影响⽂件的可⽤性。

2.2 Files.Get
.Files.Get可以通过文件名获取文件的内容。例如 {{ .Files.Get "config.ini" }}将会获取config.ini文件的内容
1.准备app/config/redis.conf配置文件

mkdir -p app/config
cat app/config/redis.conf
bind 0.0.0.0
maxclients 10000
requirepass oldxu
  1. 编写configmap资源,读入对应的配置文件
[root@k8s-master01 helm]# cat app/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  redis.conf: |-
  {{- .Files.Get "config/redis.conf" | nindent 4 }}

3.最终渲染的结果

[root@k8s-master01 helm]# helm install app ./app/ --dry-run
# Source: app/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-configmap
data:
  redis.conf: |-
    bind 0.0.0.0
    maxclients 10000
    requirepass oldxu

2.3 Files.Glob
.Files.Glob 可以使⽤ shell glob ⽅式匹配⽂件名,并返回所有匹配的⽂件的内容。
例如, {{- range $PathName, $FileContent := .Files.Glob "config/*.conf"}} 将会获取 config/ ⽬录下所有 .conf ⽂件的内容,并将⽂件名赋值给 $PathName ,将⽂件内容赋值给 $FileContent
1.准备多个配置文件

[root@k8s-master01 helm]# cat app/config/nginx.conf
server {
     listen 80;
     server_name config.oldxu.net;
     root html;
     index {
         index index.html;
     }
}

[root@k8s-master01 helm]# cat app/config/nginx-status.conf
server {
     listen 80;
     server_name status.oldxu.net;
     location / {
         stub_status;
     }
}

2.编写configmap资源,读入多个配置文件

[root@k8s-master01 helm]# cat app/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  {{- range $key, $value := .Files.Glob "config/*.conf" }} # 载⼊⽂件
  {{ base $key }}: |- # 默认是获取⽂件名称的绝对路径,base是仅获取⽂件名称作为key名称。
  {{- $value | toString | nindent 4 }} # ⽂件内容,但默认获取的是字节内容,因此使⽤toString转为字符串,⽽后使⽤nindent向右移动4个空格。
  {{- end }}

3.最终渲染的结果

[root@k8s-master01 helm]# helm install app ./app/ --dry-run
# Source: app/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-configmap
data:
  nginx-status.conf: |-
    server {
    listen 80;
    server_name status.oldxu.net;
    location / {
         stub_status;
    }
 }

   nginx.conf: |-
     server {
         listen 80;
         server_name config.oldxu.net;
         root html;
         index {
             index index.html;
         }
    }

2.4 Files读入TLS文件
1.准备证书文件

[root@master01 helm]# mkdir app/ssl && cd app/ssl
[root@master01 ssl]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout server.key -out server.crt \
-subj "/CN=server/O=oldxuedu"

[root@k8s-master01 helm]# ll app/ssl/
-rw-r--r-- 1 root root 1139 Aug 11 15:03 server.crt
-rw-r--r-- 1 root root 1704 Aug 11 15:03 server.key

2、创建 app/templates/secret.yaml 的资源清单,⽽后引⼊tls证书⽂件

[root@k8s-master01 helm]# cat app/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
 name: {{ .Release.Name }}-tls
data:
 tls.crt: {{ .Files.Get "ssl/server.crt" | b64enc }}
 tls.key: {{ .Files.Get "ssl/server.key" | b64enc }}

3.渲染模版

[root@k8s-master01 helm]# helm install app ./app/ --dry-run
---
# Source: app/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
 name: app-tls
data:
 tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHekNDQWdPZ0F3SUJBZ0l
KQUp5bmdBSnl6UXRITUEwR0NTcUdTSWIzRFFFQkN3VUFNQ1F4RHpBTkJnTlYKQkFN
 tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2l
HOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRQ2dJWmJqaWY5cUhVZFoKcHcr

3. 为Ingress资源注入TLS
场景描述:部署 Ingress 资源,需要根据 values ⽂件中的 tls 字段进⾏动态设置。

  • 如果 tls 字段设置为启⽤,则创建⼀个Secret资源,加载 TLS 证书,并配置
    Ingress 启⽤ TLS。
  • 如果 tls 字段未被开启,那么我们将不创建 Secrets,并且 Ingress 不启⽤
    TLS。
    实现思路:
  • 1、准备Values⽂件,配置对应的TLS字段;
  • 2、准备Secret资源清单,判断tls是否启⽤,启⽤则创建secret资源,并加载
    证书;
  • 3、准备Ingress资源清单,判断tls是否启⽤,启⽤则配置tls段,并使⽤
    secrets传⼊证书;
    3.1 准备Values配置文件](#tag3.1)
[root@k8s-master01 helm]# cat app/values.yaml
# Ingress配置段
ingress:
 enabled: true
 ClassName: "nginx"
 host: app-tls.oldxu.net
# TLS配置段
tls:
 enabled: true
 CertPath: "ssl/server.crt"
 KeyPath: "ssl/server.key"

3.2 准备Secret资源
Values.tls.enabled=true ,则需要创建⼀个 Secrets 的资源⽂件,同时需要读取 values.tls 下的 CertPathKeyPath 获取对应证书⽂件的路径。

[root@k8s-master01 helm]# cat app/templates/secret.yaml
{{- if .Values.tls.enabled }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Release.Name }}-tls
data:
  tls.crt: {{ .Files.Get .Values.tls.CertPath | b64enc }}
  tls.key: {{ .Files.Get .Values.tls.KeyPath | b64enc }}
{{- end }}

3.3 准备Ingress资源

[root@k8s-master01 helm]# cat app/templates/ingress.yaml
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-ingress
spec:
  ingressClassName: {{ .Values.ingress.ClassName | quote }}
  {{- if .Values.tls.enabled }}
  tls:
  - hosts:
    - {{ .Values.ingress.host }}
    secretName: {{ .Release.Name }}-tls
  {{- end }}
  rules:
  - host: {{ .Values.ingress.host }}
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: {{ .Release.Name }}-svc
            port:
              number: 80
{{- end }}

3.4 测试并验证资源文件](#tag3.4)
1、默认Values配置⽂件中的TLS是启⽤的

[root@k8s-master01 helm]# helm install app ./app/ --dry-run
# Source: app/templates/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  ingressClassName: "nginx"
  tls:
  - hosts:
    - app-tls.oldxu.net
    secretName: app-tls
  rules:
  - host: app-tls.oldxu.net
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-svc
            port:
              number: 80

2、关闭TLS测试(会发现不会创建Secret-tls资源,也不会启⽤Ingress的TLS配
置段)

[root@k8s-master01 helm]# helm install app ./app/ --set tls.enabled=false --dry-run
---
# Source: app/templates/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  ingressClassName: "nginx"
  rules:
  - host: app-tls.oldxu.net
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-svc
            port:
              number: 80

3、如果需要真的部署,则还需要添加⼀个service.yaml资源⽂件

[root@k8s-master01 helm]# cat app/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}-svc
  labels:
    {{- include "app.web.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  selector:
    {{- include "app.web.selector" . | nindent 4 }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.port }}
      protocol: TCP
      name: http

4.执行部署命令

helm install --generate-name ./app/
  1. 域名访问验证

4. NOTES.txt](#tag4)
当安装或者升级 chart 时,Helm 能够为⽤户打印⼀些有⽤的信息。这些信息可以使⽤模板进⾏定制。如果你想把使⽤说明加⼊到 chart 中,只需要创建⼀个名为 templates/NOTES.txt 的⽂件。虽然这是⼀个纯⽂本⽂件,但它可以像模板⼀样进⾏渲染。
1.创建一个简单的NOTES.txt文件;

恭喜你成功安装:{{ .Chart.Name }}
你安装的Release名称是: {{ .Release.Name }}
需要了解更多信息请执⾏如下操作:
# helm ls
# helm status {{ .Release.Name }}
# helm get {{ .Release.Name }}

2、接下来安装⼀下Chart,就可以在底部看到消息

NOTES:
恭喜你成功安装:nginx
你安装的Release名称是: nginx-hello
需要了解更多信息请执⾏如下操作:
# helm ls nginx-hello
# helm status nginx-hello
# helm get nginx-hello