Kubernetes平台存储系统部署
官方文档:Ceph Docs
一、查看前提条件
- Raw devices (no partitions or formatted filesystems); 原始磁盘,无分区或者格式化
- Raw partitions (no formatted filesystem);原始分区,无格式化文件系统
fdisk -l
# 找到自己挂载的磁盘
# 如: /dev/vdc
# 查看满足要求的
lsblk -f
#云厂商都这么磁盘清0
dd if=/dev/zero of=/dev/vdc bs=1M status=progress
NAME FSTYPE LABEL UUID MOUNTPOINT vda └─vda1 LVM2_member >eSO50t-GkUV-YKTH-WsGq-hNJY-eKNf-3i07IB ├─ubuntu--vg-root ext4 c2366f76-6e21-4f10-a8f3-6776212e2fe4 / └─ubuntu--vg-swap_1 swap 9492a3dc-ad75-47cd-9596-678e8cf17ff9 [SWAP] vdb
vdb 是可用的
二、部署&修改operator
代码语言:javascript复制cd cluster/examples/kubernetes/ceph
kubectl create -f crds.yaml -f common.yaml -f operator.yaml #注意修改operator镜像
# verify the rook-ceph-operator is in the `Running` state before proceeding
kubectl -n rook-ceph get pod
代码语言:javascript复制修改operator.yaml 把以前的默认镜像换成能用的,如下
# ROOK_CSI_CEPH_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/cephcsi:v3.3.1"
# ROOK_CSI_REGISTRAR_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-node-driver-registrar:v2.0.1"
# ROOK_CSI_RESIZER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-resizer:v1.0.1"
# ROOK_CSI_PROVISIONER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-provisioner:v2.0.4"
# ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-snapshotter:v4.0.0"
# ROOK_CSI_ATTACHER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-attacher:v3.0.2"
镜像: rook/ceph:v1.6.3
换成 registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/rook-ceph:v1.6.3
## 建议修改以下的东西。在operator.yaml里面
ROOK_CSI_CEPH_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/cephcsi:v3.3.1"
ROOK_CSI_REGISTRAR_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-node-driver-registrar:v2.0.1"
ROOK_CSI_RESIZER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-resizer:v1.0.1"
ROOK_CSI_PROVISIONER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-provisioner:v2.0.4"
ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-snapshotter:v4.0.0"
ROOK_CSI_ATTACHER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/csi-attacher:v3.0.2"
三、部署集群
代码语言:javascript复制修改
cluster.yaml
使用我们指定的磁盘当做存储节点即可
storage: # cluster level storage configuration and selection
useAllNodes: false
useAllDevices: false
config:
osdsPerDevice: "3" #每个设备osd数量
nodes:
- name: "k8s-node3"
devices:
- name: "vdc"
- name: "k8s-node1"
devices:
- name: "vdc"
- name: "k8s-node2"
devices:
- name: "vdc"
镜像: ceph/ceph:v15.2.11
换成 registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ceph-ceph:v15.2.11
四、部署dashboard
Ceph Docs
前面的步骤,已经自动部署了
代码语言:javascript复制kubectl -n rook-ceph get service
#查看service
#为了方便访问我们改为nodePort。应用nodePort文件
#获取访问密码
kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo
#默认账号 admin
4/qt]e5wad_HY:0&V.ba
MGR: 2;只有一个能用
Mon: 3; 全部可用
Osd: 全部可用
部署了高可用的mgr:提供页面。
- 先部署nodePort,验证到底哪个mgr不能访问
- 他是主备模式的高可用。kubectl get svc -n rook-ceph|grep dashboard
- curl 访问dashboard确定哪个mgr不能访问
- 自己做一个可访问到的service。如果哪天服务器故障mgr有问题。修改svc的selector即可
apiVersion: v1
kind: Service
metadata:
labels:
app: rook-ceph-mgr
ceph_daemon_id: a
rook_cluster: rook-ceph
name: rook-ceph-mgr-dashboard-active
namespace: rook-ceph
spec:
ports:
- name: dashboard
port: 8443
protocol: TCP
targetPort: 8443
selector: #service选择哪些Pod
app: rook-ceph-mgr
ceph_daemon_id: a
rook_cluster: rook-ceph
sessionAffinity: None
type: ClusterIP
- 再部署如下的ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ceph-rook-dash
namespace: rook-ceph
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/server-snippet: |
proxy_ssl_verify off;
spec:
# tls: 不用每个名称空间都配置证书信息
# - hosts:
# - itdachang.com
# - 未来的
# secretName: testsecret-tls
rules:
- host: rook.itdachang.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rook-ceph-mgr-dashboard-active
port:
number: 8443
五、神坑
代码语言:javascript复制#部署完成的最终结果一定要有这些组件
NAME READY STATUS RESTARTS AGE
csi-cephfsplugin-provisioner-d77bb49c6-n5tgs 5/5 Running 0 140s
csi-cephfsplugin-provisioner-d77bb49c6-v9rvn 5/5 Running 0 140s
csi-cephfsplugin-rthrp 3/3 Running 0 140s
csi-rbdplugin-hbsm7 3/3 Running 0 140s
csi-rbdplugin-provisioner-5b5cd64fd-nvk6c 6/6 Running 0 140s
csi-rbdplugin-provisioner-5b5cd64fd-q7bxl 6/6 Running 0 140s
rook-ceph-crashcollector-minikube-5b57b7c5d4-hfldl 1/1 Running 0 105s
rook-ceph-mgr-a-64cd7cdf54-j8b5p 1/1 Running 0 77s
rook-ceph-mon-a-694bb7987d-fp9w7 1/1 Running 0 105s
rook-ceph-mon-b-856fdd5cb9-5h2qk 1/1 Running 0 94s
rook-ceph-mon-c-57545897fc-j576h 1/1 Running 0 85s
rook-ceph-operator-85f5b946bd-s8grz 1/1 Running 0 92m
rook-ceph-osd-0-6bb747b6c5-lnvb6 1/1 Running 0 23s
rook-ceph-osd-1-7f67f9646d-44p7v 1/1 Running 0 24s
rook-ceph-osd-2-6cd4b776ff-v4d68 1/1 Running 0 25s
rook-ceph-osd-prepare-node1-vx2rz 0/2 Completed 0 60s
rook-ceph-osd-prepare-node2-ab3fd 0/2 Completed 0 60s
rook-ceph-osd-prepare-node3-w4xyz 0/2 Completed 0 60s
代码语言:javascript复制#解决方案。
#找到自己的operator,删除这个pod,让重新执行
kubectl delete pod rook-ceph-operator-65965c66b5-cxrl8 -n rook-ceph
#rbd:是ceph用来做块存储的
#cephfs:是用来做共享文件系统的
六、卸载
代码语言:javascript复制# rook集群的清除,
##1、 delete -f 之前的yaml
##2、 再执行如下命令
kubectl -n rook-ceph get cephcluster
kubectl -n rook-ceph patch cephclusters.ceph.rook.io rook-ceph -p '{"metadata":{"finalizers": []}}' --type=merge
##3、 清除每个节点的 /var/lib/rook 目录
## 顽固的自定义资源删除;
kubectl -n rook-ceph patch cephblockpool.ceph.rook.io replicapool -p '{"metadata":{"finalizers": []}}' --type=merge
Rook Ceph;
- Rook帮我们创建好 StorageClass
- pvc只需要指定存储类,Rook自动调用 StorageClass 里面的 Provisioner供应商,接下来对ceph集群操作
- Ceph
- Block:块存储。RWO(ReadWriteOnce)单节点读写【一个Pod操作一个自己专属的读写区】,适用于(有状态副本集)
- Share FS:共享存储。RWX(ReadWriteMany)多节点读写【多个Pod操作同一个存储区,可读可写】,适用于无状态应用。(文件系统 )
- 总结: 无状态应用随意复制多少份,一定用到RWX能力。有状态应用复制任意份,每份都只是读写自己的存储,用到RWO(优先)或者RWX。
- 直接通过Rook可以使用到任意能力的存储。
CRI、CNI、CSI
CRI:Container Runtime Interface:容器运行时接口(k8s集群整合容器运行时环境)
CNI:Container Network Interface:容器网络接口(k8s集群整合网络组件的接口)
CSI:Container Storage Interface:容器存储接口(k8s集群整合存储组件的接口)
kubelet启动一个Pod。CRI、CNI、CSI 起作用的顺序
- 启动Pod流程
- 每个Pod,都伴随一个Pause容器(沙箱容器)。真正的容器(nginx-pvc)和沙箱容器是公用一个网络、存储、名称空间。。。。
- 启动沙箱容器。给沙箱容器设置好网络,存储
- CRI。创建沙箱容器的运行时环境
- CNI。挂载沙箱容器网络等
- CSI。调用存储系统进行数据挂载。(提前把应用容器需要挂载的挂进来)
- 启动应用容器。(kubectl get pod 1/1【不算沙箱容器】 )
- 应用容器直接创建运行时CRI,用以上的 CNI、CSI
- 从应用容器角度出发:
CSI先与CRI启动
。 - 从Pod出发。CRI。CNI。CSI
- 沙箱容器代码 kubernetes/docker_sandbox.go at d541872f9a036ed4f792232e43fde6dacf0e1084 · kubernetes/kubernetes · GitHub
- 应用容器 kubernetes/kubelet.go at d541872f9a036ed4f792232e43fde6dacf0e1084 · kubernetes/kubernetes · GitHub
- 判断网络(前面准备好的)
- 挂载
- 容器启动