[TOC]
### **准备Ceph集群和Kubernetes集群**
首先,我们需要准备一个Ceph集群,安装好CephFS。参考教程 https://www.kancloud.cn/pshizhsysu/ceph/1978070#3CephFS_57
准备好一个K8S集群(本实验中k8s集群的版本为v1.17.3,一个节点,内核为4.19.12);另外,在K8S集群的每个节点上执行以下命令安装ceph
```
$ sudo yum -y install ceph
```
### **创建secret以保存keyring**
由于访问ceph集群需要身份验证(在kubernetes中我们打算直接使用ceph的admin用户),所以我们先把admin用户的keyring保存在kubernetes的secret中。
我们不能把keyring的内容直接保存在secret中,而要先经过base64编码。假设`ceph.client.admin.keyring`文件(在ceph集群Monitor节点的`/etc/ceph/`目录下)的内容如下:
```
[client.admin]
key = AQBRCtFci+UPKxAAvifYirfhtgEMGP46mkre+A==
```
我们对key进行base64编码,得到
```
$ echo -n "AQBRCtFci+UPKxAAvifYirfhtgEMGP46mkre+A==" | base64
QVFCUkN0RmNpK1VQS3hBQXZpZllpcmZodGdFTUdQNDZta3JlK0E9PQ==
```
接下来,我们在kubernetes集群中来创建这个secret,我们把它创建在命名空间kube-system中,名字叫`ceph-admin-secret`,注意下面的type字段的值不用设置,默认为`Opaque`(与CephRBD不同)
```
apiVersion: v1
kind: Secret
metadata:
name: ceph-adamin-secret
namespace: kube-system
data:
key: QVFCUkN0RmNpK1VQS3hBQXZpZllpcmZodGdFTUdQNDZta3JlK0E9PQ=
```
### **创建StorageClass**
然后在kubernetes集群中创建StorageClass,这里我们把provisioner设置为 `ccse.io/cephfs` (可以任意值,但注意不能为`kubernetes.io/`开头)
```
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: cephfs
provisioner: ccse.io/cephfs
reclaimPolicy: Retain
volumeBindingMode: Immediate
```
### **创建PV**
创建如下的PV
* `spec.cephfs.path`:cephfs文件系统中目录,如果不设置该字段则默认为根目录`/`,这里我们设置为`/dir1`(注意要提前在cephfs文件系统中创建好该目录)
```
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-cephfs
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 1Gi
storageClassName: cephfs
persistentVolumeReclaimPolicy: Retain
cephfs:
monitors:
- 192.168.2.107:6789
path: /dir1
secretRef:
name: ceph-admin-secret
namespace: kube-system
user: admin
```
查看PV的状态,如下:
```
$ kubectl get pv pv-cephfs
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-cephfs 1Gi RWX Retain Available cephfs 9s
```
### **创建PVC**
创建如下的PVC
```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-cephfs
spec:
accessModes:
- ReadWriteMany
storageClassName: cephfs
resources:
requests:
storage: 1Gi
```
创建好PVC后,查看PVC与PV的状态,已绑定
```
$ kubectl get pvc pvc-cephfs
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-cephfs Bound pv-cephfs 1Gi RWX cephfs 8s
$ kubectl get pv pv-cephfs
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-cephfs 1Gi RWX Retain Bound default/pvc-cephfs cephfs 72s
```
### **创建Pod**
创建如下的Pod,使用PVC
```
apiVersion: v1
kind: Pod
metadata:
name: tomcat
spec:
containers:
- name: tomcat
image: tomcat:8.0
volumeMounts:
- mountPath: /test
name: pvc1
volumes:
- name: pvc1
persistentVolumeClaim:
claimName: pvc-cephfs
```
创建成功后,查看Pod的状态
```
$ kubectl get pod tomcat -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tomcat 1/1 Running 0 23s 172.26.71.207 peng01 <none> <none>
```
等到Running后, 在Pod所在的节点上命令查看cephfs的挂载情况:
```
$ df -hT --type ceph
Filesystem Type Size Used Avail Use% Mounted on
192.168.2.107:6789:/dir1 ceph 18G 0 18G 0% /var/lib/kubelet/pods/731473e6-2f72-4e57-a6cf-8390ac8ca1f0/volumes/kubernetes.io~cephfs/pv-cephfs
```
上面的`731473e6-2f72-4e57-a6cf-8390ac8ca1f0`就是Pod tomcat的uid
```
$ kubectl get pod tomcat -o yaml | grep uid
uid: 731473e6-2f72-4e57-a6cf-8390ac8ca1f0
```
### **两个Pod使用同一PVC**
上面我们发现,cephfs的目录是挂载到`/var/lib/kubelet/pods/<podid>/...`下面,接下来我们来看一下,如果两个Pod使用同一个PVC,且调度到相同的节点上,那么ceph的挂载会是什么样的呢?
我们再新建一个Pod,yaml文件和上面的tomcat的yaml一样,除了把名字改成tomcat1,让它们调度到同一个节点上(这里的实验集群只有一个节点),如下:
```
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tomcat 1/1 Running 0 14m 172.26.71.207 peng01 <none> <none>
tomcat1 1/1 Running 0 29s 172.26.71.208 peng01 <none> <none>
```
然后,查看该节点上的cephfs的挂载
```
$ df -hT --type ceph
Filesystem Type Size Used Avail Use% Mounted on
192.168.2.107:6789:/dir1 ceph 18G 0 18G 0% /var/lib/kubelet/pods/731473e6-2f72-4e57-a6cf-8390ac8ca1f0/volumes/kubernetes.io~cephfs/pv-cephfs
```
我们发现,主机的cephfs挂载并没有发生改变。
接下来,由于cephfs是挂载到tomcat这个Pod的目录下,我们把tomcat这个Pod先删掉,
```
$ kubectl delete pod tomcat
pod "tomcat" deleted
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tomcat1 1/1 Running 0 6m57s 172.26.71.208 peng01 <none> <none>
```
然后再查看主机的挂载情况:
```
$ df -hT --type ceph
Filesystem Type Size Used Avail Use% Mounted on
192.168.2.107:6789:/dir1 ceph 18G 0 18G 0% /var/lib/kubelet/pods/79ec3cee-70fe-4aa4-8c16-8685568550a1/volumes/kubernetes.io~cephfs/pv-cephfs
```
此时发现,cephfs的挂载目录变了,变成了tomcat1这个Pod的路径下。
### **删除Pod**
再删除tomcat1,等删除成功后, 再看刚才Pod节点上cephfs的挂载,发现已经没有了。
```
$ df -hT --type ceph
df: no file systems processed
```
### **Q&A**
Q:根据上面的实验,k8s应该是使用了ceph的内核态挂载,按理说不需要在k8s节点上安装ceph才对?
A:待验证
### **Reference**
https://github.com/kubernetes/examples/tree/master/volumes/cephfs
- 常用命令
- 安装
- 安装Kubeadm
- 安装单Master集群
- 安装高可用集群(手动分发证书)
- 安装高可用集群(自动分发证书)
- 启动参数解析
- certificate-key
- ETCD相关参数
- Kubernetes端口汇总
- 安装IPv4-IPv6双栈集群
- 下载二进制文件
- 使用Kata容器
- 快速安装shell脚本
- 存储
- 实践
- Ceph-RBD实践
- CephFS实践
- 对象存储
- 阿里云CSI
- CSI
- 安全
- 认证与授权
- 认证
- 认证-实践
- 授权
- ServiceAccount
- NodeAuthorizor
- TLS bootstrapping
- Kubelet的认证
- 准入控制
- 准入控制示例
- Pod安全上下文
- Selinux-Seccomp-Capabilities
- 给容器配置安全上下文
- PodSecurityPolicy
- K8S-1.8手动开启认证与授权
- Helm
- Helm命令
- Chart
- 快速入门
- 内置对象
- 模板函数与管道
- 模板函数列表
- 流程控制
- Chart依赖
- Repository
- 开源的Chart包
- CRD
- CRD入门
- 工作负载
- Pod
- Pod的重启策略
- Container
- 探针
- 工作负载的状态
- 有状态服务
- 网络插件
- Multus
- Calico+Flannel
- 容器网络限速
- 自研网络插件
- 设计文档
- Cilium
- 安装Cilium
- Calico
- Calico-FAQ
- IPAM
- Whereabouts
- 控制平面与Pod网络分开
- 重新编译
- 编译kubeadm
- 编译kubeadm-1.23
- 资源预留
- 资源预留简介
- imagefs与nodefs
- 资源预留 vs 驱逐 vs OOM
- 负载均衡
- 灰度与蓝绿
- Ingress的TLS
- 多个NginxIngressController实例
- Service的会话亲和
- CNI实践
- CNI规范
- 使用cnitool模拟调用
- CNI快速入门
- 性能测试
- 性能测试简介
- 制作kubemark镜像
- 使用clusterloader2进行性能测试
- 编译clusterloader2二进制文件
- 搭建性能测试环境
- 运行density测试
- 运行load测试
- 参数调优
- Measurement
- TestMetrics
- EtcdMetrics
- SLOMeasurement
- PrometheusMeasurement
- APIResponsivenessPrometheus
- PodStartupLatency
- FAQ
- 调度
- 亲和性与反亲和性
- GPU
- HPA
- 命名规范
- 可信云认证
- 磁盘限速
- Virtual-kubelet
- VK思路整理
- Kubebuilder
- FAQ
- 阿里云日志服务SLS