K8s云原生存储&存储进阶

2.1.3.1 需要安装 lvm 包

1
sudo yum install -y lvm2

2.1.3.2 内核要求 RBD

一般发行版的内核都编译有,但你最好确定下:

1
2
3
foxchan@~$ lsmod|grep rbd
rbd                   114688  0
libceph               368640  1 rbd

可以用以下命令放到开机启动项里

1
2
3
cat > /etc/sysconfig/modules/rbd.modules << EOF
modprobe rbd
EOF

CephFS

如果你想使用 cephfs,内核最低要求是 4.17。

Volume

最开始直接将 volume 类型定义在一个 yaml 文件中存储不利于解藕,更适合于 k8s 管理员自己使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 volumes:
      - name: share-volume
        emptyDir: {}
          #medium: Memory
      - name: timezone
        hostPath:
          path: /etc/timezone
          type: File
      - name: nfs-volume
        nfs:
          server: 192.168.0.204
          path: /data/nfs/test-dp

后来引入了 PV 和 PVC 实现了解藕,之前只提到了静态存储,但是当集群规模变大,手动创建 PV 也是非常复杂的工作,而且不利于 PV 的回收,一旦创建的 PV 非常多,管理和扩容也很麻烦

更简单的持久化存储方式

如何解放管理 volume 的编写了,答案是 storageClass

StorageClass:存储类,由 K8s 管理员创建,用于动态 PV 的管理,可以链接至不同的后端存储,比如 Ceph、GlusterFS 等。之后对存储的请求可以指向 StorageClass,然后 StorageClass 会自动的创建、删除 PV。

实现方式如下:

image-20230831165424485

  • in-tree: 内置于K8s 核心代码,对于存储的管理,都需要编写相应的代码。开发人员需要学习合适配各种配置,给开发人员造成较大的压力
  • out-of-tree:让存储厂商适配 k8s 逻辑或接口,由存储厂商提供一个驱动(CSI或 Flex Volume),安装到 K8s 集群,然后StorageClass 只需要配置该驱动即可,驱动器会代替 StorageClass 管理存储,SCI 符合未来发展趋势。(类似于容器厂商兼容 k8s 的过程,k8s 独自开发 CRI(Container runtime interface)接口,各容器厂商开发兼容 K8S 兼容 k8s 接口,让 k8s 可以有更多的容器厂商选择)

StorageClass官方文档:https://kubernetes.io/docs/concepts/storage/storage-classes/

k8s 官方已经内置到代码中的 StorageClass(in-tree 模式,未来趋势向 CSI 方向迁移)

image-20230831165520936

下面是 k8s 适配是 AWS 厂商支持的一段参数(parameters 之后适配):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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

下面是 k8s 适配 NFS 参数配置:

1
2
3
4
5
6
7
8
9
 apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-nfs
provisioner: example.com/external-nfs
parameters:
  server: nfs-server.example.com
  path: /share
  readOnly: "false"

下面是适配 Ceph RBD 的参数配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/rbd
parameters:
  monitors: 10.16.153.105:6789 # 配置cepth monitor
  adminId: kube #配置管理员账号
  adminSecretName: ceph-secret
  adminSecretNamespace: kube-system
  pool: kube # 使用的pool
  userId: kube
  userSecretName: ceph-secret-user
  userSecretNamespace: default
  fsType: ext4
  imageFormat: "2"
  imageFeatures: "layering"

云原生存储 Rook(存储和 k8s 的桥梁)

介绍

Rook 是一个自我管理的分布式存储编排系统,它本身并不是存储系统,在存储和 k8s 之前搭建了一个桥梁,使存储系统的搭建或者维护变得特别简单,Rook 将分布式存储系统转变为自我管理、自我扩展、自我修复的存储服务。它让一些存储的操作,比如部署、配置、扩容、升级、迁移、灾难恢复、监视和资源管理变得自动化,无需人工处理。并且 Rook 支持 CSI,可以利用 CSI 做一些 PVC 的快照、扩容、克隆等操作。

参考文档:https://rook.io/

Rook 架构

生产环境有单独的 ceph 集群,Rook 建议使用外部连接方式连接 k8s 和 cepth 集群,但是测试开发环境是没有单独的 ceph 集群可以使用,中小型公司如果没有很强的运维能力,不建议在外部集群搭建 ceph 平台,而建议使用 Rook 跑一个 k8s 集群内部的 cepth 集群,本文档不去单独讲解 CSI 和 Ceph,仅仅演示 StorageClass 和 CSI 连接 ceph 集群的实现方式,所以使用 Rook 实现本地 ceph,Rook 同时还能解决非生产环境中(部分大企业已经用在生产环境)mysql、redis、kafka 较为方便有效的的存储实现方式,rook 基于本地存储的需求,如果想深入学习外部存储集群方式,可以单独去看 ceph、CSI 的课程,如果 rook 用在生产环境,建议在本地环境搭建时,将 OSD 节点(cepth)和 k8s 业务节点分开

image-20230831165653053

Rook 包含多个组件:

  • Rook Operator:Rook 的核心组件,Rook Operator 是一个简单的容器,自动启动存储集群(Rook Operator 让用户可以通过 CRD 的是用来创建和管理存储集群。每种资源都定义了自己的 CRD.),并监控存储守护进程,来确保存储集群的健康。Rook 还会用 Kubernetes Pod 的形式,部署 Ceph 的 MON、OSD 以及 MGR 守护进程。
  • Rook Agent:在每个存储节点上运行,并配置一个 FlexVolume 插件,和 Kubernetes 的存储卷控制框架进行集成。Agent 处理所有的存储操作,例如挂接网络存储设备、在主机上加载存储卷以及格式化文件系统等。
  • Rook Discovers:检测挂接到存储节点上的存储设备。
  • Rook Cluster:提供了对存储机群的配置能力,用来提供块存储、对象存储以及共享文件系统。每个集群都有多个 Pool。Pool:为块存储提供支持。Pool 也是给文件和对象存储提供内部支持。Object Store:用 S3 兼容接口开放存储服务。File System:为多个 Kubernetes Pod 提供共享存储。

Ceph 包括多个组件:

  • Ceph Monitors(MON):负责生成集群票选机制。所有的集群节点都会向 Mon 进行汇报,并在每次状态变更时进行共享信息。
  • Ceph Object Store Devices(OSD):负责在本地文件系统保存对象,并通过网络提供访问。通常 OSD 守护进程会绑定在集群的一个物理盘上,Ceph 客户端直接和 OSD 打交道。
  • Ceph Manager(MGR):提供额外的监控和界面给外部的监管系统使用。
  • Reliable Autonomic Distributed Object Stores:Ceph 存储集群的核心。这一层用于为存储数据提供一致性保障,执行数据复制、故障检测以及恢复等任务。
  • MDS:负责跟踪文件存储层次结构
  • RGW:提供对象存储接口(AWS S3、阿里云 OSS 等)

为了在 Ceph 上进行读写,客户端首先要联系 MON,获取最新的集群地图,其中包含了集群拓扑以及数据存储位置的信息。Ceph 客户端使用集群地图来获知需要交互的 OSD,从而和特定 OSD 建立联系。

image-20230831165722822

Rook 安装

注意事项:

  • K8s 集群至少五个节点,每个节点的内存不低于 5G,CPU 不低于 2 核
  • 至少有三个存储节点,并且每个节点至少有一个裸盘
  • K8s 集群所有的节点时间必须一致,被设置的节点不能打污点,除非配置污点容忍

参考文档:https://rook.io/docs/rook/v1.6/ceph-storage.html

  1. 首页
  2. kubernetes
  3. Kubernetes 存储高级

K8s 云原生存储&存储进阶

LJH • 2023 年 6 月 15 日 下午 7:45 • Kubernetes 存储高级 • 阅读 67

Volume 回顾

最开始直接将 volume 类型定义在一个 yaml 文件中存储不利于解藕,更适合于 k8s 管理员自己使用

1
volumes:      - name: share-volume        emptyDir: {}          #medium: Memory       - name: timezone        hostPath:          path: /etc/timezone          type: File      - name: nfs-volume        nfs:          server: 192.168.0.204          path: /data/nfs/test-dp Copy

后来引入了 PV 和 PVC 实现了解藕,之前只提到了静态存储,但是当集群规模变大,手动创建 PV 也是非常复杂的工作,而且不利于 PV 的回收,一旦创建的 PV 非常多,管理和扩容也很麻烦

更简单的持久化存储方式

下面讲解动态存储,通过 SirageClass 使用

StorageClass:存储类,由 K8s 管理员创建,用于动态 PV 的管理,可以链接至不同的后端存储,比如 Ceph、GlusterFS 等。之后对存储的请求可以指向 StorageClass,然后 StorageClass 会自动的创建、删除 PV。

实现方式:

K8s云原生存储&存储进阶

  • in-tree: 内置于K8s 核心代码,对于存储的管理,都需要编写相应的代码。开发人员需要学习合适配各种配置,给开发人员造成较大的压力
  • out-of-tree:让存储厂商适配 k8s 逻辑或接口,由存储厂商提供一个驱动(CSI或 Flex Volume),安装到 K8s 集群,然后StorageClass 只需要配置该驱动即可,驱动器会代替 StorageClass 管理存储,SCI 符合未来发展趋势。(类似于容器厂商兼容 k8s 的过程,k8s 独自开发 CRI(Container runtime interface)接口,各容器厂商开发兼容 K8S 兼容 k8s 接口,让 k8s 可以有更多的容器厂商选择)

StorageClass官方文档:https://kubernetes.io/docs/concepts/storage/storage-classes/

k8s 官方已经内置到代码中的 StorageClass(in-tree 模式,未来趋势向 CSI 方向迁移)

K8s云原生存储&存储进阶

下面是 k8s 适配是 AWS 厂商支持的一段参数(parameters 之后适配):

1
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: ImmediateCopy

下面是 k8s 适配 NFS 参数配置:

1
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:  name: example-nfs provisioner: example.com/external-nfs parameters:  server: nfs-server.example.com  path: /share  readOnly: "false"Copy

下面是适配 Ceph RBD 的参数配置:

1
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata:  name: fast provisioner: kubernetes.io/rbd parameters:  monitors: 10.16.153.105:6789 # 配置cepth monitor  adminId: kube #配置管理员账号  adminSecretName: ceph-secret  adminSecretNamespace: kube-system  pool: kube # 使用的pool  userId: kube  userSecretName: ceph-secret-user  userSecretNamespace: default  fsType: ext4  imageFormat: "2"  imageFeatures: "layering"Copy

云原生存储 Rook(存储和 k8s 的桥梁)

介绍

Rook 是一个自我管理的分布式存储编排系统,它本身并不是存储系统,在存储和 k8s 之前搭建了一个桥梁,使存储系统的搭建或者维护变得特别简单,Rook 将分布式存储系统转变为自我管理、自我扩展、自我修复的存储服务。它让一些存储的操作,比如部署、配置、扩容、升级、迁移、灾难恢复、监视和资源管理变得自动化,无需人工处理。并且 Rook 支持 CSI,可以利用 CSI 做一些 PVC 的快照、扩容、克隆等操作。

参考文档:https://rook.io/

Rook 架构

生产环境有单独的 ceph 集群,Rook 建议使用外部连接方式连接 k8s 和 cepth 集群,但是测试开发环境是没有单独的 ceph 集群可以使用,中小型公司如果没有很强的运维能力,不建议在外部集群搭建 ceph 平台,而建议使用 Rook 跑一个 k8s 集群内部的 cepth 集群,本文档不去单独讲解 CSI 和 Ceph,仅仅演示 StorageClass 和 CSI 连接 ceph 集群的实现方式,所以使用 Rook 实现本地 ceph,Rook 同时还能解决非生产环境中(部分大企业已经用在生产环境)mysql、redis、kafka 较为方便有效的的存储实现方式,rook 基于本地存储的需求,如果想深入学习外部存储集群方式,可以单独去看 ceph、CSI 的课程,如果 rook 用在生产环境,建议在本地环境搭建时,将 OSD 节点(cepth)和 k8s 业务节点分开

K8s云原生存储&存储进阶

Rook 包含多个组件:

  • Rook Operator:Rook 的核心组件,Rook Operator 是一个简单的容器,自动启动存储集群(Rook Operator 让用户可以通过 CRD 的是用来创建和管理存储集群。每种资源都定义了自己的 CRD.),并监控存储守护进程,来确保存储集群的健康。Rook 还会用 Kubernetes Pod 的形式,部署 Ceph 的 MON、OSD 以及 MGR 守护进程。
  • Rook Agent:在每个存储节点上运行,并配置一个 FlexVolume 插件,和 Kubernetes 的存储卷控制框架进行集成。Agent 处理所有的存储操作,例如挂接网络存储设备、在主机上加载存储卷以及格式化文件系统等。
  • Rook Discovers:检测挂接到存储节点上的存储设备。
  • Rook Cluster:提供了对存储机群的配置能力,用来提供块存储、对象存储以及共享文件系统。每个集群都有多个 Pool。Pool:为块存储提供支持。Pool 也是给文件和对象存储提供内部支持。Object Store:用 S3 兼容接口开放存储服务。File System:为多个 Kubernetes Pod 提供共享存储。

Ceph 包括多个组件:

  • Ceph Monitors(MON):负责生成集群票选机制。所有的集群节点都会向 Mon 进行汇报,并在每次状态变更时进行共享信息。
  • Ceph Object Store Devices(OSD):负责在本地文件系统保存对象,并通过网络提供访问。通常 OSD 守护进程会绑定在集群的一个物理盘上,Ceph 客户端直接和 OSD 打交道。
  • Ceph Manager(MGR):提供额外的监控和界面给外部的监管系统使用。
  • Reliable Autonomic Distributed Object Stores:Ceph 存储集群的核心。这一层用于为存储数据提供一致性保障,执行数据复制、故障检测以及恢复等任务。
  • MDS:负责跟踪文件存储层次结构
  • RGW:提供对象存储接口(AWS S3、阿里云 OSS 等)

为了在 Ceph 上进行读写,客户端首先要联系 MON,获取最新的集群地图,其中包含了集群拓扑以及数据存储位置的信息。Ceph 客户端使用集群地图来获知需要交互的 OSD,从而和特定 OSD 建立联系。

K8s云原生存储&存储进阶

Rook 安装

注意事项:

  • K8s 集群至少五个节点,每个节点的内存不低于 5G,CPU 不低于 2 核
  • 至少有三个存储节点,并且每个节点至少有一个裸盘
  • K8s 集群所有的节点时间必须一致,被设置的节点不能打污点,除非配置污点容忍

参考文档:https://rook.io/docs/rook/v1.6/ceph-storage.html

Rook 安装

注意 1:rook 的版本大于 1.3,不要使用目录创建集群,要使用单独的裸盘进行创建,也就是创建一个新的磁盘,挂载到宿主机,不进行格式化,直接使用即可。对于的磁盘节点配置如下:

image-20230831165905426

其中 nodes 下可以分配对应的节点名称和磁盘名称,磁盘名称用 lsblk 来看。

下载 Rook 安装文件

下载指定版本 Rook,也可以参考视频中的步骤下载最新版

git clone –single-branch –branch v1.6.3 https://github.com/rook/rook.git

配置更改

cd rook/deploy/examples/

修改 Rook CSI 镜像地址,原本的地址可能是 gcr 的镜像,但是 gcr 的镜像无法被国内访问,所以需要同步 gcr 的镜像到阿里云镜像仓库,文档版本已经为大家完成同步,可以直接修改如下:

vim operator.yaml

image-20230831170039745

改为:

ROOK_CSI_REGISTRAR_IMAGE: “registry.cn-beijing.aliyuncs.com/dotbalo/csi-node-driver-registrar:v2.0.1”

ROOK_CSI_RESIZER_IMAGE: “registry.cn-beijing.aliyuncs.com/dotbalo/csi-resizer:v1.0.1”

ROOK_CSI_PROVISIONER_IMAGE: “registry.cn-beijing.aliyuncs.com/dotbalo/csi-provisioner:v2.0.4”

ROOK_CSI_SNAPSHOTTER_IMAGE: “registry.cn-beijing.aliyuncs.com/dotbalo/csi-snapshotter:v4.0.0”

ROOK_CSI_ATTACHER_IMAGE: “registry.cn-beijing.aliyuncs.com/dotbalo/csi-attacher:v3.0.2”

如果是其他版本,需要自行同步,同步方法可以在网上找到相关文章。可以参考https://blog.csdn.net/sinat_35543900/article/details/103290782

还是 operator 文件,新版本 rook 默认关闭了自动发现容器的部署,可以找到 ROOK_ENABLE_DISCOVERY_DAEMON 改成 true 即可:

image-20230831170131006

部署 rook

1.5.3 版本的部署步骤如下:

cd cluster/examples/kubernetes/ceph

kubectl create -f crds.yaml -f common.yaml -f operator.yaml

等待 operator 容器和 discover 容器启动

[root@k8s-master01 ceph]#kubectl -n rook-ceph get pod|egrep ‘rook-ceph-operator|rook-discover’

image-20230831170310587

全部变成 1/1 Running 才可以创建 Ceph 集群

创建 ceph 集群

配置更改

主要更改的是 osd 节点所在的位置(cluster.yaml):

image-20230831170413051

注意:新版必须采用裸盘,即未格式化的磁盘。其中 k8s-master03 k8s-node01 node02 有新加的一个磁盘,可以通过 lsblk -f 查看新添加的磁盘名称。建议最少三个节点,否则后面的试验可能会出现问题

创建 Ceph 集群

kubectl create -f cluster.yaml

创建完成后,可以查看 pod 的状态:

[root@k8s-master01 ceph]# kubectl -n rook-ceph get pod

image-20230831170459980

需要注意的是,osd-x 的容器必须是存在的,且是正常的。如果上述 Pod 均正常,则认为集群安装成功。磁盘几个 osd 就是几个。

更多配置:https://rook.io/docs/rook/v1.6/ceph-cluster-crd.html

安装 ceph snapshot 控制器

k8s 1.19 版本以上需要单独安装 snapshot 控制器,才能完成 pvc 的快照功能,所以在此提前安装下,如果是 1.19 以下版本,不需要单独安装,直接参考视频即可。

snapshot 控制器的部署在集群安装时的 k8s-ha-install 项目中,需要切换到 1.20.x 分支:

cd /root/k8s-ha-install/

git checkout manual-installation-v1.20.x

创建 snapshot controller:

kubectl create -f snapshotter/ -n kube-system

[root@k8s-master01 k8s-ha-install]# kubectl get po -n kube-system -l app=snapshot-controller

具体文档:https://rook.io/docs/rook/v1.6/ceph-csi-snapshot.html

安装 ceph 客户端工具

[root@k8s-master01 ceph]# pwd

cd /root/rook/cluster/examples/kubernetes/ceph

[root@k8s-master01 ceph]# kubectl create -f toolbox.yaml -n rook-ceph

deployment.apps/rook-ceph-tools created

待容器 Running 后,即可执行相关命令

[root@k8s-master01 ceph]# kubectl get po -n rook-ceph -l app=rook-ceph-tools

image-20230831170745544

[root@k8s-master01 ceph]# kubectl -n rook-ceph exec -it deploy/rook-ceph-tools – bash

[root@rook-ceph-tools-fc5f9586c-9hs8q /]# ceph config set mon auth_allow_insecure_global_id_reclaim false

[root@rook-ceph-tools-6f7467bb4d-qzsvg /]# ceph status

image-20230831170821726

[root@rook-ceph-tools-6f7467bb4d-qzsvg /]# ceph osd status

注:按照文档应该只有 k8s-11-n1~n3,这里我都加入了

image-20230831170924183

image-20230831171017697

Ceph dashboard

暴露服务

默认情况下,ceph dashboard 是打开的,可以创建一个 nodePort 类型的 Service 暴露服务:

vim dashboard-np.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
kind: Service
metadata:
  labels:
    app: rook-ceph-mgr
    ceph_daemon_id: a
    rook_cluster: rook-ceph
  name: rook-ceph-mgr-dashboard-np
  namespace: rook-ceph
spec:
  ports:
  - name: http-dashboard
    port: 8443
    protocol: TCP
    targetPort: 8443
  selector:
    app: rook-ceph-mgr
    ceph_daemon_id: a
    rook_cluster: rook-ceph
  sessionAffinity: None
  type: NodePort

保存退出后,会创建一个端口,然后通过任意 k8s 节点的 IP+该端口即可访问该 dashboard:

[root@k8s-master01 ceph]# kubectl get svc -n rook-ceph rook-ceph-mgr-dashboard-np

image-20230831171156952

访问一下

image-20230831171534572

账号为 admin,查看密码:

kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{[‘data’][‘password’]}" | base64 –decode && echo

image-20230831172211082

问题警告解决:https://docs.ceph.com/en/octopus/rados/operations/health-checks/

ceph 块存储的使用

块存储一般用于一个 Pod 挂载一块存储使用,相当于一个服务器新挂了一个盘,只给一个应用使用。

参考文档:https://rook.io/docs/rook/v1.6/ceph-block.html

创建 StorageClass 和 ceph 的存储池

[root@k8s-master01 ceph]# pwd

/root/rook/cluster/examples/kubernetes/ceph

[root@k8s-master01 ceph]# vim csi/rbd/storageclass.yaml

failureDomain: host 是根据 host 来存放多个 OSD 副本,且模式为多个节点上(replicated:size 决定副本数量),若单台 node 故障可以通过其他节点上的数据恢复。因为我是试验环境,所以将副本数设置成了 2(不能设置为 1),生产环境最少为 3,且要小于等于 osd 的数量,其他配置可以参考视频:

image-20230831172333472

创建 StorageClass 和存储池:

[root@k8s-master01 ceph]# kubectl create -f csi/rbd/storageclass.yaml -n rook-ceph

查看创建的 cephblockpool 和 storageClass(StorageClass 没有 namespace 隔离性):

[root@k8s-master01 ceph]# kubectl get cephblockpool -n rook-ceph

[root@k8s-master01 ceph]# kubectl get sc

此时可以在 ceph dashboard 查看到改 Pool,如果没有显示说明没有创建成功

image-20230831172532677

挂载测试

创建一个 MySQL 服务

参考:https://rook.io/docs/rook/v1.6/ceph-block.html

[root@k8s-master01 kubernetes]# pwd

/root/rook/cluster/examples/kubernetes

使用 RDB 创建 mysql.yaml,mysql 要求有主从,有自己的独立空间使用块存储

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  storageClassName: rook-ceph-block
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi #测试环境修改小一些
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
    tier: mysql
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
        - image: mysql:5.6
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: changeme
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          persistentVolumeClaim:
            claimName: mysql-pv-claim

[root@k8s-master01 kubernetes]# kubectl create -f mysql.yaml

image-20230831172616220

pvc 会连接刚才创建的 storageClass,然后动态创建 pv,然后连接到 ceph 创建对应的存储

之后创建 pvc 只需要指定 storageClassName 为刚才创建的 StorageClass 名称即可连接到 rook 的 ceph。如果是 statefulset,只需要将 volumeTemplateClaim 里面的 Claim 名称改为 StorageClass 名称即可动态创建 Pod。

其中 MySQL deployment 的 volumes 配置挂载了该 pvc:

image-20230831172634958

claimName 为 pvc 的名称

因为 MySQL 的数据不能多个 MySQL 实例连接同一个存储,所以一般只能用块存储。相当于新加了一块盘给 MySQL 使用。

创建完成后可以查看创建的 pvc 和 pv

此时在 ceph dashboard 上面也可以查看到对应的 image 的 csi-vol

共享文件系统的使用

共享文件系统一般用于多个 Pod 共享一个存储

官方文档:https://rook.io/docs/rook/v1.6/ceph-filesystem.html

创建共享类型的文件系统

[root@k8s-master01 ceph]# pwd

/root/rook/cluster/examples/kubernetes/ceph

[root@k8s-master01 ceph]# kubectl create -f filesystem.yaml

cephfilesystem.ceph.rook.io/myfs created

[root@k8s-master01 ceph]# vim filesystem.yaml

创建完成后会启动 mds 容器,需要等待启动后才可进行创建 pv

[root@k8s-master01 ceph]# kubectl -n rook-ceph get pod -l app=rook-ceph-mds

也可以在 ceph dashboard 上面查看状态

image-20230831172745284

image-20230831172816707

创建共享类型文件系统的 StorageClass

[root@k8s-master01 cephfs]# pwd

/root/rook/cluster/examples/kubernetes/ceph/csi/cephfs

[root@k8s-master01 cephfs]# kubectl create -f storageclass.yaml

storageclass.storage.k8s.io/rook-cephfs created

之后将 pvc 的 storageClassName 设置成 rook-cephfs 即可创建共享文件类型的存储,类似于 NFS,可以给多个 Pod 共享数据。

挂载测试

[root@k8s-master01 cephfs]# pwd

/root/rook/cluster/examples/kubernetes/ceph/csi/cephfs

[root@k8s-master01 cephfs]# ls

image-20230831173001213

kube-registry.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cephfs-pvc
  namespace: kube-system
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  storageClassName: rook-cephfs
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kube-registry
  namespace: kube-system
  labels:
    k8s-app: kube-registry
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 3
  selector:
    matchLabels:
      k8s-app: kube-registry
  template:
    metadata:
      labels:
        k8s-app: kube-registry
        kubernetes.io/cluster-service: "true"
    spec:
      containers:
        - name: registry
          image: registry:2
          imagePullPolicy: Always
          resources:
            limits:
              cpu: 100m
              memory: 100Mi
          env:
            # Configuration reference: https://docs.docker.com/registry/configuration/
            - name: REGISTRY_HTTP_ADDR
              value: :5000
            - name: REGISTRY_HTTP_SECRET
              value: "Ple4seCh4ngeThisN0tAVerySecretV4lue"
            - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
              value: /var/lib/registry
          volumeMounts:
            - name: image-store
              mountPath: /var/lib/registry
          ports:
            - containerPort: 5000
              name: registry
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: registry
          readinessProbe:
            httpGet:
              path: /
              port: registry
      volumes:
        - name: image-store
          persistentVolumeClaim:
            claimName: cephfs-pvc
            readOnly: false

[root@k8s-master01 cephfs]# kubectl create -f kube-registry.yaml

查看创建的 pvc 和 pod

[root@k8s-master01 cephfs]# kubectl get po -n kube-system -l k8s-app=kube-registry

[root@k8s-master01 cephfs]# kubectl get pvc -n kube-system

该文件的 pvc 配置,用于连接 ceph 创建存储,如下:

image-20230831173103068

然后在 deployment 的 volumes 配置添加了该 pvc,并将其挂载到了/var/lib/registry

image-20230831173146832

注意 claimName 为 pvc 的名称。

此时一共创建了三个 Pod,这三个 Pod 共用了一个存储,挂载到了/var/lib/registry,该目录三个容器共享数据。

验证共享数据:

image-20230831173203708

Nginx 挂载测试

vim nginx.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
    selector:
    app: nginx
    type: ClusterIP
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nginx-share-pvc
spec:
  storageClassName: rook-cephfs
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  replicas: 3 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
      volumes:
        - name: www
          persistentVolumeClaim:
            claimName: nginx-share-pvc

kubectl create -f nginx.yaml

测试数据清理

如果 Rook 要继续使用,可以只清理创建的 deploy、pod、pvc 即可。之后可以直接投入使用

数据清理步骤(必须听课):

  1. 首先清理挂载了 PVC 和 Pod,可能需要清理单独创建的 Pod 和 Deployment 或者是其他的高级资源 kubectl delete deployments.apps wordpress-mysql –all kubectl delete pod –all
  2. 之后清理 PVC,清理掉所有通过 ceph StorageClass 创建的 PVC 后,最好检查下 PV 是否被清理 kubectl delete pvc –all
  3. 之后清理快照:kubectl delete volumesnapshot XXXXXXXX
  4. 之后清理创建的 Pool,包括块存储和文件存储
    1. kubectl delete -n rook-ceph cephblockpool replicapool
    2. kubectl delete -n rook-ceph cephfilesystem myfs
  5. 清理 StorageClass:kubectl delete sc rook-ceph-block rook-cephfs
  6. 清理 Ceph 集群:kubectl -n rook-ceph delete cephcluster rook-ceph
  7. 删除 Rook 资源:
    1. kubectl delete -f operator.yaml
    2. kubectl delete -f common.yaml
    3. kubectl delete -f crds.yaml
  8. 如果卡住需要参考 Rook 的 troubleshooting
    1. https://rook.io/docs/rook/v1.6/ceph-teardown.html#troubleshooting

for CRD in $(kubectl get crd -n rook-ceph | awk ‘/ceph.rook.io/ {print $1}’); do kubectl get -n rook-ceph “$CRD” -o name | xargs -I {} kubectl patch {} –type merge -p ‘{“metadata”:{“finalizers”: [null]}}’ -n rook-ceph; done

  1. 清理数据目录和磁盘

参考链接:https://rook.io/docs/rook/v1.6/ceph-teardown.html#delete-the-data-on-hosts

参考链接:https://rook.io/docs/rook/v1.6/ceph-teardown.html

清除已经安装 rook-ceph

1
2
3
4
5
6
7
8
9
kubectl delete -n rook-ceph cephblockpool replicapool
kubectl delete storageclass rook-ceph-block
kubectl delete storageclass csi-cephfs

kubectl -n rook-ceph delete cephcluster rook-ceph

kubectl delete -f operator.yaml
kubectl delete -f common.yaml
kubectl delete -f crds.yaml

清理磁盘的脚本再次记录一下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# yum -y install gdisk

#!/usr/bin/env bash
DISK="/dev/sdb" # 修改具体的磁盘

# Zap the disk to a fresh, usable state (zap-all is important, b/c MBR has to be clean)

# You will have to run this step for all disks.
sgdisk --zap-all $DISK

# Clean hdds with dd # 机械磁盘使用这个命令清除磁盘数据
dd if=/dev/zero of="$DISK" bs=1M count=100 oflag=direct,dsync

# Clean disks such as ssd with blkdiscard instead of dd # 固态磁盘使用这个命令清除磁盘数据,若不是固态磁盘则会提示不支持这一步操作
blkdiscard $DISK

# These steps only have to be run once on each node
# If rook sets up osds using ceph-volume, teardown leaves some devices mapped that lock the disks.
ls /dev/mapper/ceph-* | xargs -I% -- dmsetup remove %

# ceph-volume setup can leave ceph-<UUID> directories in /dev and /dev/mapper (unnecessary clutter)
rm -rf /dev/ceph-*
rm -rf /dev/mapper/ceph--*

# Inform the OS of partition table changes
partprobe $DISK

清理/var/lib/rook 目录。

如果遇到 invalid capacity 0 on image filesystem

1
systemctl restart containerd

failed to get sandbox image “k8s.gcr.io/pause:3.6”

由于 k8s.gcr.io 需要连外网才可以拉取到,导致 k8s 的基础容器 pause 经常无法获取。k8s docker 可使用代理服拉取,再利用 docker tag 解决问题

1
2
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6 k8s.gcr.io/pause:3.6

但是我们 k8s 集群中使用的 CRI 是 containerd。所以只能通过 docker tag 镜像,再使用 ctr 导入镜像.

1
2
docker save k8s.gcr.io/pause -o pause.tar
ctr -n k8s.io images import pause.tar

安装 Pod 网络附加组件(calico 或 flannel)

calico 安装文档

flannel flannel 节点之间无法通信解决办法

允许控制平面节点上调度 Pod

1
kubectl taint nodes --all node-role.kubernetes.io/control-plane- node-role.kubernetes.io/master-

加入节点

遇到问题

1
2
3
4
5
error execution phase control-plane-prepare/download-certs: error downloading certs: error downloading the secret: secrets "kubeadm-certs" is forbidden
# certificate-key 默认2小时的有效期,如果过期按照提示重新生成
# 使用命令重新生成 certificate-key
# 用新证书替换--certificate-key后面的内容
$ kubeadm init phase upload-certs --upload-certs

不关闭 swap 启动 k8s

1
vi /etc/sysconfig/kubelet
1
KUBELET_EXTRA_ARGS="--fail-swap-on=false"

dashboard

其他 pc 访问 dashboard,端口转发 安装 dashboard

1
ssh -L localhost:8001:localhost:8001 -NT root@<ip>

创建用户

获取 Token

1
kubectl -n kubernetes-dashboard create token admin-user

安装 helm

helm

安装 ingress

选择下面任何一个即可

haproxy

haproxy-ingress

traefik

install-traefik

nginx-ingress

NGINX Ingress Controller

外部负载均衡器 metalLB

metalLB

ingress 配置 Https

准备好证书文件,各种证书之间的转换方式参考转换证书格式

创建 secret 保存证书

1
2
3
kubectl create secret tls your-domian.com-tls -n your-namespace \
  --cert=/root/ca/cert.pem \
  --key=/root/ca/key.pem

ingress 使用证书

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: haproxy
  name: hello-https
  namespace: your-namespace
spec:
  rules:
    - host: your-domian.com
      http:
        paths:
          - backend:
              service:
                name: hello-tls
                port:
                  number: 8080
            path: /
            pathType: Prefix
  tls:
    - hosts:
        - your-domian.com
      secretName: your-domian.com-tls

常用工具安装

1
yum install systemd-networkd

ceph 常用操作

显示 ceph pools

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 ceph osd lspools

删除存储池
$ ceph osd pool delete  replicapool  replicapool --yes-i-really-really-mean-it


 ceph osd pool set replicapool pg_num 16
 ceph osd pool set replicapool pgp_num 16
 ceph osd pool get  replicapool pgp_num
ceph osd pool set replicapool pg_num 256
ceph osd pool set replicapool pgp_num 256
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
清除测试数据

rados -p replicapool cleanup
rados -p  myfs-replicated cleanup


  #进行性能测试
 rados bench -p replicapool  10 write --no-cleanup
 rados bench -p replicapool  10 write --no-cleanup -t 30 -b 4M
  rados bench -p myfs-replicated   10 write -t 30 -b 4M
  rados bench -p myfs-replicated  10 write --no-cleanup -t 30 -b 4M

MySQL 单实例配置

容器资源:

  • CPU:8C
  • 内存:24G
  • 磁盘:100G(基于 Ceph RBD,在存储千万级文件的场景下元数据大约占用 30G 磁盘空间)
  • 容器镜像:mysql:5.7

MySQL 的 my.cnf 配置:

1
2
3
ignore-db-dir=lost+found  # 如果使用 MySQL 8.0 及以上版本,需要删除这个配置
max-connections=4000
innodb-buffer-pool-size=12884901888  # 12G复制代码对象存储
1
2
3
4
5
6
7
8
一个OSD可以设置250个PG。
一个pool默认是3副本机制,创建pool的 pg_num * 3
确定取值是强制性的,因为不能自动计算。下面是几个常用的值(总的pg):

少于 5 个 OSD 时可把 pg_num 设置为 128
OSD 数量在 5 到 10 个时,可把 pg_num 设置为 512
OSD 数量在 10 到 50 个时,可把 pg_num 设置为 4096
OSD 数量大于 50 时,你得理解权衡方法、以及如何自己计算 pg_num 取值

ceph 排查错误的使用,使用

1
2
 ceph health detail
 ceph df

ceph 报错 low disk space

出现这个问题是因为磁盘的根目录低于 30%可用,就会报这个错。

参考磁盘空间 , 故障原因: / 磁盘空间少于 70%

1
2
[root@hh-yun-ceph-cinder026-128076 ~]# df -h | grep -E 'root|home'
/dev/mapper/centos-root   50G   35G   16G   70% /

缩减 HOME 磁盘空间

1
2
3
4
5
6
[root@hh-yun-ceph-cinder026-128076 /]# lvreduce -L100g /dev/centos/home
  WARNING: Reducing active and open logical volume to 100.00 GiB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce home? [y/n]: y
  Size of logical volume centos/home changed from 2.64 TiB (691200 extents) to 100.00 GiB (25600 extents).
  Logical volume home successfully resized

查询 lvm 空间

1
2
3
4
5
6
7
8
9
[root@hh-yun-ceph-cinder026-128076 /]# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  home centos -wi-ao---- 100.00g
  root centos -wi-ao----  50.00g
  swap centos -wi-ao----  31.44g

[root@hh-yun-ceph-cinder026-128076 /]# vgs
  VG     #PV #LV #SN Attr   VSize VFree
  centos   1   3   0 wz--n- 3.64t 3.46t

扩容 root 空间

1
2
3
[root@hh-yun-ceph-cinder026-128076 /]# lvextend -l +100%FREE /dev/centos/root
  Size of logical volume centos/root changed from 50.00 GiB (12800 extents) to 3.51 TiB (919900 extents).
  Logical volume root successfully resized

检查 LVM

1
2
3
4
5
[root@hh-yun-ceph-cinder026-128076 /]# lvs
  LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  home centos -wi-ao---- 100.00g
  root centos -wi-ao----   3.51t
  swap centos -wi-ao----  31.44g

查询文件系统

1
2
3
4
5
6
7
[root@hh-yun-ceph-cinder026-128076 /]# df -h | grep -E 'root|home'
/dev/mapper/centos-root   50G   35G   16G   70% /
/dev/mapper/centos-home  3.6T   33M  3.6T    1% /home

[root@hh-yun-ceph-cinder026-128076 /]# mount | grep -E 'root|home'
/dev/mapper/centos-root on / type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/centos-home on /home type xfs (rw,relatime,attr2,inode64,noquota)

扩容文件系统

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[root@hh-yun-ceph-cinder026-128076 /]#  xfs_growfs -d /
meta-data=/dev/mapper/centos-root isize=256    agcount=4, agsize=3276800 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=0        finobt=0
data     =                       bsize=4096   blocks=13107200, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=6400, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 13107200 to 941977600
[root@hh-yun-ceph-cinder026-128076 /]# df -h
文件系统                 容量  已用  可用 已用% 挂载点
/dev/mapper/centos-root  3.6T   35G  3.5T    1% /

home 目录已经破坏, 需要进行重新格式化. 并进行数据恢复

参考 ceph 信息

1
2
[root@hh-yun-ceph-cinder026-128076 ~]# ceph health detail
HEALTH_OK
Licensed under CC BY-NC-SA 4.0
最后更新于 Jan 06, 2025 05:52 UTC
comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计
Caret Up