K8s企业实践使用storageclass实现动态存储


一、原理简介

因为要搭建,很多人还不太懂原理,我这里只是简单说明

使用StatefulSet的前提:

Kubernetes集群的版本 >=1.5 安装好DNS集群插件,版本 >=15 )

StatefulSet

注意: 官方提示StatefulSets在1.9中是稳定的

StatefulSet由ServicevolumeClaimTemplates组成。Service中的多个Pod将会被分别编号,并挂载volumeClaimTemplates中声明的PV。

1.每个节点都有固定的身份ID,通过这个ID,集群中的成员可以互相发现并且通信 2.集群的规模是比较固定的,集群规模不能随意变动。 3.集群里的每个节点都是有状态的,通常会持久化数据到永久存储中 4.如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。

官方文档对Statefulet解释

StorageClass

通过StorageClass的定义,管理员可以将存储资源定义为某种类别(Class),正如存储设备对于自身的配置描述(Profile),例如 "快速存储" "慢速存储" "有数据冗余" "无数据冗余"等。用户根据StorageClass的描述就能够直观得知各种存储资源的特性,就可以根据应用对存储资源的需求去申请存储资源了。

Deployment

Deployment相对于RC的一个最大升级是我们可以随时知道当前Pod"部署"的进度,实际上由于一个Pod的创建、调度、绑定节点及在Node上启动对应的容器这一完整过程需要一定的时间,所以我们期待系统启动N个Pod副本的目标状态,实际上是一个连续变化的"部署过程"导致的最终状态


二、服务搭建

IP 服务 备注
192.168.60.24 K8S环境-master 在master节点需要安装ceph-common,否则会出现image错误
192.168.60.25 K8S环境-node节点 master和slave节点需要安装ceph命令,用于调用
192.168.60.28 ceph-master
192.168.60.29 ceph1
192.168.60.31 Ceph2
Centos7.4系统,其他不变 Ceph 安装文章 Ceph 工作原理详解

创建StorageClass之后有两种方式引用,第一种:StatefulSet 第二种使用:Deployment

StatefulSet相比Deployment有以下特点 1.稳定的,唯一的网络表示,可以用来发现集群内部的其他成员。比如StatefulSet的名字叫abc,那么第一个起来的叫abc-1第二个abc-2依此类推 2.稳定的持久化存储:通过K8S的PV/PVC或者外部存储(预先提供的)来实现启动或关闭保证有序:优雅的部署和伸缩:操作第n个pod时,前n-1Pod已经是运行并且是准备好的状态。

RDB类型的pv只能被一个Pod可以读写,一个rbd image挂载到Pod后,image会加锁。如果使用支持多个Pod同时读写挂载的PV类型,就需要用到StorageClass,每个Pod各自挂载一个PV

注! 比如mysql、redis我们可以使用StatefulSet,nginx,tomcat可以使用deployment

一、使用StatefulSet创建StorageClass、pv和pvc

使用ceph存储前需要先创建pool池和密钥,便于服务调用

==(1).创建pool池,本例环境均在namespace abc_pool==

通常在创建pool,需要覆盖默认的pg_num,官方推荐

  • 若小于5个OSD,设置pg_num为128
  • 5~10个OSD,设置pg_num为512
  • 10~50个OSD,设置pg_num为4096
  • 超过50个OSD,可以参考pgcalc计算
  • 更多pool配置参考

温馨提示:K8s中master节点及node节点都需要安装ceph命令!!!! Ceph install 仅仅需要安装ceph并不需要其他的认证了

#创建pool池

ceph osd pool create abc_pool 512


#####################命令格式##################
#创建Pool
ceph osd pool create [pool池名称] 512
#删除pool
ceph osd pool delete [pool池名称]
#调整副本数量
ceph osd pool set [pool池名称] size 2

查看pool 池

ceph osd lspools
rados lspools

查看pool池密钥,记录下pool池的密钥,创建用户密钥信息的时候会使用到

查看并创建test用户
ceph auth get-or-create client.test mon 'allow r' osd 'allow rwx pool=abc_pool'

记录admin用户key
ceph auth get-key client.admin


##如果需要修改test用户权限,可执行下命令
ceph auth caps client.test mon 'allow r' osd 'allow rwx pool=rbd'

ceph用户管理,官方文档 我们还需要查看admin用户的key,并进行记录. admin用户默认就存在 -w810

查看用户权限及密钥

查看用户秘钥
ceph auth get-key client.admin

查询用户权限
ceph auth get client.admin

-w806

ceph auth list
查看全部用户

-w810

==(2). 创建用户的空间创建用户的密钥信息== 创建用户的空间创建用户的密钥信息

创建 命名空间,也可以使用default
kubectl create namespace abcdocker
    ##不同的命名空间不可以互通

创建k8s admin用户
kubectl create secret generic ceph-secret-admin --from-literal=key='AQAhjnZb8iCgOBAAhp/nQrkivY+d660jk6FL6A==' --type=kubernetes.io/rbd -n kube-system
###这里的key是我们上面查看admin用户的key

创建k8s use用户
kubectl create secret generic ceph-secret-user --from-literal=key='AQAhjnZb8iCgOBAAhp/nQrkivY+d660jk6FL6A==' --type=kubernetes.io/rbd -n abcdocker
## 这里的key是上面创建用户的key

查询admin & user secret
Admin
kubectl get secret ceph-secret-admin -o yaml --namespace=kube-system

User
kubectl get secrets --namespace=abcdocker ceph-secret-user

创建k8s用户参数解释:kubectl create secret generic [USERSecretName] --from-literal=key='[pool池密钥]' --type=kubernetes.io/rbd -n [命名空间]

==(3).创建StorageClass== 需要修改的地方

请不要执行,这里是参数说明@@@@@#######

cat >./storageclass.yaml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: [StorageClass名称]
provisioner: kubernetes.io/rbd
parameters:
    monitors: mon节点:6789,172.16.20.3:6789,#多节点mon请使用逗号分隔
    adminId: admin   ##admin用户是我们刚刚k8s上创建的用户
    adminSecretName: ceph-secret-admin    #secret用户
    adminSecretNamespace: "kube-system"     #命secret名空间
    pool: [pool池名称]
    userId: [USER-ID]   ##ceph上创建的用户
    userSecretName: [USERSecretName]  ##普通用户的secret
EOF

创建StorageClass

cat > storageclass.yaml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: abc-storageclass
provisioner: kubernetes.io/rbd
parameters:
    monitors: 192.168.60.28:6789
    adminId: admin
    adminSecretName: ceph-secret-admin
    adminSecretNamespace: "kube-system"
    pool: abc_pool
    userId: test
    userSecretName: ceph-secret-user
EOF

kubectl create -f storageclass.yaml --namespace=abcdocker
#需要我们指定命名空间,也可以写在配置文件中,不同的命名空不可以互相通信

检查是否创建成功 -w810

==(4)StatefulSet服务调用storageclass,自动创建pv和pvc==

下面的创建StatefulSet使用企业真实案例进行创建 (这只是个例子,下面我们进行创建,启动redis 3个pod实例)

cat >./statefulset-template.yaml <<EOF
apiVersion: apps/v1beta1           #指定api版本,此值必须在kubectl apiversion种
kind: StatefulSet       #指定创建资源的角色/类型
metadata:    #资源的元数据/属性
  name: statefulset-template        #资源(Pod)的名称
  namespace: qiqi-china-zxbk-prod    #命名空间
  labels:           #设置资源标签
    k8s-app: statefulset-template
spec:
  serviceName: statefulset-template  #service名称
  replicas: 3
  template:
    metadata:
      labels:
        name: statefulset-template   
    spec:
      containers:       #容器配置
        - name: statefulset-template    #容器名称
          image: harbor.zxbike.cn/public/redis:3.2.11   #容器镜像
          imagePullPolicy: IfNotPresent   #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registry)images的策略
                                          # Always,每次都检查
                                          # Never,每次都不检查 (不管本地是否有)
                                          # IfNotPresent,如果本地有就不检查,如果没有就拉取                                      
          command:
            - redis-server    #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockerfile中的ENTRYOINT
          args:
            - /config/master.conf #启动容器的命令参数,对应Dockerfile中CND参数
          volumeMounts:       #volume挂载参数
            - name: data      #volume名称
              mountPath: /data #volume容器内部挂载路径
          subPath: nodejs-mallh5 #一个pod中,将同一个卷共享,使其有多个用处。volumeMounts.subPath特性可以用来指定卷中的一个子目录,而不是直接使用卷的根目录。
  volumeClaimTemplates:
    - metadata:
        name: data   #statefulSet名称
        annotations:
          volume.beta.kubernetes.io/storage-class: "[StorageClass名称]"  #这里定义StorageClass名称
          gcp-auto-backup: "yes"
      spec:
        accessModes: [ "ReadWriteOnce" ]  #访问模式
        resources:
          requests:
            storage: 2Gi          #2G的动态共享资源供应模式
EOF
################################################################

StatefulSet服务调用storageclass,自动创建pv和pvc redis例子 因为StatefulSet会自动帮我们创建pv和pvc

cat >./statefulset-template.yaml <<EOF
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: statefulset-template
  namespace: abcdocker
  labels:
    k8s-app: statefulset-template
spec:
  serviceName: statefulset-template
  replicas: 3
  template:
    metadata:
      labels:
        name: statefulset-template
    spec:
      containers:
        - name: statefulset-template
          image: daocloud.io/library/redis:3.2.9
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: data
              mountPath: /data
              subPath: nodejs-mallh5
  volumeClaimTemplates:
    - metadata:
        name: data
        annotations:
          volume.beta.kubernetes.io/storage-class: "abc-storageclass"
          gcp-auto-backup: "yes"
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 2Gi  
EOF

kubectl create -f statefulet-template.yaml

storageclass会自动帮我们创建pv和pvc

==(5) 验证检查redis实例==

  • 首先我们需要检查PVC和PV是否被创建
  • 当检查PVC和PV都属于绑定状态我们在查看Pod是否正常

这里我们可以pvc已经属于绑定状态,绑定到我们创建的sc上 -w1250 如果创建了pvc并没有创建pv或者是pvc报错,可以通过kubectl describe pvc进行查看

查看Pod启动是否正常 -w1172 如果无法正常运行可以使用kubectl describe查看详细信息,或者使用journalctl -fu kube-controller-manager.servicec查看报错

查看secret用户

[root@master ceph]# kubectl get --namespace=abcdocker secrets
NAME                  TYPE                                  DATA      AGE
ceph-secret-user      kubernetes.io/rbd                     1         56m
default-token-krlgb   kubernetes.io/service-account-token   3         56m

进入容器,查看/data/目录的数据是否是大小为2G -w1110

进入容器在data目录下写入文件 -w1002

我们可以看到数据还在 -w1215

如果使用我们本地emptyDir卷当删除pod时,同时数据也会被删除

rdb类型的pv只能被一个pod可以挂载,一个rbd image挂在到pod后,image会加锁。 也就是pv只能这一个访问,如果想多个pod访问就使用StatefulSet。Deployment 只可以一个pod访问一个image


二、StorageClass 手动指定pvc

刚刚我们演示了使用storageclass直接创建Pod,期间不需要创建pv和pvc,接下来我们演示手动指定pvc

缺点:手动指定pvc可以自己定义

创建nginx例子

上面我们已经介绍了如何获取ceph用户的key这里就直接执行了 创建pool池

ceph osd pool create nginx_pool 128

创建ceph用户,用于sc连接

ceph auth get-or-create client.nginx mon 'allow r' osd 'allow rwx pool=nginx_pool'

#用户名称nginx 
pool是nginx_pool

创建命名空间

kubectl create namespace nginx

在K8s中创建ceph用户的密钥信息(下面pvc和pv会用到)

如果你上面已经创建过sc模式了,已经在k8s中生成了admin的key,那么你这里不需要在创建admin用户的key了

#########################################
#查看ceph admin的用户密钥
cat /etc/ceph/ceph.client.admin.keyring |grep key |awk '{print $3}'
#将密钥输入到以下地方,创建ceph在k8s上的密钥
kubectl create secret generic ceph-secret-admin --from-literal=key='AQBfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=' --namespace=kube-system --type=kubernetes.io/rbd

如果使用文件创建就需要使用base64加密
######################################



& 我们这里直接创建普通用户的key



查看ceph 普通用户(nginx)密钥
ceph auth get-key client.nginx

kubectl create secret generic ceph-secret-user-nginx --from-literal=key='AQBQyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy==' --namespace=nginx --type=kubernetes.io/rbd
##指定我们创建好的命名空间


###### 如果不使用文件创建的,不需要使用base64加密

查看名称为ceph-secret-user-nginx普通用户 -w1095

创建storageClass (创建动态卷组)

### sc文件解释 ###
cat >rbd-storage-class.yaml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: nginx-deployment-sc     ## sc名称
   namespace: nginx               ##命名空间
provisioner: kubernetes.io/rbd     #该字段指定使用存储卷类型为kubernetes.io/rbd,注意kubernetes.io开头为K8s内部支持的存储提供者,不同的存储卷提供类型这里要修改对应的值
parameters:
    monitors: 172.16.30.5:6789        #mon节点地址,多节点以逗号分隔
    adminId: admin            #ceph角色admin,默认admin用户已经创建。userID如果没有也可以使用admin
    adminSecretName: ceph-secret-admin    #k8s中创建ceph的用户,为上边创建的Ceph管理员admin使用的。secret种必须要有"kubernetes.io/rbd"这个type
    adminSecretNamespace: "kube-system"        #管理员secret使用的命名空间,默认是default
    pool: nginx_pool                #pool池地址
    userId: nginx                #secret用户,连接sc
    userSecretName: ceph-secret-user-nginx     #K8s中创建的ceph用户,连接ceph    
EOF

创建storageClass

需要注意的是执行的时候pvc和sc要在一个命名空间哦

cat >rbd-storage-class.yaml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: nginx-deployment-sc
provisioner: kubernetes.io/rbd
parameters:
    monitors: 192.168.60.28:6789
    adminId: admin
    adminSecretName: ceph-secret-admin
    adminSecretNamespace: "kube-system"
    pool: nginx_pool
    userId: nginx
    userSecretName: ceph-secret-user-nginx
EOF

kubectl create -f rbd-storage-class.yaml --namespace=nginx

我们没有创建的管理员用户 -w1198

查看创建好的storageClass

[root@master deployment]# kubectl get storageclasses.storage.k8s.io --namespace=nginx 
NAME                  PROVISIONER         AGE
abc-storageclass      kubernetes.io/rbd   1d
nginx-deployment-sc   kubernetes.io/rbd   16s

-w1043

创建pvc

pvc文件解释
cat >nginx-pvc.yaml <<EOF
{
  "kind": "PersistentVolumeClaim",
  "apiVersion": "v1",
  "metadata": {
    "name": "nginx-deployment-pvc"     ##pvc名称
  },
  "spec": {
    "accessModes": [            #访问模式,此处不多说了
      "ReadWriteOnce"
    ],
    "resources": {
      "requests": {
        "storage": "3Gi"        #设置数据大小
      }
    },
    "storageClassName": "nginx-deployment-sc"     #sc名称
  }
}
EOF

查看创建好的pvc

[root@master deployment]# kubectl get pvc --namespace=nginx 
NAME                  STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS          AGE
nginx-deployment-sc   Pending                                       nginx-deployment-sc   12m

查看pvc,现在pvc创建好是属于等待的一个状态,这里需要等待几分钟,一会就会变成绑定状态

正常效果如下

我们手动创建pvc,一个pod只可以绑定一个pvc,否则会报错。如果想多个pod连接可以不创建pvc

-w1145 如果长时间没有创建出来,那么我们就要看一下日志

解决办法:删除pvc,这个是由于master和node节点没有安装ceph造成的,在master和node安装ceph命令

创建nginx pod

cat > nginx_pod.yaml < EOF
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment-sc
  namespace: abcdocker
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx-sc
    spec:
      containers:
      - name: nginx-sc
        image: daocloud.io/library/nginx:1.13.0-alpin
        ports:
        - containerPort: 80
        volumeMounts:
          - mountPath: "/data"
            name: nginx-volume
      volumes:
        - name: nginx-volume
          persistentVolumeClaim:
            claimName: nginx-deployment-pvc
EOF

## claimName  pvc名称

Deployment或者set删除的时候需要注意

  • 删除rc
  • 删除pvc 和pvc

参考: https://www.cnblogs.com/iiiiher/p/7159810.html

https://blog.csdn.net/qqhappy8/article/details/78959588

https://blog.csdn.net/liukuan73/article/details/79228180

Copyright © i4t.com 2019 all right reserved,powered by Gitbook该文件修订时间: 2019-11-21 17:10:56

results matching ""

    No results matching ""