k8s使用ceph存储
ceph配置
rbd create --size 100 rbd/nginx-image
[root@localhost my-cluster]# rbd list
nginx-image
[root@localhost my-cluster]# rbd info nginx-image
rbd image 'nginx-image':
size 100MiB in 25 objects
order 22 (4MiB objects)
block_name_prefix: rbd_data.5e4d6b8b4567
format: 2
features: layering
flags:
create_timestamp: Tue Apr 30 18:10:05 2019
[root@localhost my-cluster]#
# 获取密码
[root@localhost my-cluster]# ceph auth get-key client.admin | base64
QVFDRTQ4ZGNLRFVIRFJBQTVGd2J5QzU0d3B0cGJuOTREcjM1VHc9PQ==
k8s 配置
通过静态pv,pvc使用ceph
每次重建需要先执行 rbd map 将镜像挂载到node节点,rbd卷允许将Rados块设备卷安装到Pod中。与删除Pod时擦除emptyDir不同,rbd卷的内容被保留,而卷仅被卸载。这意味着RBD卷可以预先填充数据,并且可以在pod之间“传递”数据。ceph RBD只能进行单节点读写或多节点读,不能进行多节点读写.但是有的业务可能需要多节点读写的功能,可用cephfs解决了这个问题。
安装ceph-common
yum -y install ceph-common
ceph配置拷至k8s node 节点
ceph.conf ,ceph.client.admin.keyring 至 /etc/ceph/ 目录
格式化为 xfs
[root@localhost my-cluster]# rbd map nginx-image
/dev/rbd0
[root@localhost my-cluster]# mkfs.xfs /dev/rbd0
[root@localhost my-cluster]# rbd unmap nginx-image
- 创建ceph的secret
cat ceph-secret.yaml
**********************
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
type: "kubernetes.io/rbd"
data:
key: QVFDTTlXOWFOMk9IR3hBQXZyUjFjdGJDSFpoZUtmckY0N2tZOUE9PQ==
kubectl create -f ceph-secret.yaml
[root@node1 work]# kubectl get secret
NAME TYPE DATA AGE
ceph-secret Opaque 1 8d
default-token-7s88r kubernetes.io/service-account-token 3 11d
- 创建PV
[root@node1 work]# cat nginx-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
rbd:
monitors:
- 192.168.6.156:6789,192.168.6.157:6789,192.168.6.158:6789
pool: rbd
image: nginx-image
user: admin
secretRef:
name: ceph-secret
fsType: xfs
readOnly: false
persistentVolumeReclaimPolicy: Recycle
- 创建PVC
[root@node1 work]# cat nginx-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
kubectl create -f nginx-pvc.yml
- 创建Deployment并挂载
[root@node1 work]# cat nginx-deploy.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: demo
spec:
replicas: 3
template:
metadata:
labels:
app: demo
spec:
containers:
- name: demo
image: mritd/demo
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/data"
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: nginx-pvc
[root@node1 work]# rbd map nginx-image
/dev/rbd0
[root@node1 work]# kubectl create -f nginx-deploy.yml
deployment "demo" created
- 创建service
[root@node1 work]# kubectl expose deployment/demo
service "demo" exposed
[root@node1 work]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo ClusterIP 10.254.170.53 <none> 80/TCP 6m
kubernetes ClusterIP 10.254.0.1 <none> 443/TCP 11d
当前k8s1.8版本对于pv 的 RWO 似乎是有bug的,三个pod都挂载了pv,都可写数据,但相互看不到,正常应当是只有一个pod 创建成功。rbd使用前,需要在节点上执行 rbd map 命令,也不太方便。
https://github.com/kubernetes/kubernetes/issues/60903
测试多pod挂载静态pv数据不一致问题
[root@node1 work]# ansible k8s -a 'rbd map nginx-image'
192.168.6.161 | SUCCESS | rc=0 >>
/dev/rbd0
192.168.6.162 | SUCCESS | rc=0 >>
/dev/rbd0
192.168.6.163 | SUCCESS | rc=0 >>
/dev/rbd1
[root@node1 work]# kubectl create -f nginx-deploy.yml
deployment "demo" created
[root@node1 work]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ceph-mysql-pod 1/1 Running 0 8d
demo-579d6c87d6-5c59l 1/1 Running 0 10s
demo-579d6c87d6-dck74 1/1 Running 0 10s
demo-579d6c87d6-gg9jf 1/1 Running 0 10s
[root@node1 work]# for i in `kubectl get pods -l app=demo|grep demo|awk '{print $1}'`; do kubectl exec -it $i touch /data/$i.txt ;done;
[root@node1 work]# for i in `kubectl get pods -l app=demo|grep demo|awk '{print $1}'`; do kubectl exec -it $i ls /data ;done;
3.txt demo-579d6c87d6-5c59l.txt
3.txt demo-579d6c87d6-dck74.txt
3.txt demo-579d6c87d6-gg9jf.txt
每个 pod 文件各不相同。
删除deploy后重建pod
[root@node1 work]# kubectl delete -f nginx-deploy.yml
deployment "demo" deleted
[root@node1 work]# ansible k8s -a 'rbd map nginx-image'
192.168.6.161 | SUCCESS | rc=0 >>
/dev/rbd0
192.168.6.162 | SUCCESS | rc=0 >>
/dev/rbd0
192.168.6.163 | SUCCESS | rc=0 >>
/dev/rbd1
[root@node1 work]# kubectl create -f nginx-deploy.yml
deployment "demo" created
[root@node1 work]# kubectl get pods
NAME READY STATUS RESTARTS AGE
ceph-mysql-pod 1/1 Running 0 8d
demo-579d6c87d6-fbdc2 1/1 Running 0 4s
demo-579d6c87d6-hslhw 1/1 Running 0 4s
demo-579d6c87d6-p5dc5 1/1 Running 0 4s
[root@node1 work]# for i in `kubectl get pods -l app=demo|grep demo|awk '{print $1}'`; do kubectl exec -it $i ls /data ;done;
3.txt demo-579d6c87d6-gg9jf.txt
3.txt demo-579d6c87d6-gg9jf.txt
3.txt demo-579d6c87d6-gg9jf.txt
rbd中只保留了最后一份。
StoragaClass 方式
在 1.4 以后,kubernetes 提供了一种更加方便的动态创建 PV 的方式;也就是说使用 StoragaClass 时无需预先创建固定大小的 PV,等待使用者创建 PVC 来使用;而是直接创建 PVC 即可分配使用。也无需到各Node节点上执行rbd map 镜像。
- 创建系统级 Secret
注意: 由于 StorageClass 要求 Ceph 的 Secret type必须为 kubernetes.io/rbd ,所以上一步创建的 ceph-secret 需要先被删除,然后使用如下命令重新创建;此时的 key 并没有经过 base64
[root@node1 work]# kubectl delete secret ceph-secret
secret "ceph-secret" deleted
[root@node1 work]# ceph auth get-key client.admin
AQCE48dcKDUHDRAA5FwbyC54wptpbn94Dr35Tw==
# 这个 secret type 必须为 kubernetes.io/rbd,否则会造成 PVC 无法使用
kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" --from-literal=key='AQCE48dcKDUHDRAA5FwbyC54wptpbn94Dr35Tw=='
- 创建 StorageClass
cat << EOF >> ceph.storageclass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: test-storageclass
provisioner: kubernetes.io/rbd
parameters:
monitors: 192.168.6.156:6789,192.168.6.157:6789,192.168.6.158:6789
# Ceph 客户端用户 ID(非 k8s 的)
adminId: admin
adminSecretName: ceph-secret
pool: rbd
userId: admin
userSecretName: ceph-secret
EOF
[root@node1 work]# kubectl create -f ceph.storageclass.yml
storageclass "ceph-storageclass" created
[root@node1 work]# kubectl get storageclass
NAME PROVISIONER
ceph-storageclass kubernetes.io/rbd
- 创建PVC
[root@node1 work]# vim nginx-pvc2.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-pvc2
annotations:
volume.beta.kubernetes.io/storage-class: ceph-storageclass
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
[root@node1 work]# kubectl create -f nginx-pvc2.yaml
persistentvolumeclaim "nginx-pvc2" create
- 创建Deployment
[root@node1 work]# vim nginx-deploy2.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: demo2
spec:
replicas: 3
template:
metadata:
labels:
app: demo2
spec:
containers:
- name: nginx-demo2
image: mritd/demo
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/data"
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: nginx-pvc2
[root@node1 work]# kubectl create -f nginx-deploy2.yml
deployment "demo2" created
[root@node1 work]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
ceph-mysql-pod 1/1 Running 0 8d 172.30.128.6 node3
demo2-66fd75bb8d-nwxmr 1/1 Running 0 15s 172.30.128.3 node3
demo2-66fd75bb8d-wmt7g 0/1 ContainerCreating 0 15s <none> node1
demo2-66fd75bb8d-xh47j 0/1 ContainerCreating 0 15s <none> node2
可以看出只创建成功一个pod,符合预期,只有一个节点进行读写,其余节点无法创建成功。
https://github.com/kubernetes/kubernetes/issues/67474
将配置修改为 ReadOnlyMany 后仍不能多个节点挂载,可能也是bug.
ceph 常用命令
- rbd 查看锁
rbd lock list nginx-image
- rbd 查看 map情况
rbd showmapped
k8s 常用命令
- 获取pod IP
[root@node1 work]# kubectl get pods -l app=demo -o yaml|grep podIP
podIP: 172.30.128.3
podIP: 172.30.96.3
podIP: 172.30.184.2
生成service创建配置文件
kubectl get svc -l app=demo -o yaml
查看 service 描述
kubectl describe svc demo
k8s各类端口及IP说明
端口说明
targetPort:容器接收流量的端口;port:抽象的 Service 端口,可以使任何其它 Pod 访问该 Service 的端口
问题
- rbd: failed to lock image nginx-image (maybe locked by other nodes), error exit status 1
Error syncing pod
May 7 10:50:19 node2 kubelet: E0507 10:50:19.891141 27177 kubelet.go:1633] Unable to mount volumes for pod "demo-67bf76f84c-z8kmx_defaul t(3eaf6dab-7072-11e9-b0eb-000c29bda28d)": timeout expired waiting for volumes to attach/mount for pod "default"/"demo-67bf76f84c-z8kmx". li st of unattached/unmounted volumes=[data]; skipping pod May 7 10:50:19 node2 kubelet: E0507 10:50:19.891219 27177 pod_workers.go:182] Error syncing pod 3eaf6dab-7072-11e9-b0eb-000c29bda28d ("d emo-67bf76f84c-z8kmx_default(3eaf6dab-7072-11e9-b0eb-000c29bda28d)"), skipping: timeout expired waiting for volumes to attach/mount for pod "default"/"demo-67bf76f84c-z8kmx". list of unattached/unmounted volumes=[data]
解决
每节点执行:rbd map nginx-image
[root@node3 ~]# rbd showmapped
id pool image snap device
0 rbd db-image - /dev/rbd0
1 rbd nginx-image - /dev/rbd1
PV访问模式
- 访问模式包括:
- ReadWriteOnce —— 该volume只能被单个节点以读写的方式映射
- ReadOnlyMany —— 该volume可以被多个节点以只读方式映射
- ReadWriteMany —— 该volume只能被多个节点以读写的方式映射
- 状态
- Available:空闲的资源,未绑定给PVC
- Bound:绑定给了某个PVC
- Released:PVC已经删除了,但是PV还没有被集群回收
- Failed:PV在自动回收中失败了
- 当前的回收策略有:
- Retain:手动回收
- Recycle:需要擦出后才能再使用
- Delete:相关联的存储资产,如AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷都会被删除
当前,只有NFS和HostPath支持回收利用,AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷支持删除操作。
测试结果
k8s RBD只能进行单节点读写或多节点读,不能进行多节点读写。测试ceph的rbd发现,多节点读好像有bug,生产使用还是最好能具备一定开发能力。
参考
https://mritd.me/2017/06/03/use-ceph-storage-on-kubernetes/
k8s使用ceph存储的更多相关文章
- k8s对接ceph存储
前提条件:已经部署好ceph集群 本次实验由于环境有限,ceph集群是部署在k8s的master节点上的 一.创建ceph存储池 在ceph集群的mon节点上执行以下命令: ceph osd pool ...
- Ceph 14.2.5-K8S 使用Ceph存储实战 -- <6>
K8S 使用Ceph存储 PV.PVC概述 管理存储是管理计算的一个明显问题.PersistentVolume子系统为用户和管理员提供了一个API,用于抽象如何根据消费方式提供存储的详细信息.于是引入 ...
- K8S学习笔记之k8s使用ceph实现动态持久化存储
0x00 概述 本文章介绍如何使用ceph为k8s提供动态申请pv的功能.ceph提供底层存储功能,cephfs方式支持k8s的pv的3种访问模式ReadWriteOnce,ReadOnlyMany ...
- k8s使用ceph的rbd作后端存储
k8s使用rbd作后端存储 k8s里的存储方式主要有三种.分别是volume.persistent volumes和dynamic volume provisioning. volume: 就是直接挂 ...
- 自建Ceph存储与 AWS、阿里云、腾讯云的成本对比
本文单从存储成本角度对比了自建Ceph存储和业界公有云存储的硬件成本,不包括IDC带宽成本. 统计Ceph集群的用到的主要设备为: OSD.MON.RGW服务器 .TOR交换机. 机架. 下表解释: ...
- 我所了解的各公司使用的 Ceph 存储集群 (携程、乐视、有云、宝德云、联通等)
Ceph 作为软件定义存储的代表之一,最近几年其发展势头很猛,也出现了不少公司在测试和生产系统中使用 Ceph 的案例,尽管与此同时许多人对它的抱怨也一直存在.本文试着整理作者了解到的一些使用案例. ...
- ceph存储之ceph客户端
CEPH客户端: 大多数Ceph用户不会直接往Ceph存储集群里存储对象,他们通常会选择Ceph块设备.Ceph文件系统.Ceph对象存储之中的一个或多个: 块设备: 要实践本手册,你必须先完成存储集 ...
- ceph存储之查找对象
对象存储(而非块存储): 要把对象存入ceph集群,客户端必须做到: 1.指定对象名 2.指定存储池 Ceph客户端检出最新集群运行图,客户端用CRUSH算法动态地计算出如何把对象映射到归置组.然后计 ...
- Ceph 存储集群
Ceph 存储集群 Ceph 作为软件定义存储的代表之一,最近几年其发展势头很猛,也出现了不少公司在测试和生产系统中使用 Ceph 的案例,尽管与此同时许多人对它的抱怨也一直存在.本文试着整理作者了解 ...
随机推荐
- Pyhton学习——Day30
# 内核态# 用户态# 操作系统的运行是在BOIS启动盘读取代码,从硬盘读取到内存中,被操作系统的内核中,一直存在在内存中# 计算机系统的三层结构:应用软件-->操作系统-->硬件# 一般 ...
- C# 基础复习 三 XML操作
XML 可扩展标记语言(所有标签都是自己定义,没有固定格式) 如果要给XML规定格式,可以使用dtd (dtd是什么?你不会自己百度吗) XML主要用来存储数据 XML的要求: 根节点只能有一 ...
- 为什么使用GitHub
GitHub的特点: 1.开源式分布版本管理系统 2.开源项目集中的代码库 3.所有略有规模的公司都在使用 GitHub的功能介绍: 1.记录多个版本 2.查看历史操作,可以进行版本吧回退和前进的控制 ...
- NOIP2018提高组金牌训练营——字符串专题
NOIP2018提高组金牌训练营——字符串专题 1154 回文串划分 有一个字符串S,求S最少可以被划分为多少个回文串. 例如:abbaabaa,有多种划分方式. a|bb|aabaa - 3 个 ...
- 20121124.Nodejs创建HTTP程序.md
####1.源代码: var http=require('http');//读取http模块 http.createServer(function(req,res){//创建一个服务,接受一个回 ...
- JS实现缓存运动
JS ...
- Jquery-ajax错误分析
当我把cshtml中的js代码移出到js文件中,将js代码作为文件引入cshtml时,出现了下面的这样的错误 网上的不少人说是通过在\(.ajax参数中加上async:true解决的,但\).ajax ...
- URAL 1457. Heating Main
space=1&num=1457">1457. Heating Main Time limit: 1.0 second Memory limit: 64 MB Backgrou ...
- jquery outerHeight方法 outerWidth方法 获取元素实际宽度高度
曾经写代码中,每当须要获取元素的实际"宽度"(这里的宽度是指元素宽度加上其边距)时,都须要用元素宽度加上margin值才行,今天发现一个叫outerWidth(options)的方 ...
- wikioi 1306 机智Trie树
题目描写叙述 Description 看广播操无聊得非常~你有认为吗?在看广播操一波又一波的人潮涌过再退去.认为非常没意思--于是,偶们的大神犇JHT发明了一个及其好玩的游戏~ 把每一班级的队形看成一 ...