0%

ceph-release rpm包用于在/etc/yum.repos.d/目录下安装ceph.repo文件。
本人使用容器进行RPM包构建,镜像为centos:7hub.docker.com下载)

rpmbuild安装

1
yum install -y rpm-build

rpmbuild目录树建立

1
mkdir -pv ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS,BUILDROOT}
  • SPEC 保存RPM包配置(.spec)文件
  • SOURCES 源代码目录,保存源码包(如.tar 包)和所有patch补丁
  • BUILD 构建目录,源码包被解压至此,并在该目录的子目录完成编译
  • BUILDROOT 最终安装目录,保存 %install 阶段安装的文件,打包好后此目录相关内容会自动删除
  • RPMS 标准RPM包目录,生成/保存二进制RPM包
  • SRPMS 源代码RPM包目录,生成/保存源码RPM包(SRPM)

构建BUILDROOT目录

1
2
mkdir -p ~/rpmbuild/BUILDROOT/ceph-release-1-1.el7.noarch/etc/yum.repos.d/
# 必须建一个你程序名的一个目录

~/rpmbuild/BUILDROOT/ceph-release-1-1.el7.noarch/etc/yum.repos.d/目录下创建ceph.repo文件,并写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
[Ceph]
name=Ceph packages for $basearch
baseurl=http://10.100.13.112/rpm-mimic/el7/$basearch
enabled=1
gpgcheck=0

[Ceph-noarch]
name=Ceph noarch packages
baseurl=http://10.100.13.112/rpm-mimic/el7/noarch
enabled=1
gpgcheck=0

编写SPEC文件

1
touch ~/rpmbuild/SPEC/ceph-release.spec

内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Name: ceph-release
Version: 1
Release: 1.el7
Summary: Ceph Release
License: GPL
Group: Applications/System
Vendor: zhoub
Buildarch: noarch

%description
%prep
%build
%pre
%post
%preun
%postun
%files
/etc/yum.repos.d/ceph.repo
%changelog
  • Name 标签就是软件名,Version标签为版本号,而Release是发布编号。
  • Summary 标签是简要说明,英文的话第一个字母应大写,以避免rpmlint工具(打包检查工具)警告
  • License 标签说明软件包的协议版本,审查软件的License状态是打包者的职责,这可以通过检查源码或LICENSE文件,或与作者沟通来完成。
  • Group 标签过去用于按照/usr/share/doc/rpm-/GROUPS分类软件包。目前该标记已丢弃,vim的模板还有这一条,删掉即可,不过添加该标记也不会有任何影响。
  • %changelog 标签应包含每个Release所做的更改日志,尤其应包含上游的安全/漏洞补丁的说明。Changelog日志可使用rpm --changelog -q <packagename>查询,通过查询可得知已安装的软件是否包含指定漏洞和安全补丁。%changelog条目应包含版本字符串,以避免rpmlint工具警告。
  • 多行的部分,如%changelog%description由指令下一行开始,空行结束。
  • 一些不需要的行(如BuildRequires和Requires)可使用‘#’注释。
  • %prep%build%install%file暂时用默认的,未做任何修改。

构建RPM包

1
rpmbuild -bb ~/rpmbuild/SPEC/ceph-release.spec

参考&鸣谢

Yum源

安装createrepo

1
yum install -y createrepo

创建仓库

使用createrepo工具创建、更新仓库

按Yum源的规则创建目录树rpm-<ceph版本名称>/<os version>/<arch>

1
2
mkdir -p ./ceph_repo/rpm-mimic/el7/x86_64/
mkdir -p ./ceph_repo/rpm-mimic/el7/noarch/

创建完目录树之后,将不同arch的rpm包copy到对应的目录中。然后在创建仓库

创建仓库

1
2
createrepo ./ceph_repo/rpm-mimic/el7/x86_64
createrepo ./ceph_repo/rpm-mimic/el7/noarch

若仓库中RPM有更新、增加、删除,需要更新仓库

1
createrepo --update ./ceph_repo/rpm-mimic/el7/x86_64/

发布仓库

本示例以docker形式发布仓库

1
docker run -d --net=host --name ceph_repo -v $PWD/ceph_repo:/root/repo -w /root/repo/ --restart=always python:3 python -m http.server 80

or

1
docker run -d --net=host --name ceph_repo -v $PWD/ceph_repo:/root/repo -w /root/repo/ --restart=always python:3 python -m SimpleHTTPServer 80

参考&鸣谢

export cephfs

创建用户目录

使用admin用户将根目录挂载,并创建用户使用需要的目录

1
mount -t ceph <monitor ip>:6789:/ /mnt/ -o name=admin,secret=xxxxxxxxxxxxxxxxxxxxxxxx==

/mnt目录下创建kubefs目录

给目录设置配额(Quota)

设置目录配额是linux内核本身提供的功能,cephfs只是支持了该功能。设置前需要先安装attr的rpm包yum install -y attr

设置目录配额

1
setfattr -n ceph.quota.size_bytes -v <size byte> /mnt/kubefs

通过getfattr可以获取该quota值。

cephfs quota 不能精确的限制配额,容量统计有延时,大概10s左右。

创建用户

创建一个名称为client.kubefs的用户,使其在/目录下有只读的权限,在/kubefs目录下有读写权限

1
ceph fs authorize cephfs client.kubefs / r /kubefs rw

cephfsfilesystem name,可以通过ceph fs ls查询。用户创建成功后,可以通过ceph auth list查询用户权限。需要删除用户也可以通过ceph auth rm仅限删除操作。

挂载

1
mount -t ceph <monitor ip>:6789:/kubefs /mnt/ -o name=kubefs,secret=xxxxxxxxxxxxxxxxxxxxxx==

export nfs

cephfs本身不支持nfs协议,可以通过nfs-ganesha将cephfs转成nfs提供出去。

镜像

ananace/nfs-ganesha-ceph

ganesha配置

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
# NFS protocol options
EXPORT
{
# Export Id (mandatory, each EXPORT must have a unique Export_Id)
Export_Id = 77;

# Exported path (mandatory)
Path = /;

# Pseudo Path (for NFS v4)
Pseudo = /;

# Access control options
Access_Type = RW;
Squash = No_Root_Squash;

# NFS protocol options
SecType = "sys";
Transports = TCP;
Protocols = 4;

# Exporting FSAL
FSAL {
Name = CEPH;
}
}

运行ganesha容器

1
docker run -d --net=host  -v /home/xxx/ceph/etc_ceph/:/etc/ceph -v /home/xxx/ceph/ganesha/:/etc/ganesha --name nfs -e GANESHA_BOOTSTRAP_CONFIG=no ananace/nfs-ganesha-ceph

Bucket Policy 开启S3数据分享这扇大门。该配置通过S3接口设置到Bucket上,使bucket可对某些用户开放一些访问权限;或拒绝某些用户的一些访问权限。

环境

  • Ceph集群版本mimic
  • RGW版本nautilus
  • 一个Realm中一个master zonegroup
  • master zonegroup中包含两个zone,exter(master zone)和backup
  • master zongrroup中包含两个placement,default-placement 和 cold-placement
    default-placement 将数据存储于 exter.rgw.buckets.{data, index, non-ec}
    cold-placement 将数据存储于 exter.rgw.cold.{data, index, non-ec}
  • zone exter中创建了4个用户分别属于ours tenant和 默认tenant
    默认tenant包括用户,colder 和 admin
    ours tenant包括用户,ourone 和 ourtwo
  • colder 用户使用的 cold-placement,其它用户均使用default-placement

使用

Policy 配置Json Example:

1
2
3
4
5
6
7
8
9
10
11
12
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": ["*"]},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-cold-bucket",
"arn:aws:s3:::my-cold-bucket/*"
]
}]
}

** 配置说明:**

  1. Version可以选择2008-10-17或者2012-10-17 AWS就是这样的,没道理讲的。
  2. EffectAllowDeny两个选项
  3. Principal操作主体。eg: “arn:aws:iam:::user/“ 该示例有待验证。
  4. ActionAllowDeny得动作
  5. Resource被操作得对象
  6. Condition使用条件

更多配置得内容参见ceph源码src/rgw/rgw_iam_policy_keywords.gperf

测试

目的

调研同tenant访问配置使用方法和跨tenant访问配置使用方法

测试方法

用户ours$ourone创建一个叫ouronebucket的bucket,并配置其policy

1
2
3
4
5
6
7
8
9
10
11
12
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": ["arn:aws:iam::ours:user/ourtwo", "arn:aws:iam:::user/admin"]},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::ouronebucket",
"arn:aws:s3:::ouronebucket/*"
]
}]
}

使用s3cmd工具将policy写入bucket

1
s3cmd setpolicy policy.json s3://ouronebucket

用户colder创建一个叫my-cold-bucket的bucket,并配置其policy

1
2
3
4
5
6
7
8
9
10
11
12
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": ["*"]},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-cold-bucket",
"arn:aws:s3:::my-cold-bucket/*"
]
}]
}

使用s3cmd工具将policy写入bucket

1
s3cmd setpolicy policy.json s3://my-cold-bucket

** 使用admin用户访问my-cold-bucket **

1
2
3
$ s3cmd -c ./admin.cfg ls s3://my-cold-bucket
2019-10-17 09:06 207 s3://my-cold-bucket/admin.cfg
2019-10-16 08:40 8478720 s3://my-cold-bucket/tgt.tar

同tenant内正常访问

** 使用admin用户访问ouronebucket **

1
2
3
4
5
$ s3cmd -c ./admin.cfg ls s3://ouronebucket
ERROR: Bucket 'ouronebucket' does not exist
ERROR: S3 error: 404 (NoSuchBucket)
$ s3cmd -c ./admin.cfg ls s3://ours:ouronebucket 12 ↵
ERROR: S3 error: 403 (SignatureDoesNotMatch)

** 使用ourtwo用户访问my-cold-bucket **

1
2
3
4
5
$ s3cmd -c ./ours_two.cfg ls s3://my-cold-bucket                                                                                                     77 ↵
ERROR: Bucket 'my-cold-bucket' does not exist
ERROR: S3 error: 404 (NoSuchBucket)
$ s3cmd -c ./ours_two.cfg ls s3://:my-cold-bucket 12 ↵
ERROR: S3 error: 403 (SignatureDoesNotMatch)

** 使用ourtwo用户访问ouronebucket **

1
2
3
4
5
$ s3cmd -c ./ours_two.cfg ls s3://ouronebucket                                                                                                       77 ↵
ERROR: Access to bucket 'ouronebucket' was denied
ERROR: S3 error: 403 (AccessDenied)
$ s3cmd -c ./ours_two.cfg ls s3://ours:ouronebucket 77 ↵
ERROR: S3 error: 403 (SignatureDoesNotMatch)

** 修改 **
ouronebucket的policy中的Principal改为{"AWS": ["*"]},。再试一次

1
2
3
4
5
6
$ s3cmd -c ./ours_two.cfg put ./ours_two.cfg s3://ouronebucket
WARNING: Module python-magic is not available. Guessing MIME types based on file extensions.
upload: './ours_two.cfg' -> 's3://ouronebucket/ours_two.cfg' [1 of 1]
207 of 207 100% in 0s 356.83 B/s done
$ s3cmd -c ./ours_two.cfg ls s3://ouronebucket
2019-10-17 12:01 207 s3://ouronebucket/ours_two.cfg

在网上看到“Rgw bucket policy权限设置”这篇文章,里面提到boto3对tenant不支持,于是猜想是不是s3cmd也不支持tenant,遂自己写一个python验证一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
# encoding: utf-8

import boto
import boto.s3.connection

access_list = ["1CXO01UCDSR1182IUYPL","8I4K2USDV5SK3UFLQUB0"]
secret_list = ["Ww0Io3b6fF7dXHQiO9gLo99DZbZAKqfvNO2N7g48","A4JuvB468tmnDpmkZMfwesb2zmGZeSiCJlzJMALc"]
bucket_list = [":my-cold-bucket","ours:ouronebucket"]

for i in range(0,len(access_list)):
access = access_list[i]
secret = secret_list[i]
bucket = bucket_list[i]
conn = boto.connect_s3(aws_access_key_id=access,
aws_secret_access_key = secret,
host='172.30.12.137',
port=7480,
is_secure=False,
calling_format = boto.s3.connection.OrdinaryCallingFormat())
bkt = conn.get_bucket(bucket)
print(bkt.get_all_keys())

执行下

1
2
3
# python bkt-policy.py
[<Key: :my-cold-bucket,admin.cfg>, <Key: :my-cold-bucket,tgt.tar>]
[<Key: ours:ouronebucket,ours_two.cfg>]

发现跨tenant可以正常访问。

修改ouronebucket policy 中的Principal{"AWS": ["arn:aws:iam::ours:user/two","arn:aws:iam:::user/admin"]},只允许ours$twoadmin这两个用户访问。
再次执行上面的python脚本

1
2
3
# python bkt-policy.py
[<Key: :my-cold-bucket,admin.cfg>, <Key: :my-cold-bucket,tgt.tar>]
[<Key: ours:ouronebucket,ours_two.cfg>]

再在上面的脚本中增加colder的access、secret key。并执行脚本

1
2
3
4
5
6
7
8
9
10
11
# python bkt-policy.py
[<Key: :my-cold-bucket,admin.cfg>, <Key: :my-cold-bucket,tgt.tar>]
[<Key: ours:ouronebucket,ours_two.cfg>]
Traceback (most recent call last):
File "bkt-policy.py", line 22, in <module>
bkt = conn.get_bucket(bucket)
File "/usr/local/lib/python2.7/site-packages/boto/s3/connection.py", line 509, in get_bucket
return self.head_bucket(bucket_name, headers=headers)
File "/usr/local/lib/python2.7/site-packages/boto/s3/connection.py", line 542, in head_bucket
raise err
boto.exception.S3ResponseError: S3ResponseError: 403 Forbidden

由于Principal中没有给colder用户授权,所以colder访问ouronebucket时报403错误。

参考&鸣谢

书接上文,上回书咱们了解了multisite的配置,最重要的是知道了zonegroup、zone是个什么东西,该怎么用。

那么今天我们来看看zonegroup和zone中的placement,顾名思义,用于告诉zone使用这个placement会将bucket、object要放到哪个里。

关于single rgw的模式,可以参考官网的使用配置,这里不做赘述了。下面介绍一下Multisite上的配置方法。

Placement

  1. 在master zone和非master zone上分别创建同名placement
  2. 使用的时候可以在用户信息中指定placement,也可以在创建bucket的s3请求中指定placement。

master zone

1
2
3
4
5
6
7
8
9
10
11
# radosgw-admin zonegroup placement add \
--rgw-zonegroup default \
--placement-id cold-placement

# radosgw-admin zone placement add \
--rgw-zone exter \
--placement-id cold-placement \
--data-pool exter.rgw.cold.data \
--index-pool exter.rgw.cold.index \
--data-extra-pool exter.rgw.cold.non-ec \
--compression zlib

看一下配置完的zone(此处忽略zonegroup配置完的接口)

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
# radosgw-admin zone get
{
"id": "69234f1d-8f48-4431-b45f-912087431a47",
"name": "exter",
"domain_root": "exter.rgw.meta:root",
"control_pool": "exter.rgw.control",
"gc_pool": "exter.rgw.log:gc",
"lc_pool": "exter.rgw.log:lc",
"log_pool": "exter.rgw.log",
"intent_log_pool": "exter.rgw.log:intent",
"usage_log_pool": "exter.rgw.log:usage",
"reshard_pool": "exter.rgw.log:reshard",
"user_keys_pool": "exter.rgw.meta:users.keys",
"user_email_pool": "exter.rgw.meta:users.email",
"user_swift_pool": "exter.rgw.meta:users.swift",
"user_uid_pool": "exter.rgw.meta:users.uid",
"otp_pool": "exter.rgw.otp",
"system_key": {
"access_key": "85ZFW53VCKBZR7DQ7GS8",
"secret_key": "MfyuJECq3Et2kktmf3T077rYwXQMEiIGYRlwKBnq"
},
"placement_pools": [
{
"key": "cold-placement",
"val": {
"index_pool": "exter.rgw.cold.index",
"data_pool": "exter.rgw.cold.data",
"data_extra_pool": "exter.rgw.cold.non-ec",
"index_type": 0,
"compression": "zlib"
}
},
{
"key": "default-placement",
"val": {
"index_pool": "exter.rgw.buckets.index",
"data_pool": "exter.rgw.buckets.data",
"data_extra_pool": "exter.rgw.buckets.non-ec",
"index_type": 0,
"compression": ""
}
}
],
"metadata_heap": "",
"realm_id": ""
}

让上述配置生效需要radosgw-admin period update --commit一下。

非master zone

1
2
3
4
5
6
7
8
9
10
11
# radosgw-admin zonegroup placement add \
--rgw-zonegroup default \
--placement-id cold-placement

# radosgw-admin zone placement add \
--rgw-zone backup \
--placement-id cold-placement \
--data-pool backup.rgw.cold.data \
--index-pool backup.rgw.cold.index \
--data-extra-pool backup.rgw.cold.non-ec \
--compression lz4

*** 此处用的压缩算法与之前master zone使用的不一致,不影响使用。放心。***rgw会在每个对象上记录一个压缩类型,所以即使你这一刻使用的压缩算法和之前使用的不一致也不影响解压工作。

看一下配置完的zone(此处忽略zonegroup配置完的接口)

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
# radosgw-admin zone get
{
"id": "a6621518-6f80-41f5-a736-fb5d1814e036",
"name": "backup",
"domain_root": "backup.rgw.meta:root",
"control_pool": "backup.rgw.control",
"gc_pool": "backup.rgw.log:gc",
"lc_pool": "backup.rgw.log:lc",
"log_pool": "backup.rgw.log",
"intent_log_pool": "backup.rgw.log:intent",
"usage_log_pool": "backup.rgw.log:usage",
"reshard_pool": "backup.rgw.log:reshard",
"user_keys_pool": "backup.rgw.meta:users.keys",
"user_email_pool": "backup.rgw.meta:users.email",
"user_swift_pool": "backup.rgw.meta:users.swift",
"user_uid_pool": "backup.rgw.meta:users.uid",
"otp_pool": "backup.rgw.otp",
"system_key": {
"access_key": "85ZFW53VCKBZR7DQ7GS8",
"secret_key": "MfyuJECq3Et2kktmf3T077rYwXQMEiIGYRlwKBnq"
},
"placement_pools": [
{
"key": "cold-placement",
"val": {
"index_pool": "backup.rgw.cold.index",
"data_pool": "backup.rgw.cold.data",
"data_extra_pool": "backkup.rgw.cold.non-ec",
"index_type": 0,
"compression": "lz4"
}
},
{
"key": "default-placement",
"val": {
"index_pool": "backup.rgw.buckets.index",
"data_pool": "backup.rgw.buckets.data",
"data_extra_pool": "backup.rgw.buckets.non-ec",
"index_type": 0,
"compression": ""
}
}
],
"metadata_heap": "",
"realm_id": "f334e6c2-c2b4-4c04-b541-f64d96c10c07"
}

同样为了上诉修改生效也需要执行一下radosgw-admin period update --commit

User中使用Placement

要想在User中配置Placement,首先得创建一个User。由于我们是在Multisite模式中创建的User,所以创建的动作必须在master zone上操作,如果在非master zone上操作用户不能同步到master zone上。具体原因请见Deploy multisite in 同一个集群

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
# radosgw-admin user create --uid colder --display-name colder

# radosgw-admin user info --uid colder
{
"user_id": "colder",
"display_name": "colder",
"email": "",
"suspended": 0,
"max_buckets": 1000,
"auid": 0,
"subusers": [],
"keys": [
{
"user": "colder",
"access_key": "WGCQOD46GA92J7CIGXIY",
"secret_key": "8yZw0FkYojiLdebWEF61HHTGhUvBrCel6ZzvGQRu"
}
],
"swift_keys": [],
"caps": [],
"op_mask": "read, write, delete",
"default_placement": "",
"placement_tags": [],
"bucket_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"user_quota": {
"enabled": false,
"check_on_raw": false,
"max_size": -1,
"max_size_kb": 0,
"max_objects": -1
},
"temp_url_keys": [],
"type": "rgw",
"mfa_ids": []
}

其中default_placement为空,此时会使用默认的placement也就是default-placement。所以需要配置这个选项。但是radosgw-admin中没有直接配置这个项目的参数,所以需要采用导出导入metadata的方式来修改该项目。

1
# radosgw-admin metadata get user:colder > colder.json

将user colder的配置导出到coder.json中,然后编辑其中的"default_placement": "cold-placement",,然后再将colder.json导入回去。

1
# radosgw-admin metadata put user:colder < colder.json

接下来可以使用该用户的access-key和secret-key去创建bucket并上传对象了。

在一个Ceph集群里部署一个multisite RGW环境。有什么意义吗?没有,存属个人折腾。由于资源有限,所以只能在一个集群里委屈了。

限盐少许,直接开整。

版本

14.2.3 (0f776cf838a1ae3130b2b73dc26be9c95c6ccc39) nautilus (stable)

RGW配置部署

一个Site的部署

修改.rgw.rootPool

修改/etc/ceph/ceph.conf中使用到.rgw.rootpool的所有配置项,将其改为exter.rgw.rootceph.conf中没有显示的配置,所以建议查找一下源代码中的配置options.cc
之后再创建realmzonegroupzone等信息都会记录到exter.rgw.root中。

1
2
3
4
5
rgw_zone_root_pool = exter.rgw.root
rgw_region_root_pool = exter.rgw.root
rgw_zonegroup_root_pool = exter.rgw.root
rgw_realm_root_pool = exter.rgw.root
rgw_period_root_pool = exter.rgw.root

配置完成后,启动RGW。本人将RGW安装到了容器中,所以下面给出容器的启动命令

1
docker run -d --net=host --name rgw -v /etc/ceph/:/etc/ceph/ -v /var/lib/ceph/:/var/lib/ceph/ ceph/daemon:latest-nautilus rgw

运行后记得用docker logs -f rgw看一下rgw日志,确保其正常运行。

然后使用ceph df看一下,当前RGW创建了哪些Pools

1
2
3
4
5
6
7
8
9
10
# ceph df
GLOBAL:
SIZE AVAIL RAW USED %RAW USED
57 GiB 56 GiB 654 MiB 1.12
POOLS:
NAME ID USED %USED MAX AVAIL OBJECTS
exter.rgw.root 18 1.2 KiB 0 27 GiB 4
default.rgw.control 19 0 B 0 27 GiB 8
default.rgw.meta 20 0 B 0 27 GiB 0
default.rgw.log 21 0 B 0 27 GiB 33

创建Realm

创建一个 realm ,若不创建,后续在设置自定义的zone为default时会报无效参数的错误。此问题,可以看rgw_admin.cc的源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
4438     case OPT_ZONE_DEFAULT:
4439 {
4440 RGWZoneGroup zonegroup(zonegroup_id,zonegroup_name);
4441 int ret = zonegroup.init(g_ceph_context, store->svc()->sysobj);
4442 if (ret < 0) {
4443 cerr << "WARNING: failed to initialize zonegroup " << zonegroup_name << std::endl;
4444 }
4445 if (zone_id.empty() && zone_name.empty()) {
4446 cerr << "no zone name or id provided" << std::endl;
4447 return EINVAL;
4448 }
4449 RGWZoneParams zone(zone_id, zone_name);
4450 ret = zone.init(g_ceph_context, store->svc()->sysobj);
4451 if (ret < 0) {
4452 cerr << "unable to initialize zone: " << cpp_strerror(-ret) << std::endl;
4453 return -ret;
4454 }
4455 ret = zone.set_as_default();
4456 if (ret < 0) {
4457 cerr << "failed to set zone as default: " << cpp_strerror(-ret) << std::endl;
4458 return -ret;
4459 }
4460 }
4461 break;

failed to set zone as default这个位置报错。

所以先配置一个realm吧

1
2
3
4
5
6
7
8
9
10
11
12
[root@master ~]# radosgw-admin realm list
{
"default_info": "",
"realms": []
}
[root@master ~]# radosgw-admin realm create --rgw-realm=default --default
{
"id": "f334e6c2-c2b4-4c04-b541-f64d96c10c07",
"name": "default",
"current_period": "40775bd3-d592-46c0-98c7-33171915825b",
"epoch": 1
}

设置zonegroup的default info

此时zonegroup的default info缺失了

1
2
3
4
5
6
7
8
9
[root@master ~]# radosgw-admin zonegroup list
{
"default_info": "",
"zonegroups": [
"default"
]
}
[root@master ~]# radosgw-admin zonegroup get
failed to init zonegroup: (2) No such file or directory

使用 zonegroup default重新设置default info

1
2
3
4
5
6
7
8
[root@master ~]# radosgw-admin zonegroup default --rgw-zonegroup=default
[root@master ~]# radosgw-admin zonegroup list
{
"default_info": "57b6eaac-63da-42dd-b69d-f7e871ce74c9",
"zonegroups": [
"default"
]
}

创建Zone

接下来,创建我们需要的zone, 并设置其为default

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
[root@master ~]# radosgw-admin zone list
{
"default_info": "",
"zones": [
"default"
]
}
[root@master ~]# radosgw-admin zone create --rgw-zonegroup=default --rgw-zone=exter --master --default
2019-10-14 19:00:50.322 7f3698ef7240 0 NOTICE: overriding master zone: f2a55476-fb68-4ea7-af97-251b91e94747
{
"id": "69234f1d-8f48-4431-b45f-912087431a47",
"name": "exter",
"domain_root": "exter.rgw.meta:root",
"control_pool": "exter.rgw.control",
"gc_pool": "exter.rgw.log:gc",
"lc_pool": "exter.rgw.log:lc",
"log_pool": "exter.rgw.log",
"intent_log_pool": "exter.rgw.log:intent",
"usage_log_pool": "exter.rgw.log:usage",
"reshard_pool": "exter.rgw.log:reshard",
"user_keys_pool": "exter.rgw.meta:users.keys",
"user_email_pool": "exter.rgw.meta:users.email",
"user_swift_pool": "exter.rgw.meta:users.swift",
"user_uid_pool": "exter.rgw.meta:users.uid",
"otp_pool": "exter.rgw.otp",
"system_key": {
"access_key": "",
"secret_key": ""
},
"placement_pools": [
{
"key": "default-placement",
"val": {
"index_pool": "exter.rgw.buckets.index",
"data_pool": "exter.rgw.buckets.data",
"data_extra_pool": "exter.rgw.buckets.non-ec",
"index_type": 0,
"compression": ""
}
}
],
"metadata_heap": "",
"realm_id": "f334e6c2-c2b4-4c04-b541-f64d96c10c07"
}
[root@master ~]# radosgw-admin zone list
{
"default_info": "69234f1d-8f48-4431-b45f-912087431a47",
"zones": [
"exter",
"default"
]
}

删除default zone

现在你会发现有两个zone了,一个是我们新建的,另一个是default,这个default没用了,我们把它删掉。

1
radosgw-admin zone delete --rgw-zone=default --default

细心的朋友可能会发现radosgw-admin命令中没有zone delete这个命令啊,-h中显示的是zone rm啊。这是Bug,嘿嘿嘿~~~

1
2
3
4
5
6
7
8
9
10
11
12
[root@master ~]# radosgw-admin -h | grep -i zone | grep -i rm
zonegroup rm remove a zone group info
zonegroup rm remove a zone from a zonegroup
zonegroup placement rm remove a placement target from a zonegroup
zone rm remove a zone
zone placement rm remove a zone placement target
--tags-rm=<list> list of tags to remove for zonegroup placement modify command
--sync-from-rm=[zone-name][,...]
[root@master ~]# radosgw-admin -h | grep -i delete
replica mdlog get/delete
replica datalog get/delete
(NOTE: required to delete a non-empty bucket)

重启RGW服务

1
2
[root@master ~]# docker stop rgw
[root@master ~]# docker start rgw

删除default相关的Pools

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@master ~]# ceph df
GLOBAL:
SIZE AVAIL RAW USED %RAW USED
57 GiB 56 GiB 657 MiB 1.13
POOLS:
NAME ID USED %USED MAX AVAIL OBJECTS
exter.rgw.root 18 1.7 KiB 0 27 GiB 13
default.rgw.control 19 0 B 0 27 GiB 8
default.rgw.meta 20 0 B 0 27 GiB 0
default.rgw.log 21 0 B 0 27 GiB 175
exter.rgw.control 22 0 B 0 27 GiB 8
exter.rgw.meta 23 0 B 0 27 GiB 0
exter.rgw.log 24 0 B 0 27 GiB 159

重启RGW服务后,发现多了三个Pool exter.rgw.controlexter.rgw.metaexter.rgw.log。而default开头的pool就没用了,可以删除了。

1
2
3
4
5
6
[root@master ~]# ceph osd pool rm default.rgw.control default.rgw.control --yes-i-really-really-mean-it
pool 'default.rgw.control' removed
[root@master ~]# ceph osd pool rm default.rgw.meta default.rgw.meta --yes-i-really-really-mean-it
pool 'default.rgw.meta' removed
[root@master ~]# ceph osd pool rm default.rgw.log default.rgw.log --yes-i-really-really-mean-it
pool 'default.rgw.log' removed

另一个Site的部署

*** 参考一个Site的部署方法吧 ***

Zone之间的数据同步

如果上述的部署方法你都清楚了,相信配置一个Zone之间同步数据的Multisite应该不在话下了。下面说说数据同步的几点注意事项吧。

  1. 数据同步必须是在不同zone之间进行的,但zone必须在同一zonegroup之下。
  2. 每一个zonegroup内都有一个master zone;一个realm中有多个zonegroup,但master zonegroup只有一个,realm命名空间全局唯一;
  3. 数据分为 period 数据、user数据、bucket数据、object数据。
    period数据需要用户手动配置,不能自动同步;
    user数据只能从master zone写入,然后非master zone同步;
    bucket数据可以从任意一个zone写入,但最后都会转发给master zone,待master 写入成功后,其它zone同步数据,若master失败,其它zone亦失败;
    object数据可以从任意一个zone写入,若master zone写入失败,不影响其它zone写入情况。
  4. 每个zone的endpoints需要配置,否则zone之间无法正常访问
  5. zone上配置的access keysecret要与master zone一致

补个图吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
                                          +--- master zone
|
+--- secondary zone 1
|
+---------- master zonegroup ----+--- ......
| |
| +--- secondary zone n
|
realm ---+---------- secondary zonegroup 1 --+--- master zone
| |
| +--- secondary zone 1
+---------- ...... |
| +--- ......
|
+---------- secondary zonegropu n

Ceph的部署有很多种,从最早的手动部署,到后来的Ceph-deploy,再到目前比较火的容器部署等等。但能作为生产环境部署的却不多,其中Ceph-ansible算是生产环境部署的方法之一。Ceph-ansible是基于ansible工具完成Ceph部署的。对于生产环境中动则几十、成百上千的节点数量如果一台一台安装配置效率太低。引入ansible工具可以快速完成Ceph集群的安装配置,大大提高效率。让运维人员从机械重复的工作中解脱出来。

使用

环境

三个节点,其中一个节点用作ansible和Ceph节点的复用节点。

节点IP 节点角色 OS
172.30.12.137 ansible节点、ceph节点 CentOS Linux release 7.7.1908
172.30.12.197 ceph节点 CentOS Linux release 7.7.1908
172.30.12.227 ceph节点 CentOS Linux release 7.7.1908

本文中使用的ansible工具运行在一个 CentOS7.6.1810 的容器内。

安装

ceph-ansible是基于ansible工作的,所以要先安装ansible。既然要安装ansible,首先要先搞清楚安装哪个版本?

本文部署的Ceph版本为mimic,官方推荐可以使用stable-3.1stable-3.2,我选择了较新的stable-3.2stable-3.2对应的ansible版本为2.6。(更多关于版本对应关系请见官网

选择完了ansible版本接下来就可以安装了,安装分为两种方式

  • pip 安装
  • yum/apt 安装

由于 yum/apt 安装版本选择范围比较狭窄,所以本人推荐使用 pip 安装。(关于pip安装请见pypa官网)

首先clone ceph-ansible project

1
2
# git clone git@github.com:ceph/ceph-ansible.git
# git checkout -b 3.2.0 v3.2.0

然后使用ceph-ansible中推荐的requirements.txt安装对应版本的ansible

1
pip install -r ./ceph-ansible/requirements.txt

待安装完成后,查看确认ansible版本

1
2
3
4
5
6
7
# ansible --version
ansible 2.6.19
config file = /root/ceph-ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]

配置

ansible 配置

ansible inventory 自定义的配置可以放置在任何位置,只是在运行ansible时增加-i {inventory host path}指定其路径即可。若不指定inventory文件,ansible将去/etc/ansible/hosts这个路径去找。

inventory配置:

1
2
3
4
5
6
7
8
9
[mons]
172.30.12.197 ansible_ssh_user=root ansible_ssh_pass=1234\$\#

[osds]
172.30.12.137 ansible_ssh_user=root ansible_ssh_pass=1234\$\#
172.30.12.197 ansible_ssh_user=root ansible_ssh_pass=1234\$\#

[mgrs]
172.30.12.137 ansible_ssh_user=root ansible_ssh_pass=1234\$\#

密码中若存在特殊字符$,#等,需要使用\\进行转义。
配置完成后,可使用ansible all -i {inventory host} -m ping测试节点连通情况

1
2
3
4
5
6
7
8
9
10
11
12
13
# ansible all -i dummy-ansible-hosts -m ping
172.30.12.197 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.30.12.227 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.30.12.137 | SUCCESS => {
"changed": false,
"ping": "pong"
}

ceph-ansible 配置

ceph-ansible的配置,主要是对group变量的配置,一般场景中我们不需要修改role。

配置 all.yml

首先:

1
cp ./gourp_vars/all.yml.sample ./gourp_vars/all.yml

然后,修改all.yml中的配置,如下:

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
# Inventory host group variables
mon_group_name: mons
osd_group_name: osds
#rgw_group_name: rgws
#mds_group_name: mdss
#nfs_group_name: nfss
#restapi_group_name: restapis
#rbdmirror_group_name: rbdmirrors
#client_group_name: clients
#iscsi_gw_group_name: iscsigws
#mgr_group_name: mgrs
# 上述 Inventory host 相关变量的默认值与 Inventory配置中的标签名一致,也就是说这里注释打开与否没有影响
...
# If configure_firewall is true, then ansible will try to configure the
# appropriate firewalling rules so that Ceph daemons can communicate
# with each others.
#configure_firewall: True
configure_firewall: False
# 建议Firewall配不明白的同学将Firewall关闭,免得找麻烦。
...
# Set type of NTP client daemon to use, valid entries are chronyd, ntpd or timesyncd
# Note that this selection is currently ignored on containerized deployments
#ntp_daemon_type: timesyncd
ntp_daemon_type: chronyd
# Ceph需要做时间同步,具体用什么做可根据自己环境来选择。目前提供支持的有三种 chronyd, ntpd, timesyncd
...
# ORIGIN SOURCE
#
# Choose between:
# - 'repository' means that you will get ceph installed through a new repository. Later below choose between 'community', 'rhcs', 'dev' or 'obs'
# - 'distro' means that no separate repo file will be added
# you will get whatever version of Ceph is included in your Linux distro.
# 'local' means that the ceph binaries will be copied over from the local machine
#ceph_origin: dummy
ceph_origin: repository
#valid_ceph_origins:
# - repository
# - distro
# - local

ceph_repository: community
#valid_ceph_repository:
# - community
# - rhcs
# - dev
# - uca
# - custom
# - obs

# REPOSITORY: COMMUNITY VERSION
#
# Enabled when ceph_repository == 'community'
#
#ceph_mirror: http://download.ceph.com
#ceph_stable_key: https://download.ceph.com/keys/release.asc
#ceph_stable_release: dummy
#ceph_stable_repo: "{{ ceph_mirror }}/debian-{{ ceph_stable_release }}"
ceph_mirror: http://mirrors.163.com/ceph
ceph_stable_key: https://mirrors.163.com/ceph/keys/release.asc
ceph_stable_release: mimic
ceph_stable_repo: "{{ ceph_mirror }}/rpm-{{ ceph_stable_release }}"
# Ceph 软件包的安装方式,有三种,repository使用一个新的源进行安装;distro使用linux发行版自带的源进行安装;local使用本地安装包的形式进行安装。
# 具体情况根据自身要求而定吧。
...
## Monitor options
#
# You must define either monitor_interface, monitor_address or monitor_address_block.
# These variables must be defined at least in all.yml and overrided if needed (inventory host file or group_vars/*.yml).
# Eg. If you want to specify for each monitor which address the monitor will bind to you can set it in your **inventory host file** by using 'monitor_address' variable.
# Preference will go to monitor_address if both monitor_address and monitor_interface are defined.
#monitor_interface: interface
monitor_interface: ens33
#monitor_address: 0.0.0.0
#monitor_address_block: subnet
# set to either ipv4 or ipv6, whichever your network is using
#ip_version: ipv4
#mon_use_fqdn: false # if set to true, the MON name used will be the fqdn in the ceph.conf
# Monitor的配置,必须要在 interface, address, address_block 中选择一个定义。(更多使用方法,请仔细阅读上面的英文吧。)
...
## OSD options
#
#is_hci: false
#hci_safety_factor: 0.2
#non_hci_safety_factor: 0.7
#osd_memory_target: 4294967296
#journal_size: 5120 # OSD journal size in MB
journal_size: 1024 # OSD journal size in MB
#block_db_size: -1 # block db size in bytes for the ceph-volume lvm batch. -1 means use the default of 'as big as possible'.
#public_network: 0.0.0.0/0
public_network: 172.30.12.0/24
cluster_network: 172.30.12.0/24
#cluster_network: "{{ public_network | regex_replace(' ', '') }}"
#osd_mkfs_type: xfs
#osd_mkfs_options_xfs: -f -i size=2048
#osd_mount_options_xfs: noatime,largeio,inode64,swalloc
#osd_objectstore: bluestore
osd_objectstore: filestore
# 根据硬盘的存储介质与速度决定Journal size的大小;配置public,cluster newtwork;选择objectstore filestore or bluestore
...

配置 osds.yml

首先

1
cp ./gourp_vars/osds.yml.sample ./gourp_vars/osds.yml

然后,修改osds.yml配置,如下:

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
...
# Even though OSD nodes should not have the admin key
# at their disposal, some people might want to have it
# distributed on OSD nodes. Setting 'copy_admin_key' to 'true'
# will copy the admin key to the /etc/ceph/ directory
#copy_admin_key: false
copy_admin_key: true
# 根据个人喜好来吧,我喜欢各个OSD节点都有admin key
...
# Declare devices to be used as OSDs
# All scenario(except 3rd) inherit from the following device declaration
# Note: This scenario uses the ceph-disk tool to provision OSDs

devices:
- /dev/sdb
- /dev/sdc
# - /dev/sdd
# - /dev/sde

#devices: []
# 根据主机情况配置硬盘路径相关信息
...
osd_scenario: collocated
#valid_osd_scenarios:
# - collocated
# - non-collocated
# - lvm
# collocated是将日志和数据部署到同一个硬盘上;non-collocated是分硬盘部署日志和数据;这两个选项都是使用ceph-disk创建的。
# lvm使用ceph-volume创建osd,需要指定vg、lvm等信息。
# 此处具体信息,请见`osds.yml.sample`里面有很详细的注解。
...

配置 mgrs.yml

首先

1
cp ./gourp_vars/mgrs.yml.sample ./gourp_vars/mgrs.yml

然后,修改mgrs.yml配置,如下:

1
2
3
4
5
6
7
...
###########
# MODULES #
###########
# Ceph mgr modules to enable, current modules available are: status,dashboard,localpool,restful,zabbix,prometheus,influx
ceph_mgr_modules: [status]
...

部署

集群初始化部署

首先

1
cp ./site.yml.sample ./site.yml

然后

1
2
ansible-playbook -i {inventory host} site.yml
...

部署过程需要下载RPM包安装,所以网速对部署速度的影响很大。请耐心等待。

增加OSD节点部署

首先

1
cp ./infrastructure-playbooks/add-osd.yml ./add-osd.yml

然后,修改inventory host文件,在[osds]中增加172.30.12.227这条记录,相当于增加一个osd节点。

1
2
3
4
5
6
7
8
9
10
[mons]
172.30.12.197 ansible_ssh_user=root ansible_ssh_pass=1234\$\#

[osds]
172.30.12.137 ansible_ssh_user=root ansible_ssh_pass=1234\$\#
172.30.12.197 ansible_ssh_user=root ansible_ssh_pass=1234\$\#
172.30.12.227 ansible_ssh_user=root ansible_ssh_pass=1234\$\#

[mgrs]
172.30.12.137 ansible_ssh_user=root ansible_ssh_pass=1234\$\#

最后

1
ansible-playbook -i {inventory host} add-osd.yml

清除集群部署

首先

1
cp ./infrastructure-playbooks/purge-cluster.yml ./purge-cluster.yml

然后

1
ansible-playbook -i {inventory host} purge-cluster.yml

Ceph配置文件分发

配置文件分发各个节点

1
ansible all -i dummy-ansible-hosts -m copy -a "src=/root/ceph.conf dest=/etc/ceph/"

参考&鸣谢

RGW支持很多种认证AWS标准的V2、V4;还有开放的LDAP,MFA,keystone,barbican等。太多了就不一一列举了。

LDAP

要想使用LDAP认证,首先你的有个LDAP Server。然后将RGW的LDAP开关打开,LDAP相关配置项配置好。重启RGW,你就可以使用LDAP认证了,简单不!

关于LDAP的搭建请见参考&鸣谢中的23

RGW配置

1
2
3
4
5
6
7
8
...
rgw_ldap_uri = ldap://10.100.13.111:389
rgw_ldap_binddn = "cn=Manager,dc=my-domain,dc=com"
rgw_ldap_secret = "/etc/ceph/bindpass"
rgw_ldap_searchdn = "dc=my-domain,dc=com"
rgw_ldap_dnattr = "cn"
rgw_s3_auth_use_ldap = true
...
  • rgw_ldap_binddn
    RGW访问LDAP Server使用的账户名
  • rgw_ldap_secret
    访问LDAP Server账户名对应的密码,必须放到文件中,这里指定一个访问文件的路径(明文存储文件就行)
  • rgw_ldap_searchdn
    验证是检索的范围
  • rgw_ldap_dnattr
    构建检索filter的属性名,RGW在程序中会将需要验证的账户名与之组对儿 eg: cn=ldapuser1

其它别的参数就不用解释了,看不懂可以先测一下智商。

LDAP_Server

截止目前未知,我都依然没有搞清楚什么事 cn,ou,dn,dc。嗯~~~~一头雾水啊!不管了,LDAP相关的自己问度娘去吧。

验证流程

Todo…

参考&鸣谢

  1. CEPH OBJECT GATEWAY WITH LDAP/AD GUIDE
  2. CentOS 7下安装部署OpenLDAP+phpLDAPadmin
  3. LDAP落地实战(一):OpenLDAP部署及管理维护

** 背景 **

容器是一个很老的技术,但这几年却很火热。好多应用都已经容器化了,只要是在用户空间运行的,几乎都可以被容器化。就是放到docker里运行。

面对着容器里运行的应用程序它与外界隔离了,这种隔离有优点,也有缺点。今天我们不讲优点,说一说它的一个缺点。。。

如果你是在linux上写C/C++的朋友,你肯定会用到gdb这个神一样的调试工具。在当下这么火爆的容器面前,你的APP可能早就被扔到容器里了。

有一天,除了一个问题,需要你用gdb去调试一下,我靠,ns完全是隔离的,根本无法调试,火大了吧,别急!我来帮你~v~

调试方法

方法一

其实gdb调试容器内app也不难,只要做到两点就可以成功调试了。

  1. 你所使用的镜像里必须得有gdb工具,没有怎么调试啊。要么做镜像的时候将gdb安装进去,要么使你的gdb与被调试app的容器处于同一命名空间。
  2. 使用一些工具(nsenter)侵入到容器命名空间后再运行gdb调试。eg: sudo nsenter -t {容器的PID} -m -p gdb -p {容器内被调试app的PID}

方法二

方法二也需要在被调试的容器上先装有gdb,然后在启动容器的时候通过增加一些特权参数。待需要调试的时候直接登录到容器内就可以调试了。

  1. 在启动docker容器的时候需要增加--privileged参数
  2. 由于gdb调试需要的SYS_PTRACE属性被禁止掉了,所以在启动容器时候需要增加这个属性--cap-add sys_ptrace
  3. gdb调试时,需要关闭linux虚拟地址随机化(虚拟地址随机化是为了安全考虑而出现的,gdb调试只是暂时关闭)。关闭有两种方法,一是通过gdb的命令set disable-randomization off关闭。二是通过设置docker的参数--security-opt seccomp=unconfined

有此三步,可保gdb无告警,并正常使用。

参考&鸣谢

容器化、容器化、容器化。。。都说重要的事情说三遍,那么Ceph部署有必要容器化吗?

有必要,非常有必要。容器化以后,不仅不会损失性能,而且对以后更新、回退都很方便。而且一个物理机(或虚拟机)上可以跑多个Ceph集群。对于一个开发人员,修改调试都实在是太方便了~~~~~!

闲言碎语不要讲,先拉个集群起来看看吧。

mimic

镜像

ceph/daemon:latest-mimic

网络

使用docker bridge网络,每个容器指定静态IP。

1
docker network create --subnet 192.168.44.0/24 cephnet

拉起Ceph集群

MON

1
docker run -d --net cephnet --ip 192.168.44.11 -v /Users/zhoub/temp/etc_ceph/:/etc/ceph -v /Users/zhoub/temp/var_lib_ceph/:/var/lib/ceph -e MON_IP=192.168.44.11 -e CEPH_PUBLIC_NETWORK=192.168.44.0/24 --name mon --hostname mon  ceph/daemon:latest-mimic mon

MGR

MGR节点很重要,如果没有MGR节点,你就看不到OSD的使用量了。现在的MON真是翻身农奴把歌唱啊,一心只做心跳了。

1
docker run -d --net cephnet --ip 192.168.44.12 -v /Users/zhoub/temp/etc_ceph/:/etc/ceph -v /Users/zhoub/temp/var_lib_ceph/:/var/lib/ceph --name mgr --hostname mgr ceph/daemon:latest-mimic mgr

OSD

OSD有两种部署方式,一种是将硬盘部署;另一种是目录部署。由于本人使用mac版本docker,所以在映射硬盘过程不太方便,所以使用目录部署。后面会给出硬盘部署的方式。

目录

1
docker run -d --net cephnet --ip 192.168.44.13 -v /Users/zhoub/temp/etc_ceph/:/etc/ceph -v /Users/zhoub/temp/var_lib_ceph/:/var/lib/ceph --name osd --hostname osd -e OSD_TYPE=directory ceph/daemon:latest-mimic osd

由于mac上的docker是运行在一个虚拟机中的,目前不太清楚该虚拟机使用的文件系统是什么,所以osd会暴如下错误:

1
2
3
4
5
6
7
8
9
10
11
$ docker logs -f osd
2019-09-23 10:59:14 /opt/ceph-container/bin/entrypoint.sh: static: does not generate config
2019-09-23 10:59:14 /opt/ceph-container/bin/entrypoint.sh: Creating osd
2019-09-23 10:59:14 /opt/ceph-container/bin/entrypoint.sh: OSD created with ID: 0
2019-09-23 10:59:14 /opt/ceph-container/bin/entrypoint.sh: created folder /var/lib/ceph/osd/ceph-0/
creating /var/lib/ceph/osd/ceph-0//keyring
added entity osd.0 auth auth(auid = 18446744073709551615 key=AQCCpYhdbE1EGxAAxX2Av3Gzez/5j8sijQg1jQ== with 0 caps)
2019-09-23 10:59:15.014 7f255136fd80 -1 filestore(/var/lib/ceph/osd/ceph-0) WARNING: max attr value size (1024) is smaller than osd_max_object_name_len (2048). Your backend filesystem appears to not support attrs large enough to handle the configured max rados name size. You may get unexpected ENAMETOOLONG errors on rados operations or buggy behavior
2019-09-23 10:59:15.084 7f255136fd80 -1 filestore(/var/lib/ceph/osd/ceph-0) mkjournal(1101): error creating journal on /var/lib/ceph/osd/ceph-0//journal: (22) Invalid argument
2019-09-23 10:59:15.084 7f255136fd80 -1 OSD::mkfs: ObjectStore::mkfs failed with error (22) Invalid argument
2019-09-23 10:59:15.084 7f255136fd80 -1 ** ERROR: error creating empty object store in /var/lib/ceph/osd/ceph-0: (22) Invalid argument

硬盘

在硬盘部署以前,需要先对硬盘进行格式化

1
docker run -d --privileged=true --rm -v /dev/:/dev/ -e OSD_DEVICE=/dev/sdb ceph/daemon:latest-mimic zap_device

格式化后再启动容器

1
docker run -d --net cephnet --ip 192.168.44.13 --hostname osd --name=osd --privileged  -v /Users/zhoub/temp/etc_ceph/:/etc/ceph -v /Users/zhoub/temp/var_lib_ceph/:/var/lib/ceph -v /dev/:/dev/ -e OSD_DEVICE=/dev/sdb ceph/daemon:latest-mimic osd

总结

集群除OSD服务外其它服务均可以正常容器化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@mon /]# ceph -s
cluster:
id: 61a4f9d8-fdc7-4883-8b71-7f93c2017f86
health: HEALTH_OK

services:
mon: 1 daemons, quorum mon
mgr: mgr(active)
osd: 1 osds: 0 up, 0 in

data:
pools: 0 pools, 0 pgs
objects: 0 objects, 0 B
usage: 0 B used, 0 B / 0 B avail
pgs:

OSD目录部署不能正常提供服务主要是因为宿主机的文件系统类型未知,若宿主机可正常登录操作,此问题可解;
OSD硬盘部署不能正常提供服务主要是因为宿主机不能增加硬盘设备,若宿主机可以添加硬盘,此问题可解。

综上所述,问题根本在于对宿主机的操作了解不够清晰。

参考&鸣谢