k8s(14)-- Helm

Helm

地址:https://github.com/helm/helm

Helm 对于 Kubernetes 来说就相当于 yum 对于 Centos 来说,如果没有 yum 的话,我们在 Centos 下面要安装一些应用程序是极度麻烦的,同样的,对于越来越复杂的 Kubernetes 应用程序来说,如果单纯依靠我们去手动维护应用程序的 YAML 资源清单文件来说,成本也是巨大的。

Helm是Deis (https://deis.com/) 开发的一个用于kubernetes的包管理器。每个包称为一个Chart,一个Chart是一个目录(一般情况下会将目录进行打包压缩,形成name-version.tgz格式的单一文件,方便传输和存储)。

对于应用发布者而言,可以通过Helm打包应用,管理应用依赖关系,管理应用版本并发布应用到软件仓库。

除此以外,Helm还提供了kubernetes上的软件部署,删除,升级,回滚应用的强大功能

1. 诞生背景

k8s是一个分布式的容器集群管理系统,它将集群中的所有资源都抽象成 API 对象,并且使用声明的方式来创建、修改、删除这些对象。在微服务盛行的今天,如果使用这种方式将导致大量API声明文件的编写维护,使运维工作量爆发式增长,并且对每个微服务应用都需要编写对应的yaml配置文件,极容易出错,维护困难。helm就是为解决这些问题而诞生的。

  • 在云 (Kubernetes)上,部署一个应用往往不是那么简单。如果想要部署一个应用程序到云上,首先要准备好它所需要的环境,打包成 Docker 镜像,进而把镜像放在部署文件 (Deployment) 中、配置服务 (Service)、应用所需的账户 (ServiceAccount) 及权限 (Role)、命名空间 (Namespace)、密钥信息 (Secret)、可持久化存储 (PersistentVolumes) 等资源。也就是编写一系列互相相关的 YAML 配置文件,将它们部署在 Kubernetes 集群上。

  • 即便应用的开发者可以把这些 Docker 镜像存放在公共仓库中,并且将所需的 YAML 资源文件提供给用户,用户仍然需要自己去寻找这些资源文件,并把它们一一部署。倘若用户希望修改开发者提供的默认资源,比如使用更多的副本 (Replicas) 或是修改服务端口 (Port),他还需要自己去查需要在这些资源文件的哪些地方修改,更不用提版本变更与维护会给开发者和用户造成多少麻烦了。

2. 主要功能

Helm主要功能如下:

  1. 查找要安装和使用的预打包软件(Chart);

  2. 轻松创建和托管自己的软件包;

  3. 将软件包安装到任何K8s集群中;

  4. 查询集群已安装和正在运行的程序包;

  5. 更新、删除、回滚或查看已安装软件包的历史记录;

从使用方角度看:

  • 应用发布者:可以通过Helm打包应用,管理应用依赖关系,管理应用版本并发布应用到软件仓库。Helm还提供了kubernetes上的软件部署,删除,升级,回滚应用的强大功能。

  • 使用者:使用Helm后不用需要了解Kubernetes的Yaml语法并编写应用部署文件,可以通过Helm下载并在kubernetes上安装需要的应用。

3. Helm 相关概念

  • helm :是一个命令行工具,用于本地开发及管理chart,chart仓库管理等

  • chart: Helm 的软件包,采用 TAR 格式,所谓chart就是一系列文件, 它描述了一组相关的 k8s 集群资源

  • release: 是运行在 Kubernetes 集群中的 chart 的实例,一个 chart 通常可以在同一个集群中安装多次。每一次安装都会创建一个新的 release。以 MySQL chart为例,如果你想在你的集群中运行两个数据库,你可以安装该chart两次。每一个数据库都会拥有它自己的 releaserelease name

  • Repoistory:Helm 的软件仓库,Repository 本质上是一个 Web 服务器,该服务器保存了一系列的 Chart 软件包以供用户下载,并且提供了一个该 Repository 的 Chart 包的清单文件以供查询。Helm 可以同时管理多个不同的 Repository。

  • Tiller:Tiller 是 Helm 的服务端,部署在 Kubernetes 集群中。Tiller 用于接收 Helm 的请求,并根据 Chart 生成 Kubernetes 的部署文件( Helm 称为 Release ),然后提交给 Kubernetes 创建应用。Tiller 还提供了 Release 的升级、删除、回滚等一系列功能。

4. 安装

Helm的版本用 x.y.z 描述,x是主版本,y是次版本,z是补丁版本。

不推荐将Helm用于比编译它所依赖的版本更高的Kubernetes版本,因为Helm并没有做出任何向前兼容的保证。如果您选择了一个Kubernetes版本不支持的Helm,需自负风险。

Helm Version

Supported Kubernetes Versions

3.9.x

1.24.x - 1.21.x

3.8.x

1.23.x - 1.20.x

3.7.x

1.22.x - 1.19.x

3.6.x

1.21.x - 1.18.x

3.5.x

1.20.x - 1.17.x

3.4.x

1.19.x - 1.16.x

3.3.x

1.18.x - 1.15.x

3.2.x

1.18.x - 1.15.x

3.1.x

1.17.x - 1.14.x

3.0.x

1.16.x - 1.13.x

2.16.x

1.16.x - 1.15.x

2.15.x

1.15.x - 1.14.x

2.14.x

1.14.x - 1.13.x

2.13.x

1.13.x - 1.12.x

2.12.x

1.12.x - 1.11.x

2.11.x

1.11.x - 1.10.x

2.10.x

1.10.x - 1.9.x

2.9.x

1.10.x - 1.9.x

2.8.x

1.9.x - 1.8.x

2.7.x

1.8.x - 1.7.x

2.6.x

1.7.x - 1.6.x

2.5.x

1.6.x - 1.5.x

2.4.x

1.6.x - 1.5.x

2.3.x

1.5.x - 1.4.x

2.2.x

1.5.x - 1.4.x

2.1.x

1.5.x - 1.4.x

2.0.x

1.4.x - 1.3.x

wget https://get.helm.sh/helm-v3.9.0-linux-amd64.tar.gz
tar -zxvf helm-v3.9.0-linux-amd64.tar.gz
mv linux-amd64/helm  /usr/local/bin/

所有节点都安装。

#校验是否安装成功
helm version
#帮助
helm --help

注意:由于 Helm V2 版本必须在 Kubernetes 集群中安装一个 Tiller 服务进行通信,这样大大降低了其安全性和可用性,所以在 V3 版本中移除了,helm 3版本,没有Tiller,也就不用安装Tiller

在Helm 2开发周期中,Helm团队引入了Tiller(Helm2是C/S架构,主要分为客户端helm和服务端 Tiller)。它使多个不同的操作员可以与同一组发行版进行交互,对于在共享集群中工作的团队非常有用。但Kubernetes v1.6默认启用基于角色的访问控制(RBAC),这之后在生产环境中用Tiller会变得难以管理。同时出于安全策略考虑,Helm 3移除了Tiller,helm 直接和 Kubernetes API 进行通信,安全模型从根本上得以简化。这样做带来的好处有如下几点:

  • Helm 的架构变的更为简单和灵活

  • 不再需要创建 ServiceAccount,直接使用当前环境中的 kubeconfig 配置

  • 可以直接和 Kubernetes API 交互,更为安全

  • 不再需要使用 helm init 来进行初始化(以前的版本需要使用该命令来向 K8S 集群中安装 Tiller)

6. 仓库

一旦 Helm 客户端准备成功后,我们就可以添加一个 chart 仓库,当然最常用的就是官方的 Helm stable charts 仓库,但是由于官方的 charts 仓库地址需要科学上网,我们可以使用阿里云的 charts 仓库代替:

# 查看仓库
helm repo list
# 移除原先的仓库
helm repo remove stable
# 添加新的仓库地址
helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
# 更新仓库
helm repo update

安装完成后可以用 search 命令来搜索可以安装的 chart 包:

helm search repo stable

6.1 查找Charts

  • helm search hubArtifact Hub 中查找并列出 helm charts。 Artifact Hub中存放了大量不同的仓库

  • helm search repo 从你添加(使用 helm repo add)到本地 helm 客户端中的仓库中进行查找。该命令基于本地数据进行搜索,无需连接互联网。

# 从添加的本地仓库查找
helm search repo mongo
# 从远端仓库查找
helm search hub wordpress 

Helm 搜索使用模糊字符串匹配算法,所以你可以只输入名字的一部分

[root@master ctx]# helm search repo mongo
NAME                            CHART VERSION   APP VERSION     DESCRIPTION                                       
bitnami/mongodb                 13.1.2          6.0.1           MongoDB(R) is a relational open source NoSQL da...
bitnami/mongodb-sharded         6.1.1           6.0.1           MongoDB(R) is an open source NoSQL database tha...
stable/mongodb                  0.4.27          3.7.1           NoSQL document-oriented database that stores JS...
stable/mongodb-replicaset       2.3.1           3.6             NoSQL document-oriented database that stores JS...

6.2 仓库添加

可以从官网chart新地址:https://artifacthub.io/,查找仓库。

通过 helm repo add 命令添加一个 chart 仓库:

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

当添加完成后,通过 helm search repo 命令能够看到可以被您安装的charts列表:

[root@master ctx]# helm search repo bitnami
NAME                                            CHART VERSION   APP VERSION     DESCRIPTION                                       
bitnami/airflow                                 13.1.4          2.3.4           Apache Airflow is a tool to express and execute...
bitnami/apache                                  9.2.3           2.4.54          Apache HTTP Server is an open-source HTTP serve...
bitnami/argo-cd                                 4.1.3           2.4.11          Argo CD is a continuous delivery tool for Kuber...
bitnami/argo-workflows                          2.4.3           3.3.9           Argo Workflows is meant to orchestrate Kubernet...
bitnami/aspnet-core                             3.5.2           6.0.8           ASP.NET Core is an open-source framework for we...

7. 使用

7.1 安装一个helm包(helm install)

使用 helm install 命令来安装一个新的 helm 包。

helm install 命令可以从多个来源进行安装:

从仓库安装

最简单的使用方法只需要传入两个参数:你命名的release名字和你想安装的chart的名称。

可以使用helm repo update命令来获取最新的chart列表。

  • 安装chart时创建了一个新的 release 对象。如果想让Helm生成一个名称,发布时使用--generate-name

  • 在安装过程中,helm 客户端会打印一些有用的信息,其中包括:哪些资源已经被创建,release当前的状态,以及你是否还需要执行额外的配置步骤。

  • Helm 客户端不会等到所有资源都运行才退出。许多 charts 需要大小超过 600M 的 Docker 镜像,可能需要很长时间才能安装到集群中。

# 手动指定名字
helm install msmysql bitnami/mysql
#自动生成名字
helm install bitnami/mysql --generate-name

比如:

[root@master helm]# helm install bitnami/mysql --generate-name
NAME: mysql-1662808138
LAST DEPLOYED: Sat Sep 10 19:09:00 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 9.3.2
APP VERSION: 8.0.30

** Please be patient while the chart is being deployed **

Tip:

  Watch the deployment status using the command: kubectl get pods -w --namespace default

Services:

  echo Primary: mysql-1662808138.default.svc.cluster.local:3306

Execute the following to get the administrator credentials:

  echo Username: root
  MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default mysql-1662808138 -o jsonpath="{.data.mysql-root-password}" | base64 -d)

To connect to your database:

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

      kubectl run mysql-1662808138-client --rm --tty -i --restart='Never' --image  docker.io/bitnami/mysql:8.0.30-debian-11-r15 --namespace default --env MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD --command -- bash

  2. To connect to primary service (read/write):

      mysql -h mysql-1662808138.default.svc.cluster.local -uroot -p"$MYSQL_ROOT_PASSWORD"

运行命令之后,bitnami/mysql这个chart被发布。

  • 您可以通过执行 helm show chart bitnami/mysql 命令简单的了解到这个chart的基本信息。 或者您可以执行 helm show all bitnami/mysql 获取关于该chart的所有信息。

  • 每当您执行 helm install 的时候,都会创建一个新的发布版本。 所以一个chart在同一个集群里面可以被安装多次,每一个都可以被独立的管理和升级。

[root@master helm]# helm show chart bitnami/mysql
annotations:
  category: Database
apiVersion: v2
appVersion: 8.0.30
dependencies:
- name: common
  repository: https://charts.bitnami.com/bitnami
  tags:
  - bitnami-common
  version: 2.x.x
description: MySQL is a fast, reliable, scalable, and easy to use open source relational
  database system. Designed to handle mission-critical, heavy-load production applications.
home: https://github.com/bitnami/charts/tree/master/bitnami/mysql
icon: https://bitnami.com/assets/stacks/mysql/img/mysql-stack-220x234.png
keywords:
- mysql
- database
- sql
- cluster
- high availability
maintainers:
- name: Bitnami
  url: https://github.com/bitnami/charts
name: mysql
sources:
- https://github.com/bitnami/containers/tree/main/bitnami/mysql
- https://mysql.com
version: 9.3.2

7.2 查看release

通过 helm listhelm ls 命令会列出所有被发布的Chart:

  • helm list --all 会展示 Helm 保留的所有 release 记录,包括失败或删除的条目(指定了 --keep-history)

[root@master helm]# helm list
NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
mysql-1662808138        default         1               2022-09-10 19:09:00.680841397 +0800 CST deployed        mysql-9.3.2     8.0.30 

7.3 卸载release

可以使用 helm uninstall 命令卸载你发布的版本

[root@master helm]# helm uninstall mysql-1662808138
release "mysql-1662808138" uninstalled
  • 该命令会从Kubernetes卸载 mysql-1662808138, 它将删除和该版本相关的所有相关资源(service、deployment、 pod等等)甚至版本历史。

  • 如果您在执行 helm uninstall 的时候提供 --keep-history 选项, Helm将会保存版本历史。 您可以通过命令查看该版本的信息

7.4 查看release状态

您可以使用 helm status 命令查看 release 的状态,或是重新读取配置信息:

  • 若卸载Chart时使用了 --keep-history 选项,helm会跟踪你的版本(即使你卸载了他们),所以你可以审计集群历史甚至使用 helm rollback 回滚版本。

[root@master helm]# helm status mysql-1662808138
Error: release: not found
[root@master helm]# helm install bitnami/mysql --generate-name
[root@master helm]# helm uninstall mysql-1662808602 --keep-history  
release "mysql-1662808602" uninstalled
[root@master helm]# helm status mysql-1662808602
NAME: mysql-1662808602
LAST DEPLOYED: Sat Sep 10 19:16:43 2022
NAMESPACE: default
STATUS: uninstalled
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 9.3.2
APP VERSION: 8.0.30

7.5 查看配置的仓库

Helm3 不再附带一个默认的 chart 仓库。helm repo 提供了一组命令用于添加、列出和移除仓库。

  • 使用 helm repo list 来查看配置的仓库:

    [root@master helm]# helm repo list
    NAME    URL                                                   
    stable  https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
    bitnami https://charts.bitnami.com/bitnami
    
  • 使用 helm repo add 来添加新的仓库:

    helm repo add xxx
    

因为 chart 仓库经常在变化,在任何时候你都可以通过执行 helm repo update 命令来确保你的 Helm 客户端是最新的。

使用 helm repo remove 命令来移除仓库。

7.6 自定义安装chart

上述安装方式只会使用chart的默认配置选项,很多时候,我们需要自定义 chart 来指定我们想要的配置

# 查看 chart 中的可配置选项
$ helm show values bitnami/wordpress

然后,你可以使用 YAML 格式的文件覆盖上述任意配置项,并在安装过程中使用该文件

mariadb:
  auth:
    database: testdb
    username: testuser
$ helm install -f values.yaml bitnami/wordpress --generate-name

上述命令将为 MariaDB 创建一个名称为 testuser 的默认用户,并且授予该用户访问新建的 testdb 数据库的权限。chart 中的其他默认配置保持不变。

安装过程中有两种方式传递配置数据

  • --values (或 -f):使用 YAML 文件覆盖配置。可以指定多次,优先使用最右边的文件

  • --set:通过命令行的方式对指定项进行覆盖

如果同时使用两种方式,则 --set 中的值会被合并到 --values 中,但是 --set 中的值优先级更高。在--set 中覆盖的内容会被被保存在 ConfigMap 中。可以通过 helm get values <release-name> 来查看指定 release 中 --set 设置的值。也可以通过运行 helm upgrade 并指定 --reset-values 字段来清除 --set 中设置的值。

--set 的格式和限制

--set 选项使用0或多个 name/value 对。最简单的用法类似于:--set name=value,等价于如下 YAML 格式:

name: value

多个值使用逗号分割,因此 --set a=b,c=d 的 YAML 表示是:

a: b
c: d

支持更复杂的表达式。例如,--set outer.inner=value 被转换成了:

outer:
  inner: value

列表使用花括号({})来表示。例如,--set name={a, b, c} 被转换成了:

name:
  - a
  - b
  - c

从 2.5.0 版本开始,可以使用数组下标的语法来访问列表中的元素。例如 --set servers[0].port=80 就变成了:

servers:
  - port: 80

多个值也可以通过这种方式来设置。--set servers[0].port=80,servers[0].host=example 变成了:

servers:
  - port: 80
    host: example

如果需要在 --set 中使用特殊字符,你可以使用反斜线来进行转义;--set name=value1\,value2 就变成了:

name: "value1,value2"

7.7 升级release(helm upgrade)

  • 首先创建好wp-update.yaml

mariadb:
  auth:
    password: "123456"
    rootPassword: "123456"
    username: user1
wordpressPassword: "123456"
  • 执行命令helm upgrade

[root@master helm]# helm upgrade -f wp-update.yaml wordpress-1662809924 bitnami/wordpress
Release "wordpress-1662809924" has been upgraded. Happy Helming!
NAME: wordpress-1662809924
LAST DEPLOYED: Sat Sep 10 19:42:11 2022
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
CHART NAME: wordpress
CHART VERSION: 15.2.0
APP VERSION: 6.0.2
  • 查看结果helm get values

[root@master helm]# helm get values wordpress-1662809924
USER-SUPPLIED VALUES:
mariadb:
  auth:
    password: "123456"
    rootPassword: "123456"
    username: user1
wordpressPassword: "123456"

7.8 回滚release(helm rollback)

格式:helm rollback [RELEASE] [REVISION]

$ helm rollback wordpress-1662809924 1

上面这条命令将我们的 wordpress-1662809924 回滚到了它最初的版本。release 版本其实是一个增量修订(revision)。 每当发生了一次安装、升级或回滚操作,revision 的值就会加1。第一次 revision 的值永远是1。

我们可以使用 helm history [RELEASE] 命令来查看一个特定 release 的修订版本号

[root@master helm]# helm history wordpress-1662809924
REVISION        UPDATED                         STATUS          CHART                   APP VERSION     DESCRIPTION     
1               Sat Sep 10 19:38:45 2022        superseded      wordpress-15.2.0        6.0.2           Install complete
2               Sat Sep 10 19:42:11 2022        deployed        wordpress-15.2.0        6.0.2           Upgrade complete

查看回滚结果:

[root@master helm]# helm get values wordpress-1662809924    
USER-SUPPLIED VALUES:
mariadb:
  auth:
    database: testdb
    username: testuser

7.9 安装、升级、回滚的有用选项

要查看所有参数的说明,请执行 helm <command> --help 命令。

  • --timeout:一个 Go duration类型的值, 用来表示等待 Kubernetes 命令完成的超时时间,默认值为 5m0s

  • --wait:表示必须要等到所有的 Pods 都处于 ready 状态,PVC 都被绑定,Deployments 都至少拥有最小 ready 状态 Pods 个数(Desired减去 maxUnavailable),并且 Services 都具有 IP 地址(如果是LoadBalancer, 则为 Ingress),才会标记该 release 为成功。最长等待时间由 --timeout 值指定。如果达到超时时间,release 将被标记为 FAILED。注意:当 Deployment 的 replicas 被设置为1,但其滚动升级策略中的 maxUnavailable 没有被设置为0时,--wait 将返回就绪,因为已经满足了最小 ready Pod 数。

  • --no-hooks:不运行当前命令的钩子

  • --recreate-pods(仅适用于 upgraderollback):这个参数会导致重建所有的 Pod(deployment中的Pod 除外)。(在 Helm 3 中已被废弃)

8. 解决Pending问题

[root@master helm]# kubectl describe pod mywp-wordpress-f67667857-7ljph
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  58s (x21 over 20m)  default-scheduler  0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims.

直接安装wordpress并不会成功,因为需要做pvc相关的操作,实际上就是wordpress的包并不会自动创建pv,没有也就是pvc没法和pv绑定造成的问题。

[root@master helm]# kubectl get pvc
NAME                  STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-mywp-mariadb-0   Pending                                                     9s
mywp-wordpress        Pending                                                     9s
#有pvc但是没有pv
[root@master helm]# kubectl get pv
No resources found

这里涉及到一个k8s新的资源StorageClass

9. StorageClass

Kubernetes提供了一套可以自动创建PV的机制,即:Dynamic Provisioning。而这个机制的核心在于StorageClass这个API对象。

大规模集群中可能会有很多PV,如果这些PV都需要运维手动来处理这也是一件很繁琐的事情(想象一下PVC不停的被提交,运维人员手动去创建符合要求的PV)所以就有了动态供给概念

StorageClass对象会定义下面两部分内容:

  • PV的属性。比如,存储类型,Volume的大小等。

  • 创建这种PV需要用到的存储插件。

有了这两个信息之后,Kubernetes就能够根据用户提交的PVC,找到一个对应的StorageClass,之后Kubernetes就会调用该StorageClass声明的存储插件,进而创建出需要的PV。

通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

每个 StorageClass 都包含 provisionerparametersreclaimPolicy 字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。

  • provisioner

    由那个存储器来提供,比如亚马逊,阿里云,nfs,ceph存储等

  • parameters

    参数,不同的存储提供者,参数也不相同

  • reclaimPolicy

    动态创建的pv的回收策略,默认是Delete,可以是 Delete 或者 Retain

每个 StorageClass 都有一个制备器(Provisioner),用来决定使用哪个卷插件制备 PV。 该字段必须指定。

卷插件

内置制备器

配置例子

AWSElasticBlockStore

AWS EBS

AzureFile

Azure File

AzureDisk

Azure Disk

CephFS

-

-

Cinder

OpenStack Cinder

FC

-

-

FlexVolume

-

-

GCEPersistentDisk

GCE PD

Glusterfs

Glusterfs

iSCSI

-

-

NFS

-

NFS

RBD

Ceph RBD

VsphereVolume

vSphere

PortworxVolume

Portworx Volume

Local

-

Local

9.1 案例

还是使用nfs,虽然不默认支持,但是其简单,适合做为例子

前面的课程中已经安装过nfs了

[root@master helm]# more /etc/exports
/mnt/data/nfs 192.168.200.0/24(rw,no_root_squash)
/mnt/data/pv1 192.168.200.0/24(rw,no_root_squash)
/mnt/data/pv2 192.168.200.0/24(rw,no_root_squash)
/mnt/data/pv3 192.168.200.0/24(rw,no_root_squash)

1. 创建Service Account

vim nfs-client-rbac.yaml,管理nfs-Provisioner在集群中的权限

apiVersion: v1 #创建 Service Account 账户,用来管理 NFS Provisioner 在 k8s 集群中运行的权限
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
---
apiVersion: rbac.authorization.k8s.io/v1 #创建集群角色
kind: ClusterRole
metadata:
  name: nfs-client-provisioner-clusterrole
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1 #集群角色绑定
kind: ClusterRoleBinding
metadata:
  name: nfs-client-provisioner-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: nfs-client-provisioner
  namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-clusterrole
  apiGroup: rbac.authorization.k8s.io
[root@master helm]# kubectl apply -f nfs-client-rbac.yaml 
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-clusterrole created
clusterrolebinding.rbac.authorization.k8s.io/nfs-client-provisioner-clusterrolebinding created

2. Deployment创建NFS Provisioner

vim /etc/kubernetes/manifests/kube-apiserver.yaml

spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=RemoveSelfLink=false #添加这行

vim nfs-client-provisioner.yaml

kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner          #指定Service Account账户
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: nfs-storage       #配置provisioner的Name,确保该名称与StorageClass资源中的provisioner名称保持一致
            - name: NFS_SERVER
              value: 192.168.200.104           #配置绑定的nfs服务器
            - name: NFS_PATH
              value: /mnt/data/nfs          #配置绑定的nfs服务器目录
      volumes:              #申明nfs数据卷
        - name: nfs-client-root
          nfs:
            server: 192.168.200.104
            path: /mnt/data/nfs
[root@master helm]# kubectl apply -f nfs-client-provisioner.yaml
deployment.apps/nfs-client-provisioner created

3. 创建storageclass

vim nfs-client-storageclass.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-storageclass
provisioner: nfs-storage     #这里的名称要和provisioner配置文件中的环境变量PROVISIONER_NAME保持一致
parameters:
  archiveOnDelete: "false"   #false表示在删除PVC时不会对数据进行存档,即删除数据
[root@master helm]# kubectl apply -f nfs-client-storageclass.yaml
storageclass.storage.k8s.io/nfs-client-storageclass created
[root@master helm]# kubectl get storageclasses
NAME                      PROVISIONER                            RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client                cluster.local/nfs-client-provisioner   Delete          Immediate           true                   122m
nfs-client-storageclass   nfs-storage                            Delete          Immediate           false                  25s

4. 测试

  • 创建pvc

    vim test-pvc-pod.yaml

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: test-nfs-pvc
    spec:
      accessModes:
        - ReadWriteOnce
      storageClassName: nfs-client-storageclass    #关联StorageClass对象
      resources:
        requests:
          storage: 2Gi      
    
  • 应用

    [root@master helm]# kubectl get pvc
    NAME                  STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS              AGE
    test-nfs-pvc          Bound     pvc-15628120-6425-4223-8558-ffcd3fd43c96   2Gi        RWO            nfs-client-storageclass   13s
    [root@master helm]# kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS              REASON   AGE
    pvc-15628120-6425-4223-8558-ffcd3fd43c96   2Gi        RWO            Delete           Bound    default/test-nfs-pvc   nfs-client-storageclass            85s
    

    自动进行了绑定,自动创建了pv

  • 使用pod进行测试

    [root@master helm]# ls /mnt/data/nfs/
    access.log  default-test-nfs-pvc-pvc-15628120-6425-4223-8558-ffcd3fd43c96  error.log
    

    vim test-pv-pod.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pv-pod
    spec:
      volumes:
        - name: test-pv-storage
          persistentVolumeClaim:
            claimName: test-nfs-pvc
      containers:
        - name: test-pv-container
          image: nginx
          ports:
            - containerPort: 80
              name: "http-server"
          volumeMounts:
            - mountPath: "/usr/share/nginx/html"
              name: test-pv-storage    #与PVC名称保持一致
    
    [root@master helm]# kubectl apply -f test-pv-pod.yaml
    pod/test-pv-pod created
    [root@master helm]# kubectl get pods
    NAME                                      READY   STATUS    RESTARTS   AGE
    nfs-client-provisioner-7c74fbb898-vmns7   1/1     Running   0          34m
    test-pv-pod                               1/1     Running   0          11s
    [root@master helm]# kubectl get pods -o wide
    NAME                                      READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
    nfs-client-provisioner-7c74fbb898-vmns7   1/1     Running   0          34m   10.244.2.5    node2   <none>           <none>
    test-pv-pod     
    
  • 在NFS中编辑index.html

    [root@master default-test-nfs-pvc-pvc-15628120-6425-4223-8558-ffcd3fd43c96]# vim index.html
    this is storage class
    
    [root@node1 nfs]# curl 10.244.1.13
    this is storage class
    
  • 完成测试

10. helm安装wordpress

安装是设置pvc参数即可:

[root@master helm]# helm install wordpress bitnami/wordpress --set mariadb.primary.persistence.enabled=true --set mariadb.primary.persistence.storageClass=nfs-client-storageclass --set persistence.storageClass=nfs-client-storageclass --set service.type=NodePort
[root@master helm]# kubectl get pods    
NAME                                      READY   STATUS    RESTARTS       AGE
nfs-client-provisioner-7c74fbb898-vmns7   1/1     Running   0              51m
wordpress-5cd4785cdf-l5fsq                1/1     Running   1 (5m4s ago)   6m18s
wordpress-mariadb-0                       1/1     Running   0              6m18s
[root@master helm]# kubectl get service
NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
kubernetes          ClusterIP   10.96.0.1      <none>        443/TCP                      7d20h
wordpress           NodePort    10.96.15.73    <none>        80:31775/TCP,443:30439/TCP   6s
wordpress-mariadb   ClusterIP   10.96.137.48   <none>        3306/TCP                     6s

访问:http://192.168.200.105:31775/ ,发现可以访问


k8s(14)-- Helm
http://47.123.5.226:8090//archives/k8s-14----helm
作者
pony
发布于
2024年04月28日
许可协议