最近在项目中有涉及到Kubernetes的分布式存储部分的内容,也抽空多了解了一些。项目主要基于Rook-Ceph运行,考虑到Rook-Ceph部署也不那么简单,官方文档的步骤起点也不算低,所以,在整合官方文档的某些步骤的基础上,写篇文章简单总结一下。html
Rook-Ceph是Kubernetes中分布式存储的一种解决方案,Rook做为一种开源的、云原生的存储编排器,为各类存储服务在云原生的环境中实现无缝整合,提供了所必须的平台、框架和服务;而Ceph则是Rook所支持的众多存储方案的一种,在Kubernetes环境里,Ceph基于Rook可以为应用程序提供块存储(Block Storage),对象存储(Object Storage)以及共享文件系统(SFS)服务。此处就不对Rook Ceph进行太多的介绍,直接步入正题,一步一步地演练Rook-Ceph从安装部署到使用的整个过程。node
注意:本文全部的yaml文件都是为了配合整个演练过程而设计的,理论上不能直接用在生产环境。若有须要,在用在生产环境以前,请确保所需的参数都已正确配置。linux
安装Kubernetes。安装方法有不少,不怕麻烦能够徒手安装,也能够直接使用云供应商的托管服务,好比Azure AKS,也可使用Rancher RKE,在此就不赘述了。shell
这里咱们基于Ceph来讨论。事实上Rook支持Ceph、Cassandra、CockroachDB、EdgeFS、NFS以及YugabyteDB等多种存储供应商(Storage Provider),针对不一样的存储供应商,Rook提供不一样的Operator来进行资源的部署和管理。使用下面的命令来安装Rook Ceph Operator:json
helm repo add rook-release https://charts.rook.io/release kubectl create namespace rook-ceph helm install --namespace rook-ceph rook-ceph rook-release/rook-ceph
可使用下面的yaml文件:api
# ceph-cluster-deploy.yaml apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: name: rook-ceph namespace: rook-ceph spec: cephVersion: image: ceph/ceph:v15.2.7 allowUnsupported: false dataDirHostPath: /var/lib/rook skipUpgradeChecks: false continueUpgradeAfterChecksEvenIfNotHealthy: false mon: count: 3 allowMultiplePerNode: false mgr: modules: - name: pg_autoscaler enabled: true dashboard: enabled: true ssl: true monitoring: enabled: false rulesNamespace: rook-ceph network: crashCollector: disable: false cleanupPolicy: confirmation: "" sanitizeDisks: method: quick dataSource: zero iteration: 1 allowUninstallWithVolumes: false annotations: labels: resources: removeOSDsIfOutAndSafeToRemove: false useAllNodes: true useAllDevices: false deviceFilter: nvme1n1 config: osdsPerDevice: "1" disruptionManagement: managePodBudgets: false osdMaintenanceTimeout: 30 pgHealthCheckTimeout: 0 manageMachineDisruptionBudgets: false machineDisruptionBudgetNamespace: openshift-machine-api healthCheck: daemonHealth: mon: disabled: false interval: 45s osd: disabled: false interval: 60s status: disabled: false interval: 60s livenessProbe: mon: disabled: false mgr: disabled: false osd: disabled: false
而后使用如下命令建立Ceph集群:bash
kubectl create -f ceph-cluster-deploy.yaml
命令执行成功以后,须要等待几分钟,以便OSD可以成功启动。执行下面的命令能够查看全部容器的状态:app
kubectl -n rook-ceph get pod
正常状况下,应该能够看到相似如下的结果:框架
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
须要注意几点:curl
ceph-cluster-deploy.yaml
并无包括全部的Ceph集群建立的参数,能够参考https://rook.io/docs/rook/v1.5/ceph-cluster-crd.html 来了解全部的配置信息deviceFilter: nvme1n1
是用来指定在每一个Kubernetes节点上应该使用的卷(Volume)的名称。这个Volume不能格式化成任何文件系统,不然Ceph将不会使用它做为存储卷。我在AWS上建立了独立的EBS卷,而后直接Attach到Kubernetes节点的机器上,经过lsblk
命令便可得到卷的名称,将这个名称填入deviceFilter
设置便可Rook Toolbox是一个运行在rook-ceph命名空间下的容器,经过它能够执行一些Ceph的管理任务,建议安装,仍是挺实用的。建立一个yaml文件:
# rook-toolbox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: rook-ceph-tools namespace: rook-ceph labels: app: rook-ceph-tools spec: replicas: 1 selector: matchLabels: app: rook-ceph-tools template: metadata: labels: app: rook-ceph-tools spec: dnsPolicy: ClusterFirstWithHostNet containers: - name: rook-ceph-tools image: rook/ceph:v1.5.3 command: ["/tini"] args: ["-g", "--", "/usr/local/bin/toolbox.sh"] imagePullPolicy: IfNotPresent env: - name: ROOK_CEPH_USERNAME valueFrom: secretKeyRef: name: rook-ceph-mon key: ceph-username - name: ROOK_CEPH_SECRET valueFrom: secretKeyRef: name: rook-ceph-mon key: ceph-secret volumeMounts: - mountPath: /etc/ceph name: ceph-config - name: mon-endpoint-volume mountPath: /etc/rook volumes: - name: mon-endpoint-volume configMap: name: rook-ceph-mon-endpoints items: - key: data path: mon-endpoints - name: ceph-config emptyDir: {} tolerations: - key: "node.kubernetes.io/unreachable" operator: "Exists" effect: "NoExecute" tolerationSeconds: 5
而后:
kubectl create -f rook-toolbox.yaml
接着能够执行下面的命令,进入Rook Toolbox容器:
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
而后使用ceph status
命令来查看集群的状态。正常的话应该能够看到相似下面的结果:
$ ceph status cluster: id: a0452c76-30d9-4c1a-a948-5d8405f19a7c health: HEALTH_OK services: mon: 3 daemons, quorum a,b,c (age 3m) mgr: a(active, since 2m) osd: 3 osds: 3 up (since 1m), 3 in (since 1m)
必定要确保health
的状态为HEALTH_OK
,若是不是HEALTH_OK
,则须要排查缘由并解决。问题排查指南:https://rook.io/docs/rook/v1.5/ceph-common-issues.html。
使用下面的yaml:
# ceph-block-deploy.yaml apiVersion: ceph.rook.io/v1 kind: CephBlockPool metadata: name: replicapool namespace: rook-ceph spec: failureDomain: host replicated: size: 3 --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rook-ceph-block annotations: storageclass.kubernetes.io/is-default-class: "true" provisioner: rook-ceph.rbd.csi.ceph.com parameters: clusterID: rook-ceph pool: replicapool imageFormat: "2" imageFeatures: layering csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph csi.storage.k8s.io/fstype: ext4 reclaimPolicy: Retain
而后:
Kubectl create -f ceph-block-deploy.yaml
在这个yaml中,同时定义了名为rook-ceph-block
的StorageClass
,用以在pods启动的时候可以动态建立基于Ceph的块存储(经过pool: replicapool
的设置指定)。此外,在这个StorageClass中,设定了storageclass.kubernetes.io/is-default-class: "true"
。所以,在PersistentVolumeClaim
中即便没有指定storageClassName
,Kubernetes也会默认使用Ceph块存储来保存app的数据。
部署块存储的详细内容能够参考:https://rook.io/docs/rook/v1.5/ceph-block.html。
使用下面的yaml:
# ceph-s3-deploy.yaml apiVersion: ceph.rook.io/v1 kind: CephObjectStore metadata: name: my-store namespace: rook-ceph spec: metadataPool: failureDomain: host replicated: size: 3 dataPool: failureDomain: host erasureCoded: dataChunks: 2 codingChunks: 1 preservePoolsOnDelete: true gateway: type: s3 sslCertificateRef: port: 80 # securePort: 443 instances: 3 healthCheck: bucket: disabled: false interval: 60s
而后:
kubectl create -f ceph-s3-deploy.yaml
等待几分钟后,执行下面的命令:
kubectl -n rook-ceph get pod -l app=rook-ceph-rgw
此时应该能够在pod的列表中看到名字包含有rgw的pod处于Running
状态。
接下来就是要在对象存储上建立Bucket。官方提供了基于StorageClass的建立方式。这里介绍另外一种方式,就是借用MINIO的管理工具来建立。使用下面的shell脚本:
# setup-s3-storage.sh #! /bin/bash echo "Creating Ceph User" CREATE_USER_OUTPUT=`kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- radosgw-admin user create --uid=system-user --display-name=system-user --system` ACCESS_KEY=$(echo $CREATE_USER_OUTPUT | jq -r ".keys[0].access_key") SECRET_KEY=$(echo $CREATE_USER_OUTPUT | jq -r ".keys[0].secret_key") echo "User was created successfully" echo "S3 ACCESS KEY = $ACCESS_KEY" echo "S3 SECRET KEY = $SECRET_KEY" echo "Creating Ceph S3 Bucket" kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- curl https://dl.min.io/client/mc/release/linux-amd64/mc --output mc kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- chmod +x mc kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- ./mc config host add mys3 http://rook-ceph-rgw-signals-store/ "$ACCESS_KEY" "$SECRET_KEY" kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- ./mc mb mys3/data echo "Ceph S3 Bucket created successfully" echo "S3 ACCESS KEY = $ACCESS_KEY" echo "S3 SECRET KEY = $SECRET_KEY"
在确保了当前机器上安装了jq
后,执行:
chmod +x setup-s3-storage.sh ./setup-s3-storage.sh
此时会输出S3的Access Key和Secret Key。建立的Bucket名为data。
验证Object Storage是否部署成功,首先执行下面的命令进入Rook Toolbox:
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
而后执行:
export AWS_HOST=<host> export AWS_ENDPOINT=<endpoint> export AWS_ACCESS_KEY_ID=<accessKey> export AWS_SECRET_ACCESS_KEY=<secretKey>
rook-ceph-rgw-my-store.rook-ceph
kubectl -n rook-ceph get svc rook-ceph-rgw-my-store
,而后将ClusterIP和端口号拼接起来做为endpoint的值
export AWS_HOST=rook-ceph-rgw-my-store.rook-ceph export AWS_ENDPOINT=10.104.35.31:80 export AWS_ACCESS_KEY_ID=XEZDB3UJ6X7HVBE7X7MA export AWS_SECRET_ACCESS_KEY=7yGIZON7EhFORz0I40BFniML36D2rl8CQQ5kXU6l
接下来,安装一个s3cmd的工具:
yum --assumeyes install s3cmd
而后随便写一些内容到rookObj文件:
echo "Hello Rook" > /tmp/rookObj
而后经过s3cmd,将这个文件保存到S3:
s3cmd put /tmp/rookObj --no-ssl --host=${AWS_HOST} --host-bucket= s3://data
注意--host-bucket=
后的空格。
而后,使用s3cmd从Bucket将文件下载并另存为另外一个文件:
s3cmd get s3://data/rookObj /tmp/rookObj-download --no-ssl --host=${AWS_HOST} --host-bucket=
最后,经过cat
命令,查看下载下来的文件的内容是否正确:
cat /tmp/rookObj-download
若是可以看到Hello Rook
的输出字样,表示一切正常。接下来就能够在app中使用Ceph Block Storage和Ceph Object Storage了。
部署对象存储的详细内容能够参考:https://rook.io/docs/rook/v1.5/ceph-object.html。
以后我会使用Microsoft .NET 5,编写一个Web API应用程序并部署到Kubernetes环境,演示如何在app中使用本文所部署的Ceph Block Storage和Ceph Object Storage。