k8s 动态 PV 集成 ceph 块设备存储

动态 PV 使用步骤

  1. 创建存储池并启用 RBD 功能。
  2. 创建 Ceph 用户,提供给 k8s 使用。
  3. 在 k8s 上安装 ceph-common 客户端。
  4. 复制 ceph.conf 以及 admin 用户的 keyring 文件到 k8s 节点(master and node)。
  5. 创建 Secret 资源,以 keyring 的 key 为 data。
  6. 动态 PV 使用
    1. 创建 StorageClass
    2. 创建 PVC
    3. 创建 POD

安装 ceph 客户端

在部署 kubernetes 之前我们就已经有了 Ceph 集群,因此我们可以直接拿来用。但是 kubernetes 的所有节点(尤其是 master 节点)上依然需要安装 ceph 客户端。

apt-get install -y ceph-common

还需要将 ceph 的配置文件 ceph.conf 放在所有节点的 /etc/ceph 目录下。

配置 Secret 资源

生成 Ceph secret

# ceph auth get-key client.admin |base64
QVFBS1RobGZEVysySXhBQXBVekozNGZ0RG1OTVVhRGlWL1NCMEE9PQ==

创建 ceph-secret.yaml 文件内容为:

apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret
data:
  key: QVFBS1RobGZEVysySXhBQXBVekozNGZ0RG1OTVVhRGlWL1NCMEE9PQo=

创建 pool

Ceph 创建 pool

创建 StorageClass

创建 storage-class.yaml 文件内容为:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: kchadata
  annotations:
    storageclass.beta.kubernetes.io/is-default-class: "true"
provisioner: ceph.com/rbd
parameters:
  monitors: 172.18.32.119:6789,172.18.83.170:6789
  adminId: admin
  adminSecretName: ceph-secret
  adminSecretNamespace: default
  pool: kcha
  userId: admin
  userSecretName: ceph-secret
  userSecretNamespace: default
  fsType: ext4
  imageFormat: "2"
  imageFeatures: "layering"
reclaimPolicy: Retain

创建 PVC

创建 pvc-zkdata.yaml 文件内容为:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: zkdata-zk-0
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: zkdata-zk-1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: zkdata-zk-2
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

查看 PVC 和 PV,可以看到 PVC 是 Bound 状态,而且 PV 已经自动创建:

$ kg pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
zkdata-zk-0   Bound    pvc-b5acf208-86a1-4eb9-b5f2-5f99a9621ffa   10Gi       RWO            kchadata       9m5s
zkdata-zk-1   Bound    pvc-9cc38190-7cd1-43b9-948e-7addd205bbeb   10Gi       RWO            kchadata       9m5s
zkdata-zk-2   Bound    pvc-33494a8b-a119-45a0-9741-f09aa31008b3   10Gi       RWO            kchadata       9m5s

$ kg pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE
pvc-33494a8b-a119-45a0-9741-f09aa31008b3   10Gi       RWO            Retain           Bound    manti-infra/zkdata-zk-2   kchadata                9m34s
pvc-9cc38190-7cd1-43b9-948e-7addd205bbeb   10Gi       RWO            Retain           Bound    manti-infra/zkdata-zk-1   kchadata                9m34s
pvc-b5acf208-86a1-4eb9-b5f2-5f99a9621ffa   10Gi       RWO            Retain           Bound    manti-infra/zkdata-zk-0   kchadata                9m34s

创建 POD

省略

问题解决

Failed to provision volume

$ k describe pvc zkdata-zk-0
Failed to provision volume with StorageClass "kchadata": failed to create rbd image: executable file not found in $PATH, command output:

需要安装 ceph-common 工具插件来操作 Ceph,上边报错应该就是找不到该插件导致的。

方案一:添加 ceph-common 到 hyperkube image 中,构建一个新的安装了 ceph-common 的同名镜像 hyperkube-amd64 替换官方镜像

$ vim Dockerfile
FROM gcr.io/google_containers/hyperkube-amd64:v1.2.1
 
RUN curl https://raw.githubusercontent.com/ceph/ceph/master/keys/release.asc | apt-key add - && \
    echo deb http://download.ceph.com/debian-hammer/ jessie main | tee /etc/apt/sources.list.d/ceph.list && \
    apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -q -y ceph-common && \
    apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
 
$ docker build -t custom/hyperkube-amd64:v1.2.1 .    

方案二:使用 扩展存储卷插件 来帮我们完成这一步。

$ git clone https://github.com/kubernetes-incubator/external-storage.git
$ tree external-storage/ceph/rbd/deploy/
├── README.md
├── non-rbac
│   └── deployment.yaml
└── rbac
    ├── clusterrole.yaml
    ├── clusterrolebinding.yaml
    ├── deployment.yaml
    └── serviceaccount.yaml

这里提供 rbac 和 no-rbac 两种方式,如果搭建 k8s 集群时开启了 rbac 认证的,需要采用 rbac 方式来创建该 deployment。

NAMESPACE=default # change this if you want to deploy it in another namespace
sed -r -i "s/namespace: [^ ]+/namespace: $NAMESPACE/g" ./rbac/clusterrolebinding.yaml ./rbac/rolebinding.yaml
kubectl -n $NAMESPACE apply -f ./rbac

然后修改 storage-class.yaml 文件,将 provisioner: kubernetes.io/rbd 修改为 provisioner: ceph.com/rbd,意思就是不使用 k8s 内部提供的 rbd 存储类型,而是使用我们刚创建的扩展 rbd 存储。

参考:https://github.com/kubernetes/kubernetes/issues/38923

master 节点不能部署

0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match pod affinity/anti-affinity, 2 node(s) didn't satisfy existing pods anti-affinity rules.

解决:

kubectl taint nodes --all node-role.kubernetes.io/master-

重新加入污点:

kubectl taint nodes master-hostname node-role.kubernetes.io/master=true:NoSchedule