在上一篇博文,我们通过kubernetes的devlopment和service完成了sonarqube的部署。看起来已经可用,但是仍然有一个很大的问题。我们知道,像mysql这种数据库是需要保存数据而且不能让数据丢失的。而容器恰恰是一旦退出,所有数据都会丢失。我们的mysql-sonar容器一旦重启,那么我们后续对sonarqube做的任何设置都会丢失。所以我们必须找到一种方法能让mysql-sonar容器中的mysql数据保存下来。kubernetes提供多种持久化数据的方案,包括使用hostPath,nfs,flocker,glusterfs,rbd等等。我们就使用ceph提供的rbd块存储来实现kubernetes的持久化存储。

要使用ceph作为存储,首先得安装ceph,我这里简单罗列下通过ceph-deploy安装ceph的过程,先说下运行环境:

server-: admin-node   mon-node  client-node
server-: osd-node  mon-node
server-: osd-node  mon-node

在所有机器上配置yum源:

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo vim /etc/yum.repos.d/ceph.repo
[ceph]
name=ceph
baseurl=http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/
gpgcheck=
[ceph-noarch]
name=cephnoarch
baseurl=http://mirrors.aliyun.com/ceph/rpm-jewel/el7/noarch/
gpgcheck=

然后在所有机器上配置ntp时间同步,具体操作不做说明。

配置admin-node到其他各节点的ssh免密访问。我这里图省事,直接使用root来完成后续操作,但在官方的标准安装中,要求使用普通帐号来完成,且这个帐号不能命名为ceph,因为ceph是默认启动ceph守护进程的帐户。给出一个示例:

useradd cephadmin
echo "cephadmin" | passwd --stdin cephadmin 要求所有的cephadmin有免密sudo的权限:
echo "cephd ALL = (root) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/cephd
sudo chmod /etc/sudoers.d/cephd vim /etc/sudoers Defaults:cephadmin !requiretty 然后使用这个帐户完成相互之间的ssh免密访问 最后在admin-node上编辑~/.ssh/config,内容示例如下: Host server-
Hostname server-
User cephadmin
Host server-
Hostname server-
User cephadmin
Host server-
Hostname server-
User cephadmin

部署ceph,下面所有的操作都在admin-node上完成:

安装ceph-deploy

yum install -y ceph-deploy

mkdir ceph-cluster    #创建部署目录,会在该目录生成一些必要的配置文件

cd ceph-cluster

如果之前安装过ceph,官方推荐使用如下命令获得一个干净的环境:
ceph-deploy purgedata server- server-
ceph-deploy forgetkeys
ceph-deploy purge server- server- 创建一个ceph cluster: ceph-deploy new server-117 server-236 server-227 #其中server-117为mon-node,可以指定多个mon-node 上面命令执行完成以后,会在当前目录合成一些辅助文件,其中ceph.conf默认内容如下:
[global]
fsid = 23078e5b-3f38--b2ef-7514a7fc09ff
mon_initial_members = server-
mon_host = 10.5.10.117
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx 我额外添加如下几行内容: public_network=10.5.10.0/ #定义互相通信的公有网络
mon_clock_drift_allowed = #定义多个mon节点之间时间的误差为2s
osd_pool_default_size = #定义最少可以允许有两个osd,默认是3个,如果节点数量足够,可不用修改 #以下三行配置都是为解决数据节点的存储盘为ext4文件系统时,解决“ERROR: osd init failed: () File name too long”错误的。ceph官方推荐存储盘使用xfs文件系统,但在有些特定的场合下,我们只能使用ext4文件系统。 osd_max_object_name_len =
osd_max_object_namespace_len =
filestore_xattr_use_omap = true
执行安装ceph:
ceph-depoly install server- server- server-

也可以直接在所有节点上执行如下操作:
yum install -y ceph ceph-radosgw

初始化mon-node:

ceph-deploy mon create-initial
这一过程执行完成以后,会在当前目录出现若干*.keyring文件,这是ceph组件间进行安全访问时所需要的
 
这时可以在各节点通过ps -ef | grep ceph来查看ceph-mon相关进程的运行状况:
ceph             : ?        :: /usr/bin/ceph-mon -f --cluster ceph --id server- --setuser ceph --setgroup ceph

初始化osd-node:

启动Osd-node可以分为两步:prepare和activate。osd-node是真正存储数据的节点,我们需要为ceph-osd提供独立存储空间,一般是一个独立的disk,但也可以使用目录取代。
 
在两个osd-node节点上分别创建用于存储的目录:
ssh server-
mkdir /data/osd0
exit ssh server-
mkdir /data/osd1
exit

执行如下操作:

#prepare操作会在上面创建的两个目录里创建一些后续activate激活以及osd运行时所需要的文件
ceph-deploy osd prepare server-:/data/osd0 server-:/data/osd1 #激活osd-node并启动
ceph-deploy osd prepare server-:/data/osd0 server-:/data/osd1

执行完以后,通常会抛出类似如下错误:

[WARNIN] -- ::40.325075 7fd1aa73f800 -  ** ERROR: error creating empty object store in /var/local/osd0: () Permission denied
[ERROR ] RuntimeError: command returned non-zero exit status:
[ceph_deploy][ERROR ] RuntimeError: Failed to execute command: /usr/sbin/ceph-disk -v activate --mark-init upstart --mount /data/osd0
这是因为ceph默认的守护进程的用户是ceph,无论是使用普通的ceph-admin创建的目录还是使用root创建的目录,ceph都没有访问权限。
所以需要在osd-node上再做一个授权:
server-236:
chown ceph.ceph -R /data/osd0 server-227:
chown ceph.ceph -R /data/osd1

往各节点同步配置文件:

ceph-deploy admin server- server- server-
注意,如果配置文件有修改,需要重新执行同步操作,并重新执行activate操作
 
通过如下指令查看集群状态:
ceph -s
ceph osd tree

当ceph集群安装完成以后,我们就要创建相应的rbd块用于kubernetes存储。创建块设备之前,需要先创建存储池,ceph提供了一个叫做rbd的默认存储池。我们再创建一个kube的存储专门用来存储kubernetes使用的块设备,后续的操作都在client-node上执行:

ceph osd pool create kube      #后面两个100分别为pg-num和pgp-num

在kube存储池创建一个映像文件,就叫mysql-sonar,该映像文件的大小为5GB:

rbd create kube/mysql-sonar --size  --image-format  --image-feature layering

注意,上面的命令,在我的环境下,如果不使用--image-feature layering,会抛出如下异常:

rbd: sysfs write failed
RBD image feature set mismatch. You can disable features unsupported by the kernel with "rbd feature disable".
In some cases useful info is found in syslog - try "dmesg | tail" or so.
rbd: map failed: () No such device or address

这是因为我目前centos 7.2的内核还不支持ceph的一些新特性。

将上面创建的映象文件映射为块设备:

rbd map kube/mysql-sonar --name client.admin

至此,ceph上的操作就完成了。

接下来我们看下如何在kubernetes上使用上面ceph创建的块设备。

我们可以在kubernetes的源码文件的examples/volumes/rbd目录下找到相关示例文件如下:

[root@server-116 ~]# ll /data/software/kubernetes/examples/volumes/rbd/
total 12
-rw-r-----. 1 root root 962 Mar 8 08:26 rbd.json
-rw-r-----. 1 root root 985 Mar 8 08:26 rbd-with-secret.json
-rw-r-----. 1 root root 2628 Mar 8 08:26 README.md
drwxr-x---. 2 root root 29 Mar 8 08:26 secret

[root@server-116 ~]# ll /data/software/kubernetes/examples/volumes/rbd/secret/
total 4
-rw-r-----. 1 root root 156 Mar 8 08:26 ceph-secret.yaml

其中rbd.json就是一个将rbd设备挂载为一个kubernetes volumes的示例文件。rbd-with-secret.json是使用secret的方式挂载ceph rbd的示例文件。ceph-secret.yaml是一个secret的示例文件。

我们可以先查看下ceph-secret.yaml文件:

apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
type: "kubernetes.io/rbd"
data:
key: QVFCMTZWMVZvRjVtRXhBQTVrQ1FzN2JCajhWVUxSdzI2Qzg0SEE9PQ==

我们只需要修改最后一行的key值。这个值通过base64进行过加密处理。处理前的值可以通过如下命令在ceph上获得:

ceph auth get-key client.admin

也可以直接通过如下方法查看:
[root@server- ~]# cat /etc/ceph/ceph.client.admin.keyring
[client.admin]
key = AQDRvL9YvY7vIxAA7RkO5S8OWH6Aidnu22OiFw==
caps mds = "allow *"
caps mon = "allow *"
caps osd = "allow *"

我们拿到这个key,然后做base64处理:

[root@server- ~]# echo "AQDRvL9YvY7vIxAA7RkO5S8OWH6Aidnu22OiFw==" | base64
QVFEUnZMOVl2WTd2SXhBQTdSa081UzhPV0g2QWlkbnUyMk9pRnc9PQo=

所以我们修改后的ceph-secret.yaml内容如下:

apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
type: "kubernetes.io/rbd"
data:
key: QVFEUnZMOVl2WTd2SXhBQTdSa081UzhPV0g2QWlkbnUyMk9pRnc9PQo=

创建一个secret:

kubectl create -f ceph-secret

由于直接使用volumes方式挂载的数据文件生命周期与pod一样,随着pod的释放而释放。所以在这里不推荐直接使用volumes的方式挂载,而使用pv的方式挂载。

我们先创建一个pv文件:

apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-sonar-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
rbd:
monitors:
- 10.5.10.117:
- 10.5.10.236:
- 10.5.10.227:
pool: kube
image: mysql-sonar
user: admin
secretRef:
name: ceph-secret
fsType: ext4
readOnly: false
persistentVolumeReclaimPolicy: Recycle

创建一个5GB大小的pv:

kubectl create -f mysql-sonar-pv.yml

再创建一个pvc文件:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mysql-sonar-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi

创建一个pvc:

kubectl create -f mysql-sonar-pvc.yml

最后我们修改上篇博文中创建的mysql-sonar-dm.yml文件,内容如下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mysql-sonar
spec:
replicas:
# selector:
# app: mysql-sonar
template:
metadata:
labels:
app: mysql-sonar
spec:
containers:
- name: mysql-sonar
image: myhub.fdccloud.com/library/mysql-yd:5.6
ports:
- containerPort:
env:
- name: MYSQL_ROOT_PASSWORD
value: "mysoft"
- name: MYSQL_DATABASE
value: sonardb
- name: MYSQL_USER
value: sonar
- name: MYSQL_PASSWORD
value: sonar
volumeMounts:
- name: mysql-sonar
mountPath: /var/lib/mysql
volumes:
- name: mysql-sonar
persistentVolumeClaim:
claimName: mysql-sonar-pvc

创建mysql pod:

kubectl create -f mysql-sonar-dm.yml

这样我们就创建了一个数据持久化的pod。我们可以通过往数据库上写入一些数据,然后再删除掉pod,再重新创建一个pod的方式来测试数据是否丢失。

需要说明的是,如果在创建容器的时候,rbd设备没有事先创建,或者我们在测试的时候,删除当前pod,但又还没完全删除的时候启动了一个新pod,这个pod就会一直处于ContainerCreating状态,这个时候kubelet日志会有相关报错。具体可以参考:http://tonybai.com/2016/11/07/integrate-kubernetes-with-ceph-rbd/

还需要说明的一点,必须在所有node节点上安装ceph-common包,否则,在启动容器时会出现类似如下报错:

ntVolume.SetUp failed for volume "kubernetes.io/rbd/da0deff5-0bef-11e7-bf41-00155d0a2521-mysql-sonar-pv" (spec.Name: "mysql-sonar-pv") pod "da0deff5-0bef-11e7-bf41-00155d0a2521" (UID: "da0deff5-0bef-11e7-bf41-00155d0a2521") with: rbd: map failed executable file not found in $PATH 
 

Kubernetes 1.5通过Ceph实现有状态容器的更多相关文章

  1. 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器?

    探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 线上多个服务应用陷入了死 ...

  2. ceph placement group状态总结

    一.归置组状态 1. Creating 创建存储池时,它会创建指定数量的归置组.ceph 在创建一或多个归置组时会显示 creating;创建完后,在其归置组的 Acting Set 里的 OSD 将 ...

  3. 分布式存储Ceph之PG状态详解

    https://www.jianshu.com/p/36c2d5682d87 1. PG介绍 继上次分享的<Ceph介绍及原理架构分享>,这次主要来分享Ceph中的PG各种状态详解,PG是 ...

  4. Kubernetes系列:故障排查之Pod状态为CreateContainerError

    查看pod状态如下图所示,当前状态为CreateContainerError. 通过kube describe命令去查看Pod的状态发现没有提示任何错误.但是当通过命令kube logs查看pod的日 ...

  5. 聊聊 Kubernetes Pod or Namespace 卡在 Terminating 状态的场景

    这个话题,想必玩过kubernetes的同学当不陌生,我会分Pod和Namespace分别来谈. 开门见山,为什么Pod会卡在Terminationg状态? 一句话,本质是API Server虽然标记 ...

  6. kubernetes删除pod,pod一直处于Terminating状态

    删除pod,pod一直处于Terminating状态 [root@yxz-cluster01 deploy_yaml]# kubectl get pod -n yunanbao NAME READY ...

  7. Kubernetes Dashboard - 每天5分钟玩转 Docker 容器技术(173)

    前面章节 Kubernetes 所有的操作我们都是通过命令行工具 kubectl 完成的.为了提供更丰富的用户体验,Kubernetes 还开发了一个基于 Web 的 Dashboard,用户可以用 ...

  8. 《Kubernetes与云原生应用》系列之容器设计模式

    http://www.infoq.com/cn/articles/kubernetes-and-cloud-native-app-container-design-pattern <Kubern ...

  9. Kubernetes将弃用Docker!与 containerd容器引擎

    时间戳:2022-06-07 20:32:19 星期二 撰写文档参考:(阿良-腾讯课堂)Kubernetes将弃用Docker 参考博客k8s入坑之路(3)containerd容器 container ...

随机推荐

  1. python基础知识-01-编码输入输出变量

    python其他知识目录 名词解释: 编辑器 ide 程序员 操作系统 ASCAII码 unicode utf-8 浅谈CPU.内存.硬盘之间的关系 操作系统及Python解释器工作原理讲解 关于编译 ...

  2. java面向对象的有序数组和无序数组的比较

    package aa; class Array{ //定义一个有序数组 private long[] a; //定义数组长度 private int nElems; //构造函数初始化 public ...

  3. curl和file_get_contents 区别以及各自的优劣

    PHP中fopen,file_get_contents,curl函数的区别: 1.fopen /file_get_contents 每次请求都会重新做DNS查询,并不对 DNS信息进行缓存.但是CUR ...

  4. Beta冲刺第二周王者荣耀交流协会第三次会议

    1.例会照片: 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐 master:袁玥 2.时间跨度: 2017年11月19日 17:00 — 17:11,总计11分钟. 3.地 点: 一食堂 ...

  5. java调试器

    javac.exe是编译.java文件 java.exe是执行编译好的.class文件 javadoc.exe是生成Java说明文档 jdb.exe是Java调试器 javaprof.exe是剖析工具 ...

  6. 记录 C++ STL 中 一些好用的函数--持续更新 (for_each,transform,count_if,find_if)

    在日常的编程中,有这么几种操作还是比较常见的: 把一组数据都赋值成一个数,在一组数据中查找一个数,统计一组数据中符合条件的数等等. 一般的写法可以用循环,没有什么是循环不能搞定的.假如在这里怎么用介绍 ...

  7. 线段树-hdu2795 Billboard(贴海报)

    hdu2795 Billboard 题意:h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子 思路:每次找到最大值的位子,然后减去L 线段树功能:query:区间求最大值的位子(直接 ...

  8. java 队列的使用(转载)

    转载声明:http://blog.csdn.net/lzy_lizhiyang/article/details/48311925 先我们要知道使用队列的目的是什么?一般情况下,如果是一些及时消息的处理 ...

  9. WOL*LAN远程换醒命令行方法

    wol远程唤醒需要网卡的支持,现在一般的网卡也都支持,只有有线网络能实现. 这里介绍Wake On Lan Command Line的使用 下载地址 https://www.depicus.com/w ...

  10. Bare metal APIs with ASP.NET Core MVC(转)

    ASP.NET Core MVC now provides a true "one asp.net" framework that can be used for building ...