2025,每天10分钟,跟我学K8S(三十九)- Helm (二)Helm的结构和案例

        前面一章,大概了解了下helm的安装,和创建自定义的应用,本章节,来完整演示一下通过helm安装一个mysql应用的方式,了解一下helm的目录结构及作用。

helm的目录结构

        上一章,我们创建了一个myapp的自定义应用,并且知道了他的目录结构

# 创建一个myapp的自定义应用
root@k8s-master:~/helm# helm create myapp
Creating myapp

# 进入目录
root@k8s-master:~/helm# cd myapp/

# 查看目录结构
root@k8s-master:~/helm/myapp# tree
.
├── charts
├── Chart.yaml
├── 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 

YAML 文件,描述 chart 的概要信息。

name和version是必须得,其他为选填

values.yaml

helm的核心文件,定义了对象的制化配置(镜像地址、容器检查、容器数量、卷、资源限制、pvpvc等等),chart 支持在安装的时根据参数进行定制化配置,而 values.yaml 就是提供了这些配置参数的默认值。services,deployment,configmap等配置都是从这个地方取值,然后进行渲染生成

templates 目录 

        各种 Kubernetes 对象资源的配置模板都放置在这里。Helm 会将 values.yaml 中的参数值注入到模板中进行渲染,最后生成标准的 YAML 配置文件。例如渲染成deployment.yaml,svc.yaml,ingress.yaml等等。

        模板是 chart 最重要的部分,也是 Helm 最强大的地方。模板增加了应用部署的灵活性,能够适用不同的环境。

动态字段详解​

​变量引用​

以 templates/deployment.yaml 为例:

        单独一眼扫过,其实和之前创建pod时候,自己手动写的deployment.yaml差不多,只是之前我们都是写死,但是这里是通过 {{ include "myapp.fullname" . }} 这种模板方式来定义,这其实是Go 语言的模板来编写 chart。        


 

① {{ include "myapp.fullname" . }} 定义 Deployment 的 name。这个fullname。是在 templates/_helpers.tpl 文件中定义的。​从下图可以看到,定义fmyapp.fullname又是做了一些判断,如果上一层的Values.yaml文件中有定义fullnameOverride,那就采用这个,如果没定义则继续下面的判断。

② image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 定义了deployment.yaml下的镜像下载地址,.Values.image.repository和.Values.image.tag,从

values.yaml 中取值,如果没有定义,则为空。也就是下面的内容

  repository: m.daocloud.io/docker.io/nginx
  # This sets the pull policy for images.
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: ""

拼接后内容为
image: m.daocloud.io/docker.io/nginx

③ imagePullSecrets: {{- toYaml . | nindent 8 }}  将输入的数据结构转换为 YAML 格式字符串,并且换行后缩进 8 个空格

如果 values.yaml 中的 imagePullSecrets: [] 有值
则渲染成  
    spec:
      imagePullSecrets: xx
条件判断​

以 templates/hpa.yaml 为例:

这里的if判断语法以 {{ if xxx }}开始,以最近的{{ end }}结尾

# 下面的语句就是判断.Values.autoscaling.targetCPUUtilizationPercentage是否存在,如果存在则渲染下面几行的内容

    {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
    {{- end }}

​循环与列表处理​

以 templates/ingress.yaml 为例:

这里的if判断语法以 {{ range xxx }}开始,以最近的{{ end }}结尾

# 下面的循环是根据.Values.ingress.tls下的内容焕然出一个hosts的列表
    {{- range .Values.ingress.tls }}
    - hosts:
        {{- range .hosts }}
        - {{ . | quote }}
        {{- end }}

helm安装mysql演示

上面讲解了许多,还是以一个具体的例子来实践展示,由于helm使用的镜像都是默认从docker.io下载,国内网络可能无法访问,所以还是先下载下来演示

1.helm安装前的准备

安装之前,先通过 helm inspect values azure/mysql 命令查看安装之前需要做哪些准备。其中有一部分是关于存储的。

root@k8s-master:~/longhorn# helm inspect values azure/mysql
## mysql image version
## ref: https://hub.docker.com/r/library/mysql/tags/
....
## Persist data to a persistent volume
persistence:
  enabled: true
  ## database data Persistent Volume Storage Class
  ## If defined, storageClassName: <storageClass>
  ## If set to "-", storageClassName: "", which disables dynamic provisioning
  ## If undefined (the default) or set to null, no storageClassName spec is
  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
  ##   GKE, AWS & OpenStack)
  ##
  # storageClass: "-"
  accessMode: ReadWriteOnce
  size: 8Gi
  annotations: {}
....

上从面的内容得知,chart 定义了一个 PersistentVolumeClaim,申请 8G 的 PersistentVolume。由于我们的实验环境不支持动态供给,所以得预先创建好相应的 PV
看出来需要8G的磁盘空间。这里可以通过pv/pvc,也可以使用之前演示的longhorn。本文中就直接采用longhorn作为后端来演示。

2.手动创建pv

之前已经在k8s-node01这台服务器安装了nfs服务器,安装步骤可以看之前的pv/pvc章节。

        1.创建一个新的文件夹当做mysql的挂载点

# 创建共享目录
sudo mkdir -p /data/my_mysql
sudo chmod 777 /data/my_mysql

# 配置导出规则(/etc/exports)
echo "/data/my_mysql *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports

# 应用配置
sudo exportfs -a
sudo systemctl restart nfs-kernel-server

        2.编写pv的yaml文件

# 查看pv.yaml
root@k8s-master:~/helm/my_mysql# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
#  storageClassName: nfs
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data/my_mysql
    server: 172.21.176.4
    readOnly: false



root@k8s-master:~/helm# kubectl apply -f pv.yaml 
persistentvolume/mysql-pv created

# 查看创建的pv
root@k8s-master:~/helm# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
mysql-pv   10Gi       RWX            Retain           Available                          <unset>                          14s
root@k8s-master:~/helm# 

3.下载并修改mysql的helm文件

下载并install

# 在线搜索mysql源
root@k8s-master:~/helm# helm search repo mysql
NAME                           	CHART VERSION	APP VERSION	DESCRIPTION                                       
azure/mysql                    	1.6.9        	5.7.30     	DEPRECATED - Fast, reliable, scalable, and easy...

...

# 默认在线mysql安装命令
# helm install my-mysql azure/mysql  #镜像原因,国内无法拉取镜像

# 由于镜像源默认都是用的docker.io,在线安装无法拉去镜像,所以先将azure源下的mysql pull下来到本地
root@k8s-master:~/helm# helm pull azure/mysql
root@k8s-master:~/helm# ls
mysql-1.6.9.tgz

# 解压
root@k8s-master:~/helm# tar -xzvf  mysql-1.6.9.tgz
mysql/Chart.yaml
mysql/values.yaml
mysql/templates/NOTES.txt
mysql/templates/_helpers.tpl
mysql/templates/configurationFiles-configmap.yaml
mysql/templates/deployment.yaml
mysql/templates/initializationFiles-configmap.yaml
mysql/templates/pvc.yaml
mysql/templates/secrets.yaml
mysql/templates/serviceaccount.yaml
mysql/templates/servicemonitor.yaml
mysql/templates/svc.yaml
mysql/templates/tests/test-configmap.yaml
mysql/templates/tests/test.yaml
mysql/.helmignore
mysql/README.md



# 修改values.yaml中镜像地址
image: "mysql"
imageTag: "5.7.30"

busybox:
  image: "busybox"
  tag: "1.32"

======修改为======

image: "m.daocloud.io/docker.io/mysql"
imageTag: "5.7.30"

busybox:
  image: "m.daocloud.io/docker.io/busybox"
  tag: "1.32"


# 修改service部分ClusterIP改为NodePort
service:
  annotations: {}
  ## Specify a service type
  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types
  type: ClusterIP
  port: 3306
  # nodePort: 32000
======修改为=========
service:
  annotations: {}
  ## Specify a service type
  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types
  type: NodePort
  port: 3306
  nodePort: 32000




# helm install my-mysql mysql命令开始安装
root@k8s-master:~/helm# helm install my-mysql mysql
WARNING: This chart is deprecated
NAME: my-mysql
LAST DEPLOYED: Mon Apr  7 14:41:03 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
my-mysql.default.svc.cluster.local

To get your root password run:

    MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default my-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)

To connect to your database:

1. Run an Ubuntu pod that you can use as a client:

    kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il

2. Install the mysql client:

    $ apt-get update && apt-get install mysql-client -y

3. Connect using the mysql cli, then provide your password:
    $ mysql -h my-mysql -p

To connect to your database directly from outside the K8s cluster:
    MYSQL_HOST=127.0.0.1
    MYSQL_PORT=3306

    # Execute the following command to route the connection:
    kubectl port-forward svc/my-mysql 3306

    mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}


# 通过helm list 查看状态
root@k8s-master:~/helm# helm list
NAME    	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART      	APP VERSION
my-mysql	default  	1       	2025-04-08 16:42:20.457513002 +0800 CST	deployed	mysql-1.6.9	5.7.30     


# 通过kubectl查看状态
root@k8s-master:~/helm# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
my-mysql-578494b569-8dwst   1/1     Running   0          68s



4.验证mysql

根据helm的提示查看密码

# 查看mysql密码
root@k8s-master:~/helm# echo $(kubectl get secret --namespace default my-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)
cFF8cfv3ke


# 进入容器查看mysql状态
root@k8s-master:~/helm# kubectl exec -it my-mysql-578494b569-8dwst -- /bin/bash
Defaulted container "my-mysql" out of: my-mysql, remove-lost-found (init)
root@my-mysql-578494b569-8dwst:/# mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 29
Server version: 5.7.30 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)

mysql> 

5.验证helm的渲染

        在上面的例子中,修改过了镜像地址,现在通过 kubectl get deployments.apps -oyaml 命令将deployment生成yaml格式。查看刚才的values.yaml中的值是否渲染到了deployment.yaml中.

root@k8s-master:~/helm# kubectl get deployments.apps -oyaml
apiVersion: v1
items:
- apiVersion: apps/v1
  kind: Deployment
.....
          image: m.daocloud.io/docker.io/mysql:5.7.30
.....

再查看的values.yaml中的service的端口修改是否渲染到了svc.yaml中.是否渲染出了NodePort类型的32000端口

root@k8s-master:~/helm# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          18d
my-mysql     NodePort    10.102.63.219   <none>        3306:32000/TCP   4s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值