Akemi

ceph对接k8s

2024/05/01

如果出现无法载图的情况,请检查与github的连通性

网络环境说明

ceph的部署参见《ceph分布式存储》博文

192.168.10.121 ws-k8s-master1
192.168.10.122 ws-k8s-master2
192.168.10.123 ws-k8s-master3
192.168.10.130 harbor
192.168.10.131 ws-k8s-node1
192.168.10.132 ws-k8s-node2
192.168.10.133 ws-k8s-node3
192.168.10.141 ceph-node1
192.168.10.142 ceph-node2
192.168.10.143 ceph-node3

rbd作为块存储直接给k8s主机使用

云超融合节点做ceph后生成rbd,将rbd作为磁盘提供给k8s节点
这种方案相对简单,而且我没有这个硬件条件,就不演示了

k8s直接对接ceph-rbd

注:如果rbd被一个pod挂载,就无法被另外pod挂载;
如果用deployment,那么只有其中一个pod能挂载

准备工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.k8s节点要安装ceph-common
把ceph.repo复制到各个节点,然后yum安装
scp /etc/yum.repos.d/ceph.repo ws-k8s-master1:/etc/yum.repos.d/
...
yum -y install ceph-common
2.将ceph-node1的ceph配置文件复制到各节点
scp /etc/ceph/* ws-k8s-master1:/etc/ceph/
...

3.创建一个ceph的rbd池
ceph osd pool create k8s-rbd 128
ceph osd pool application enable k8s-rbd rbd
4.基于rbd池创建卷
rbd create k8s-rbd/disk1 --size 10G
rbd feature disable k8s-rbd/disk1 object-map fast-diff deep-flatten
#卷名称为disk1

进行挂载

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
#k8s-master节点
cd ~
mkdir ceph
cd ceph

写一个pod用来挂载rbd
cat > test-rbd.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: test-rbd
spec:
containers:
- image: 192.168.10.130/wangsheng/solo:1.0
imagePullPolicy: IfNotPresent
name: test-rbd
volumeMounts:
- name: rbd
mountPath: /mnt
volumes:
- name: rbd
rbd:
monitors:
- '192.168.10.141:6789'
- '192.168.10.142:6789'
- '192.168.10.143:6789'
pool: k8s-rbd
image: disk1
fsType: xfs
readOnly: false
user: admin
keyring: /etc/ceph/ceph.client.admin.keyring
EOF
kubectl apply -f test-rbd.yaml

kubectl describe pod test-rbd | grep -i volumes -A 10
Volumes:
rbd:
Type: RBD (a Rados Block Device mount on the host that shares a pod's lifetime)
CephMonitors: [192.168.10.141:6789 192.168.10.142:6789 192.168.10.143:6789]
RBDImage: disk1
FSType: xfs
RBDPool: k8s-rbd
RadosUser: admin
Keyring: /etc/ceph/ceph.client.admin.keyring
SecretRef: nil
ReadOnly: false

基于ceph-rbd手动生成pv

解决rbd卷只能被单个pod挂载的问题。

基于ceph-rbd生成pv可以让多个pod对rbd上的空间进行挂载

但是,也存在rbd无法跨节点挂载的问题,仅对于同一个node下的pod有效,如果node挂了,pod迁移到另外的node上就会无法正常挂载。

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
1.k8s节点安装ceph

2.获取ceph client.admin的keyring值,将其存储到
ceph auth get-key client.admin | base64
QVFDTEtmZGxESHN6Q1JBQWdnRXlZeHRodzJyY3htb1ZzTFVPb1E9PQ==

3.创建secret对象ceph-secret,这个secret对象用于k8s volume插件访问ceph集群
cat > ceph-secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
data:
key: QVFDTEtmZGxESHN6Q1JBQWdnRXlZeHRodzJyY3htb1ZzTFVPb1E9PQ==
EOF
kubectl apply -f ceph-secret.yaml

4.从存储池中再创建一个卷disk2
#ceph节点,创建k8s-rbd/disk2
rbd create k8s-rbd/disk2 --size 10G
rbd feature disable k8s-rbd/disk2 object-map fast-diff deep-flatten

5.创建pv,指定使用disk2
cat > ceph-pv.yaml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: ceph-pv # 持久卷的名称
spec:
capacity:
storage: 10Gi # 卷的存储容量为10GiB
accessModes:
- ReadWriteOnce # 卷的访问模式为单节点读写
rbd:
monitors:
- '192.168.10.141:6789' # RBD监视器的地址
- '192.168.10.142:6789'
- '192.168.10.143:6789'
pool: k8s-rbd # RBD池的名称
image: disk2 # RBD镜像的名称
user: admin # 用户名
secretRef:
name: ceph-secret # 密钥的名称(引用的Secret对象)
fsType: xfs # 文件系统类型为XFS
readOnly: false # 是否只读
persistentVolumeReclaimPolicy: Recycle # 持久卷的回收策略为Recycle(废弃策略)
EOF
kubectl apply -f ceph-pv.yaml
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
ceph-pv 10Gi RWO Recycle Available 3m14s

6.创建pvc
cat > ceph-pvc.yaml << EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: ceph-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
EOF
kubectl apply -f ceph-pvc.yaml
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
ceph-pvc Bound ceph-pv 10Gi RWO 6s

7.测试pod挂载pvc
cat > pod-pvc.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: ceph-pvc-test
spec:
selector:
matchLabels:
app: solo
replicas: 2
template:
metadata:
labels:
app: solo
spec:
containers:
- name: solo
image: 192.168.10.130/wangsheng/solo:1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
volumeMounts:
- mountPath: "/ceph-data"
name: ceph-data
volumes:
- name: ceph-data
persistentVolumeClaim:
claimName: ceph-pvc
EOF
kubectl apply -f pod-pvc.yaml

kubectl get pods | grep pvc
ceph-pvc-test-76c79b74d9-m9vw6 1/1 Running 0 116s
ceph-pvc-test-76c79b74d9-qkkzd 1/1 Running 0 116s

基于storageclass自动生成pv

注: 本实验无法使用k8s1.24及以上版本,因为在1.24之后,RemoveSelfLink选项被锁定为true无法修改

准备工作

1
2
3
4
5
6
使ceph节点和k8s节点的/etc/ceph具有满权限
创建/root/.ceph目录,将/etc/ceph内文件复制过去
chmod 777 -R /etc/ceph/*
ssh ws-k8s-master2 "chmod 777 -R /etc/ceph/* && mkdir /root/.ceph && cp -ar /etc/ceph/ /root/.ceph/"
ssh ceph-node1 "chmod 777 -R /etc/ceph/* && mkdir /root/.ceph && cp -ar /etc/ceph/ /root/.ceph/"
...

开始安装

创建rbd供应商provisioner

1.创建供应商

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rbd-provisioner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
- apiGroups: [""]
resources: ["services"]
resourceNames: ["kube-dns","coredns"]
verbs: ["list", "get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rbd-provisioner
subjects:
- kind: ServiceAccount
name: rbd-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: rbd-provisioner
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: rbd-provisioner
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rbd-provisioner
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: rbd-provisioner
subjects:
- kind: ServiceAccount
name: rbd-provisioner
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rbd-provisioner
spec:
selector:
matchLabels:
app: rbd-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: rbd-provisioner
spec:
containers:
- name: rbd-provisioner
image: quay.io/xianchao/external_storage/rbd-provisioner:v1
imagePullPolicy: IfNotPresent
env:
- name: PROVISIONER_NAME
value: ceph.com/rbd
serviceAccount: rbd-provisioner
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: rbd-provisioner

kubectl apply -f rbd-provisioner.yaml
#clusterrole.rbac.authorization.k8s.io/rbd-provisioner created
#clusterrolebinding.rbac.authorization.k8s.io/rbd-provisioner created
#role.rbac.authorization.k8s.io/rbd-provisioner created
#rolebinding.rbac.authorization.k8s.io/rbd-provisioner created
#deployment.apps/rbd-provisioner created
#serviceaccount/rbd-provisioner created

2.ceph直接创建一个pool池用来给k8s调用

1
2
ceph osd pool create k8s-storageclass 128
ceph osd pool application enable k8s-storageclass rbd

3.创建k8s的ceph-secret

1
2
3
4
mkdir -p ~/ceph/storageclass
cd ~/ceph/storageclass
echo -n "AQCLKfdlDHszCRAAggEyYxthw2rcxmoVsLUOoQ==" | base64
QVFDTEtmZGxESHN6Q1JBQWdnRXlZeHRodzJyY3htb1ZzTFVPb1E9PQ==

4.创建k8s的ceph-secret

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mkdir -p ~/ceph/storageclass
cd ~/ceph/storageclass
echo -n "AQCLKfdlDHszCRAAggEyYxthw2rcxmoVsLUOoQ==" | base64
QVFDTEtmZGxESHN6Q1JBQWdnRXlZeHRodzJyY3htb1ZzTFVPb1E9PQ==

cat > ceph-secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: ceph-storageclass-secret
type: "ceph.com/rbd" #供应商名称
data:
key: QVFDTEtmZGxESHN6Q1JBQWdnRXlZeHRodzJyY3htb1ZzTFVPb1E9PQ==
EOF
kubectl apply -f ceph-secret.yaml

kubectl get secret
NAME TYPE DATA AGE
ceph-storageclass-secret ceph.com/rbd 1 4m46s

5.创建storageclass

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
cat > storageclass.yaml << EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: k8s-rbd
provisioner: ceph.com/rbd #供应商名
parameters:
monitors: 192.168.10.141:6789,192.168.10.142:6789,192.168.10.143:6789 # 指定Ceph监视器的地址和端口
adminId: admin # Ceph管理员的标识符
adminSecretName: ceph-storageclass-secret # 存储Ceph管理员凭据的Kubernetes Secret的名称
pool: k8s-storageclass # Ceph存储池的名称
userId: admin # Ceph用户的标识符
userSecretName: ceph-storageclass-secret # 存储Ceph用户凭据的Kubernetes Secret的名称
fsType: xfs # 指定要在存储中使用的文件系统类型
imageFormat: "2" # 指定Ceph RBD映像的格式
imageFeatures: "layering" # 指定Ceph RBD映像的特性
EOF

kubectl apply -f storageclass.yaml
storageclass.storage.k8s.io/k8s-rbd created

kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
k8s-rbd ceph.com/rbd Delete Immediate false

6.用storageclass创建pvc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat > storageclass-pvc.yaml << EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi
storageClassName: k8s-rbd
EOF
kubectl apply -f storageclass-pvc.yaml
如果pvc从storageclass存储类中找到供应商,从供应商对应的pool中取得空间做成pv
那么说明供应商是没有问题的

k8s挂载cephfs

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
1.找到ceph的admin用户的key
cat /etc/ceph/ceph.client.admin.keyring
AQCLKfdlDHszCRAAggEyYxthw2rcxmoVsLUOoQ==

echo -n 'AQCLKfdlDHszCRAAggEyYxthw2rcxmoVsLUOoQ==' >> /etc/ceph/admin.secret

2.通过这个key将ceph节点挂载到本机/data/ceph
mkdir -p /data/ceph
mount -t ceph 192.168.10.141:6789:/ /data/ceph -o name=admin,secretfile=/etc/ceph/admin.secret

查看文件系统状态
df -Th | grep ceph
192.168.10.141:6789:/ ceph 282G 0 282G 0% /data/ceph

3.创建secret
echo -n 'AQCLKfdlDHszCRAAggEyYxthw2rcxmoVsLUOoQ==' | base64
**QVFDTEtmZGxESHN6Q1JBQWdnRXlZeHRodzJyY3htb1ZzTFVPb1E9PQ**==

创建cephfs-secret.yaml文件
cat > cephfs-secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: cephfs-secret
data:
key: **QVFDTEtmZGxESHN6Q1JBQWdnRXlZeHRodzJyY3htb1ZzTFVPb1E9PQ**==
EOF
kubectl apply -f cephfs-secret.yaml
# secret/cephfs-secret created

4.创建pv和pvc,挂载到挂载进来的目录
cd /data/ceph/
mkdir -p wangsheng && chmod 0777 wangsheng

cat > pv-pvc.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: cephfs-pvc
spec:
accessModes:
- ReadWriteMany
volumeName: cephfs-pv
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: cephfs-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
cephfs:
monitors:
- 192.168.10.141:6789
- 192.168.10.142:6789
- 192.168.10.143:6789
path: /wangsheng
user: admin
readOnly: false
secretRef:
name: cephfs-secret
persistentVolumeReclaimPolicy: Recycle
EOF
kubectl apply -f pv-pvc.yaml

kubectl get pv | grep ceph
cephfs-pv 10Gi RWX Recycle Bound default/cephfs-pvc 117s

5.测试
创建两个pod
cat > pod-test.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: cephfs-pod-1
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: test-v1
mountPath: /mnt
volumes:
- name: test-v1
persistentVolumeClaim:
claimName: cephfs-pvc
---
apiVersion: v1
kind: Pod
metadata:
name: cephfs-pod-2
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: test-v1
mountPath: /mnt
volumes:
- name: test-v1
persistentVolumeClaim:
claimName: cephfs-pvc
EOF
kubectl apply -f pod-test.yaml
kubectl get pods
#NAME READY STATUS RESTARTS AGE
#cephfs-pod-1 1/1 Running 0 7s
#cephfs-pod-2 1/1 Running 0 7s

在两个pod都创建文件
kubectl exec -it cephfs-pod-1 -- /bin/sh
cd /mnt
touch 1

kubectl exec -it cephfs-pod-2 -- /bin/sh
cd /mnt
touch 2

查看,两个pod已经共享了一个pvc
ls /data/ceph/wangsheng/
1 2

CATALOG
  1. 1. 网络环境说明
  2. 2. rbd作为块存储直接给k8s主机使用
  3. 3. k8s直接对接ceph-rbd
    1. 3.1. 准备工作
    2. 3.2. 进行挂载
  4. 4. 基于ceph-rbd手动生成pv
  5. 5. 基于storageclass自动生成pv
    1. 5.1. 准备工作
    2. 5.2. 开始安装
      1. 5.2.1. 1.创建供应商
      2. 5.2.2. 2.ceph直接创建一个pool池用来给k8s调用
      3. 5.2.3. 3.创建k8s的ceph-secret
      4. 5.2.4. 4.创建k8s的ceph-secret
      5. 5.2.5. 5.创建storageclass
      6. 5.2.6. 6.用storageclass创建pvc
  6. 6. k8s挂载cephfs