Kubernetes 1.5通过Ceph实现有状态容器

在上一篇博文,我们通过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-117: admin-node   mon-node  client-node
server-236: osd-node  mon-node
server-227: osd-node  mon-node

在所有机器上配置yum源:

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

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

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

useradd cephadminecho "cephadmin" | passwd --stdin cephadmin

要求所有的cephadmin有免密sudo的权限:echo "cephd ALL = (root) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/cephdsudo chmod 0440 /etc/sudoers.d/cephd

vim /etc/sudoers

Defaults:cephadmin    !requiretty

然后使用这个帐户完成相互之间的ssh免密访问

最后在admin-node上编辑~/.ssh/config,内容示例如下:

Host server-117
   Hostname server-117
   User cephadmin
Host server-236
   Hostname server-236
   User cephadmin
Host server-227
   Hostname server-227
   User cephadmin

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

安装ceph-deployyum install -y ceph-deploymkdir ceph-cluster    #创建部署目录,会在该目录生成一些必要的配置文件

cd ceph-cluster

如果之前安装过ceph,官方推荐使用如下命令获得一个干净的环境:
ceph-deploy purgedata server-236 server-227ceph-deploy forgetkeys
ceph-deploy purge server-236 server-227创建一个ceph cluster:

ceph-deploy new server-117 server-236 server-227    #其中server-117为mon-node,可以指定多个mon-node

上面命令执行完成以后,会在当前目录合成一些辅助文件,其中ceph.conf默认内容如下:
[global]
fsid = 23078e5b-3f38-4276-b2ef-7514a7fc09ff
mon_initial_members = server-117mon_host = 10.5.10.117auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

我额外添加如下几行内容:

public_network=10.5.10.0/24    #定义互相通信的公有网络
mon_clock_drift_allowed = 2    #定义多个mon节点之间时间的误差为2s
osd_pool_default_size = 2    #定义最少可以允许有两个osd,默认是3个,如果节点数量足够,可不用修改

#以下三行配置都是为解决数据节点的存储盘为ext4文件系统时,解决“ERROR: osd init failed: (36) File name too long”错误的。ceph官方推荐存储盘使用xfs文件系统,但在有些特定的场合下,我们只能使用ext4文件系统。

osd_max_object_name_len = 256osd_max_object_namespace_len = 64filestore_xattr_use_omap = true

执行安装ceph:

ceph-depoly  server- server- server-  -y ceph ceph-radosgw

初始化mon-node:

ceph-deploy mon create-

这一过程执行完成以后,会在当前目录出现若干*.keyring文件,这是ceph组件间进行安全访问时所需要的

这时可以在各节点通过ps -ef | grep ceph来查看ceph-mon相关进程的运行状况:

ceph     31180     1  0 16:11 ?        00:00:04 /usr/bin/ceph-mon -f --cluster ceph --id server-117 --setuser ceph --setgroup ceph

初始化osd-node:

启动Osd-node可以分为两步:prepare和activate。osd-node是真正存储数据的节点,我们需要为ceph-osd提供独立存储空间,一般是一个独立的disk,但也可以使用目录取代。

在两个osd-node节点上分别创建用于存储的目录:

ssh server-236mkdir /data/osd0
exitssh server-227mkdir /data/osd1
exit

执行如下操作:

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

#激活osd-node并启动
ceph-deploy osd prepare server-236:/data/osd0 server-227:/data/osd1

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

[WARNIN] 2016-11-04 14:25:40.325075 7fd1aa73f800 -1  ** ERROR: error creating empty object store in /var/local/osd0: (13) Permission denied
[ERROR ] RuntimeError: command returned non-zero exit status: 1[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上再做一个授权:

 ceph.ceph -R /data/osd0

server-227:
chown ceph.ceph -R /data/osd1

往各节点同步配置文件:

ceph-deploy admin server-117 server-236 server-227

注意,如果配置文件有修改,需要重新执行同步操作,并重新执行activate操作

通过如下指令查看集群状态:

ceph -s
ceph osd tree

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

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

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

rbd create kube/mysql-sonar --size 5120 --image-format 2 --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: (6) No such device or address

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

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

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

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

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

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

[[email protected] ~]# 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

[[email protected] ~]# 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-- ~]#  /etc/ceph/= AQDRvL9YvY7vIxAA7RkO5S8OWH6Aidnu22OiFw=== = =

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

[[email protected] ~]# 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:6789
      - 10.5.10.236:6789
      - 10.5.10.227:6789
    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: 1                          #  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: 3306           
        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
时间: 2024-08-28 18:19:36

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

ceph placement group状态总结

一.归置组状态 1. Creating 创建存储池时,它会创建指定数量的归置组.ceph 在创建一或多个归置组时会显示 creating;创建完后,在其归置组的 Acting Set 里的 OSD 将建立互联;一旦互联完成,归置组状态应该变为 active+clean,意思是ceph 客户端可以向归置组写入数据了. 2. peering ceph 为归置组建立互联时,会让存储归置组副本的 OSD 之间就其中的对象和元数据状态达成一致.ceph 完成了互联,也就意味着存储着归置组的 OSD 就其当

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

查看pod状态如下图所示,当前状态为CreateContainerError. 通过kube describe命令去查看Pod的状态发现没有提示任何错误.但是当通过命令kube logs查看pod的日志时,可以看到提示日志“Failed to update lock: Operation cannot be fulfilled on endpoints "kube-controller-manager": the obj” 在pod所在节点通过docker ps -a | grep k

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

前面章节 Kubernetes 所有的操作我们都是通过命令行工具 kubectl 完成的.为了提供更丰富的用户体验,Kubernetes 还开发了一个基于 Web 的 Dashboard,用户可以用 Kubernetes Dashboard 部署容器化的应用.监控应用的状态.执行故障排查任务以及管理 Kubernetes 各种资源. 在 Kubernetes Dashboard 中可以查看集群中应用的运行状态,也能够创建和修改各种 Kubernetes 资源,比如 Deployment.Job.

理解Javascript的状态容器Redux

Redux要解决什么问题? 随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态). 这些 state 可能包括服务器响应.缓存数据.本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等.管理不断变化的 state 非常困难.如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依

2个Kubernetes使用同一个Ceph存储达到Kubernetes间持久化数据迁移

2个Kubernetes使用同一个Ceph存储达到Kubernetes间持久化数据迁移 [TOC] 当前最新Kubernetes稳定版为1.14.现在为止,还没有不同Kubernetes间持久化存储迁移的方案.但根据Kubernetes pv/pvc绑定流程和原理,只要 "存储"-->"PV"-->"PVC" 的绑定关系相同,即可保证不同间Kubernetes可挂载相同的存储,并且里面是相同数据. 1. 环境 原来我的Kubernet

Kubernetes的系统架构与设计理念

Kubernetes与云原生应用简介 随着Docker技术的发展和广泛流行,云原生应用和容器调度管理系统也成为IT领域大热的词汇.事实上,云原生应用的思想,在Docker技术火爆之前,已经由云计算技术的领导者和分布式系统架构的推广者广泛传播,例如云原生应用的12要素早在2011年就由Heroku的工程师提出了:只不过以虚拟机技术作为云原生应用的基础实施,由于虚拟机镜像大.镜像标准不统一以及打包流程和工具不统一,无法业界广泛接受的云原生应用标准,限制了云原生应用的流行.而Docker的出现正好解决

Kubernetes之深入了解Pod

1.yaml格式的Pod配置文件内容及注解 深入Pod之前,首先我们来了解下Pod的yaml整体文件内容及功能注解. 如下: # yaml格式的pod定义文件完整内容: apiVersion: v1 #必选,版本号,例如v1 kind: Pod #必选,Pod metadata: #必选,元数据 name: string #必选,Pod名称 namespace: string #必选,Pod所属的命名空间 labels: #自定义标签 - name: string #自定义标签名字 annota

Kubernetes基础篇:主要特性、基本概念与总体架构

Kubernetes基础篇:主要特性.基本概念与总体架构 本文试图将Kubernetes的基础相关知识描述清楚,让一个从来没有Kubernetes实践的开发人员,能够非常容易地理解Kubernetes是什么,能够做哪些事情,以及使用它能带来的好处是什么. Kubernetes是什么 Kubernetes是一个开源的容器编排引擎,它支持自动化部署.大规模可伸缩.应用容器化管理.我们在完成一个应用程序的开发时,需要冗余部署该应用的多个实例,同时需要支持对应用的请求进行负载均衡,在Kubernetes

Kubernetes 入门基础篇

Kubernetes 1.4 基础课程 Kubernetes 介绍 Kubernetes的发展历史 Kubernetes是一个开源的用于管理大量异构主机组成的云平台中容器的应用,Kubernetes的目标是让部署容器化的应用及微服务简单且高效.Kubernetes提供了应用部署.规划.更新和维护的软件集合,它的核心特点之一就是保证云平台中的容器按照用户的期望自动化的运行,云平台管理人员仅仅需要加载一个微型服务,规划器会自动找到合适的位置高可用的运行这个微服务. 在Docker作为高级容器引擎快速