0%

tomcat9在systemd的沙箱中运行,默认只能访问一下路径:

1
2
3
4
- /var/lib/tomcat9/conf/Catalina (actually /etc/tomcat9/Catalina)
- /var/lib/tomcat9/logs (actually /var/log/tomcat9)
- /var/lib/tomcat9/webapps
- /var/lib/tomcat9/work (actually /var/cache/tomcat9)

如果需要访问其他路径,需要覆盖默认的service设置,添加文件/etc/systemd/system/tomcat9.service.d/override.conf,其内容如下:

1
2
\[Service\]
ReadWritePaths=/path/to/the/directory/

然后

1
2
$ sudo systemctl daemon-reload
$ sudo systemctl restart tomcat9

References:
[1]README.Debian

lxd集群使用ceph后端共享存储,多个host共同管理一组容器,可以提高lxd容器的可用性,但当前版本的lxd集群功能还不够完善,不支持lxd容器在集群host之间live migration,故障迁移支持也不完善。
lxd集群部署ceph后端,数据丢失的风险大大降低,集群中host掉线,可以将lxd容器快速移动到其他host继续提供服务。

bootstrap节点配置
第一个节点加入一个存在的集群选no,集群剩余其他节点选择加入现有集群。一个集群共享一个ceph pool,不同的集群要使用不同的ceph pool。

其他节点配置

1
2
3
4
5
6
7
8
9
10
11
12
$ sudo lxd init
Would you like to use LXD clustering? (yes/no) \[default=no\]: yes
What name should be used to identify this node in the cluster? \[default=web\]:
What IP address or DNS name should be used to reach this node? \[default=10.100.0.80\]:
Are you joining an existing cluster? (yes/no) \[default=no\]: yes
IP address or FQDN of an existing cluster node: 10.100.0.31
Cluster fingerprint: 79ec4bdfa32501a664b1adde03a2296f7d663a43676a422781668df1bec2ee12
You can validate this fingerprint by running "lxc info" locally on an existing node.
Is this the correct fingerprint? (yes/no) \[default=no\]: yes
Cluster trust password:
All existing data is lost when joining a cluster, continue? (yes/no) \[default=no\] yes
Would you like a YAML "lxd init" preseed to be printed? (yes/no) \[default=no\]:

集群管理
集群节点列表

1
2
3
4
5
6
7
8
9
10
$ lxc cluster list
+---------+--------------------------+----------+--------+-------------------+
NAME URL DATABASE STATE MESSAGE
+---------+--------------------------+----------+--------+-------------------+
vm02 https://10.100.0.33:8443 YES ONLINE fully operational
+---------+--------------------------+----------+--------+-------------------+
vmsvr02 https://10.100.0.31:8443 YES ONLINE fully operational
+---------+--------------------------+----------+--------+-------------------+
web https://10.100.0.80:8443 YES ONLINE fully operational
+---------+--------------------------+----------+--------+-------------------+

容器静态迁移,假设容器名字为foo,将其移动到node2主机运行

1
2
$ lxc stop foo
$ lxc move foo --target node2

容器所在主机故障时,可以使用lxc move移动容器到健康的节点继续运行,因为使用ceph,这个过程中没有主机间的数据拷贝。

如果lxd集群支持在线迁移和故障自动迁移就好用多了。

References:
[1]Clustering
[2]LXD Clusters: A Primer

debian buster升级后date命令默认输出12 hours格式,很不适应,locale一直使用en_US.UTF-8,这次升级en_US的默认时间显示格式调整了,这习惯还要变来变去吗?!

如果想继续显示24 hours格式,就要选择一个时间习惯是24 hours格式的locale

1
$ sudo update-locale LC_TIME=C.UTF-8

此命令修改了/etc/default/locale,添加了一行LC_TIME=C.UTF-8

References:
[1]``date`` in terminal now in 12hr format on Debian Buster
[2]general: en-us locale defaults to 24-hour “military” time on stock install

一、使用nfs-ganesha

需要先创建cephfs,参考使用CephFS文件系统

安装
在ceph集群的某个节点上安装nfs-ganesha-ceph

1
$ sudo apt install nfs-ganesha-ceph

如果启动服务时出错:

1
Failed to restart nfs-ganesha.service: The name org.freedesktop.PolicyKit1 was not provided by any .service files

安装policykit-1包

1
sudo apt install policykit-1

配置
/etc/ganesha/ganesha.conf

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
NFS_CORE_PARAM
{
Enable_NLM = false;

Enable_RQUOTA = false;

Protocols = 4;
}

NFSv4
{
Delegations = active;;

Minor_Versions = 1,2;
}

CACHEINODE {
Dir_Chunk = 0;

NParts = 1;
Cache_Size = 1;
}

EXPORT
{
# Unique export ID number for this export
Export_ID=100;

# We're only interested in NFSv4 in this configuration
Protocols = 4;

# NFSv4 does not allow UDP transport
Transports = TCP;

Path = /;
Pseudo = /cephfs/;

# We want to be able to read and write
Access_Type = RW;

# Time out attribute cache entries immediately
Attr_Expiration_Time = 0;

Delegations = RW;

Squash = no_root_squash;

FSAL {
# FSAL_CEPH export
Name = CEPH;
}
}

# Config block for FSAL_CEPH
CEPH
{
# Path to a ceph.conf file for this cluster.
# Ceph_Conf = /etc/ceph/ceph.conf;

# User file-creation mask. These bits will be masked off from the unix
# permissions on newly-created inodes.
# umask = 0;
}

重启nfs-ganesha服务

1
$ sudo systemctl restart nfs-ganesha

客户端挂载

1
$ sudo mount -t nfs4 -o nfsvers=4.2,rw 192.168.3.8:/ /mnt/mycephfs

或者

1
$ sudo mount -t nfs4 -o nfsvers=4.2,rw 192.168.3.8:/cephfs /mnt/mycephfs

/etc/fstab挂载项:

1
192.168.3.8:/ /mnt/mycephfs nfs4 nfsvers=4.2 0 0

二、使用kernel driver/ceph-fuse和nfsd

Ceph 提供了 kernel driver/ceph-fuse 来挂载和访问 CephFS。在 NFS 服务器上通过 kernel driver/ceph-fuse 挂载 CephFS 后,我们可以通过 nfsd 将其发布出去。

References:
[1]NFS
[2]将 Ceph 文件系统 CephFS 挂载为 NFS
[3]nfsidmap
[4]Deploying an Active/Active NFS Cluster over CephFS

ceph提供了一个具有很多高级特性的虚拟块设备,可以当做普通块设备来使用,也可以用于qemu等虚拟化环境。ceph提供的块设备具有多副本高可用、快照、精简配置、条带化、远程镜像等很多特性。

基本操作

创建并初始化一个块设备池,取名叫rbd

1
2
$ sudo ceph osd pool create rbd 36 36
$ sudo rbd pool init

如不提供pool名字,rdb命令默认使用名字为rdb的pool

创建块设备镜像data,大小为1024MB,可以忽略掉pool名字

1
$ sudo rbd create --size 1024 rbd/data

因为ceph使用精简配置,所以把size设置的大一些也无妨,不使用并不会真正的占用存储空间。

获取镜像信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ sudo rbd info data
rbd image 'data':
size 1 GiB in 256 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 2ab0d130bf615
block_name_prefix: rbd_data.2ab0d130bf615
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
op_features:
flags:
create_timestamp: Wed Nov 6 21:59:10 2019
access_timestamp: Wed Nov 6 21:59:10 2019
modify_timestamp: Wed Nov 6 21:59:10 2019

resize镜像,扩大和缩小

1
2
$ sudo rbd resize --size 2048 foo
$ sudo rbd resize --size 2048 foo --allow-shrink

删除块设备镜像

1
2
$ suro rbd rm {pool-name}/{image-name}
$ sudo rbd rm foo

内核模块块设备映射

可以通过内核模块将ceph块设备镜像映射成为OS可以操作的块设备,就像一个真的块设备一样,比如一块硬盘。

镜像列表

1
$ sudo rbd list

映射为块设备,使用默认的client.admin用户

1
2
3
4
5
6
7
8
9
###format: rbd device map {pool-name}/{image-name} --id {user-name}
$ sudo rbd device map data
bd: sysfs write failed
RBD image feature set mismatch. You can disable features unsupported by the kernel with "rbd feature disable data object-map fast-diff deep-flatten".
In some cases useful info is found in syslog - try "dmesg tail".
rbd: map failed: (6) No such device or address
$ sudo rbd feature disable data object-map fast-diff deep-flatten
$ sudo rbd device map data
/dev/rbd0

这里映射出来的块设备名字为/dev/rbd0,当做普通的块设备来使用就行了。

查看映射设备列表

1
2
3
$ sudo rbd device list
id pool namespace image snap device
0 rbd data - /dev/rbd0

取消设备映射

1
2
3
###format: rbd device unmap /dev/rbd/{poolname}/{imagename}
###format: rbd device unmap {devicename}
$ sudo rbd device unmap /dev/rbd0

注意:块设备是不能共享访问的,所以不要多次映射并行访问同一个镜像。

QEMU集成

创建镜像,要使用raw格式,不要使用其他格式

1
2
3
###format: qemu-img create -f raw rbd:{pool-name}/{image-name} {size}
$ sudo qemu-img create -f raw rbd:rbd/foo 10G
Formatting 'rbd:rbd/foo', fmt=raw size=10737418240

查看镜像信息

1
2
3
4
5
6
$ sudo qemu-img info rbd:rbd/foo
image: json:{"driver": "raw", "file": {"pool": "rbd", "image": "foo", "driver": "rbd"}}
file format: raw
virtual size: 10G (10737418240 bytes)
disk size: unavailable
cluster_size: 4194304

resize镜像

1
2
###format: qemu-img resize rbd:{pool-name}/{image-name} {size}
$ sudo qemu-img resize rbd:rbd/foo 20G

转换已有kvm镜像为ceph镜像

1
2
$ sudo qemu-img convert -f qcow2 -O raw bar.qcow2 rbd:rbd/bar
###or: sudo qemu-img convert -f qcow2 bar.qcow2 -O raw rbd:rbd/bar

运行客户机

1
$ qemu -m 1024 -drive format=rbd,file=rbd:rbd/bar,cache=writeback

lxd集成

lxd已经内置支持ceph集群存储,执行lxd init时,指定存储后端为ceph即可。
也可以使用lxc storage命令创建新的存储池。
lxd集群使用ceph后端存储可以创建高可用lxd容器,但是同一时刻只能有一个节点在运行一个容器实例,需要其他机制来自动故障转移。

References:
[1]CEPH BLOCK DEVICE
[2]Ceph 中块设备 RBD 的基本用法
[3]Ceph storage driver in LXD

创建池
ceph文件系统需要驻留在pool上,至少需要创建一个data和一个metadata pool

1
2
3
4
5
6
7
$ sudo ceph osd pool create cephfs_data 128
pool 'cephfs_data' created

$ sudo ceph osd pool create cephfs_metadata 128
Error ERANGE: pg_num 128 size 3 would mean 768 total pgs, which exceeds max 750 (mon_max_pg_per_osd 250 * num_in_osds 3)
john@node6:~$ sudo ceph osd pool create cephfs_metadata 24
pool 'cephfs_metadata' created

创建文件系统

1
2
3
4
$ sudo ceph fs new cephfs cephfs_metadata cephfs_data
new fs with metadata pool 2 and data pool 1
$ sudo ceph fs ls
name: cephfs, metadata pool: cephfs_metadata, data pools: \[cephfs_data \]

查看mds状态

1
2
$ sudo ceph mds stat
cephfs:1 {0=node6=up:active} 2 up:standby

没有创建文件系统之前,所有的mds实例都为standby状态
集群状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ sudo ceph -s
cluster:
id: 0238426d-78d6-48cd-af64-b6a8407996c6
health: HEALTH_OK

services:
mon: 3 daemons, quorum node8,node6,node7 (age 11m)
mgr: node6(active, since 11m), standbys: node7, node8
mds: cephfs:1 {0=node6=up:active} 2 up:standby
osd: 3 osds: 3 up (since 11m), 3 in (since 3d)

data:
pools: 2 pools, 152 pgs
objects: 22 objects, 2.2 KiB
usage: 3.0 GiB used, 18 GiB / 21 GiB avail
pgs: 152 active+clean

fuse挂载cephfs
安装客户端和fuse

1
$ sudo apt install ceph-common ceph-fuse

将集群配置/etc/ceph/*拷贝到客户机相同位置
挂载

1
$ sudo ceph-fuse /path/to/mount

或者指定monitor地址

1
$ sudo ceph-fuse -m ip_of_monitor /path/to/mount

/etc/fstab:

1
none /mnt/mycephfs fuse.ceph ceph.id=admin,_netdev,defaults 0 0

这里指定使用admin用户,使用其他用户需要提前建立用户keyring

内核驱动挂载cephfs

1
2
$ sudo mount.ceph 192.168.3.8:/ /mnt/mycephfs -o name=admin,secret=AQBHybZdKRryLRAAY9jTUkPpNcXmeykzFPNTTw==
###or: sudo mount -t ceph 192.168.3.8:6789:/ /mnt/mycephfs -o name=admin,secret=AQBHybZdKRryLRAAY9jTUkPpNcXmeykzFPNTTw==

如果不指定name选项,默认使用guest用户
当前内核驱动使用msgr v1协议与ceph集群通讯,因此应该使用6789端口,指定3300端口无法连接。

后记:
只要/etc/ceph目录下的文件普通用户可以读取,特别是keyring文件,那么普通用户就可以连接到集群使用所有的ceph命令。

References:
[1]CREATE A CEPH FILESYSTEM
[2]MOUNT CEPHFS WITH THE KERNEL DRIVER
[3]CEPHFS ADMINISTRATIVE COMMANDS
[4]cephx
[5]Ceph Pool操作总结
[6]POOLS
[7]Mount Ceph Filesystem
[8]MOUNT CEPHFS IN YOUR FILE SYSTEMS TABLE
[9]Ceph 文件系统 CephFS 的介绍与配置
[10]CEPHFS SHELL

一、添加manager

通常每一个运行monitor的机器上同时运行一个manager,以获取同样的可用性,但是manager不涉及到选举,运行于primary/standby模式。

1、创建mgr认证keyring

1
2
3
$ sudo ceph auth get-or-create mgr.node6 mon 'allow profile mgr' osd 'allow *' mds 'allow *'
\[mgr.node6\]
key = AQDAzLpdq7HzDRAAkRLSSkRO/1aLZU+87FcN5g==

这里mgr的名字仍然选用主机名,也就是mgr.$(hostname -s)

2、创建mgr实例的目录

1
sudo -u ceph mkdir /var/lib/ceph/mgr/ceph-node6/

3、导出mgr keyring到ngr实例目录

1
2
$ sudo ceph auth get mgr.node6 -o /var/lib/ceph/mgr/ceph-node6/keyring
exported keyring for mgr.node6

4、运行mgr实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ sudo systemctl enable ceph-mgr@node6.service
$ sudo systemctl start ceph-mgr@node6.service
$ sudo ceph -s
cluster:
id: 0238426d-78d6-48cd-af64-b6a8407996c6
health: HEALTH_OK

services:
mon: 3 daemons, quorum node8,node6,node7 (age 11m)
mgr: node6(active, starting, since 0.109568s)
osd: 0 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:

可以看到mgr活动实例启动了,重复以上步骤添加其他mgr实例。

二、添加OSD

OSD(Object Storage Device)是真正存储数据的组件,一般生产环境至少要部署3个OSD,参数文件/etc/ceph/ceph.conf中osd pool default size = 3设定为3,至少需要3个osd进程,集群才能达到active + clean状态。

OSD有几种后端存储,建议使用bluestore提高系统稳定性和效率,bluestore只能使用逻辑卷、磁盘或分区,注意初始化OSD时指定的逻辑卷、磁盘或者分区上的数据会全部被抹掉。一般建议OSD使用单独的机器部署,并且与OS分别使用不同的驱动器。

1、导出client.bootstrap-osd keyring
如果本地机器上没有此keyring,则需要先从集群导出到本地

1
$ sudo ceph auth get client.bootstrap-osd -o /var/lib/ceph/bootstrap-osd/ceph.keyring

2、创建OSD

1
$ sudo ceph-volume lvm create --data /dev/sdb

注意要使用正确的底层设备,lsblk可以查看系统块存储设备。
如果提示错误:

1
2
3
4
ceph-volume lvm create: error: GPT headers found, they must be removed on: /dev/sdb
...
stderr: Device /dev/sdc excluded by a filter.
...

需要先清除掉分区表:

1
2
$ sudo partprobe -s /dev/sdb
$ sudo dd if=/dev/zero of=/dev/sdb bs=512 count=1

注意:这些操作是破坏性的,一定要确认是在正确的块设备上进行操作。

3、运行OSD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ sudo ceph-volume lvm list

====== osd.0 =======

\[block\] /dev/ceph-f67dd26c-f5d8-44ca-a9da-fe6b6fccec65/osd-block-bf952b83-7ffe-49e2-bdd7-d2fd3faacafb

block device /dev/ceph-f67dd26c-f5d8-44ca-a9da-fe6b6fccec65/osd-block-bf952b83-7ffe-49e2-bdd7-d2fd3faacafb
block uuid jYMJc5-jjUe-hgPk-Wlhk-yo9y-t6JF-r8SqNa
cephx lockbox secret
cluster fsid 0238426D-78D6-48CD-AF64-B6A8407996C6
cluster name ceph
crush device class None
encrypted 0
osd fsid bf952b83-7ffe-49e2-bdd7-d2fd3faacafb
osd id 0
type block
vdo 0
devices /dev/sdb

//sudo systemctl enable ceph-osd@0.service
//sudo systemctl start ceph-osd@0.service

先查找osd实例的名称,然后启用相应的实例服务,ceph-volume会自动创建相应的服务并启动它们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ sudo ceph -s
cluster:
id: 0238426d-78d6-48cd-af64-b6a8407996c6
health: HEALTH_OK

services:
mon: 3 daemons, quorum node8,node6,node7 (age 37m)
mgr: node6(active, since 25m), standbys: node7, node8
osd: 1 osds: 1 up (since 85s), 1 in (since 85s)

data:
pools: 0 pools, 0 pgs
objects: 0 objects, 0 B
usage: 1.0 GiB used, 6.0 GiB / 7 GiB avail
pgs:

可以看到运行了一个osd实例,重复以上步骤添加其他OSD实例。

三、添加mds
如果要使用CephFS文件系统才需要设置mds实例,对象存储和块设备存储无需mds实例。

1、创建mds实例目录

1
$ sudo -u ceph mkdir -p /var/lib/ceph/mds/ceph-node6

目录格式为{cluster-name}-{id},按照惯例这里id仍然取主机名$(hostname -s)

2、创建mds实例keyring

1
$ sudo -u ceph ceph-authtool --create-keyring /var/lib/ceph/mds/ceph-node6/keyring --gen-key -n mds.node6

3、将mds实例keyring导入集群并设置caps权限

1
2
$ sudo ceph auth add mds.node6 osd "allow rwx" mds "allow" mon "allow profile mds" -i /var/lib/ceph/mds/ceph-node6/keyring
added key for mds.node6

或者2,3步合并为一步:

1
$ sudo ceph auth get-or-create mds.node6 mon 'allow profile mds' mgr 'allow profile mds' mds 'allow *' osd 'allow *' sudo -u ceph tee /var/lib/ceph/mds/ceph-node6/keyring

4、编辑/etc/ceph/ceph.conf添加mds实例

1
2
\[mds.node6\]
host = node6

5、启动mds实例

1
2
$ sudo systemctl enable ceph-mds@node6
$ sudo systemctl start ceph-mds@node6

References:
[1]CEPH-MGR ADMINISTRATOR’S GUIDE
[2]DEPLOYING METADATA SERVERS

lxd容器内挂载NFS文件系统时出现错误提示:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sudo mount -t nfs 192.168.0.62:/srv/homes/upload /mnt/nfs/
mount.nfs: Operation not permitted
$ sudo mount -t nfs -v 192.168.0.62:/srv/homes/upload /mnt/nfs/
mount.nfs: timeout set for Thu Oct 24 19:05:41 2019
mount.nfs: trying text-based options 'vers=4.2,addr=192.168.0.62,clientaddr=10.100.0.20'
mount.nfs: mount(2): Operation not permitted
mount.nfs: trying text-based options 'addr=192.168.0.62'
mount.nfs: prog 100003, trying vers=3, prot=6
mount.nfs: trying 192.168.0.62 prog 100003 vers 3 prot TCP port 2049
mount.nfs: prog 100005, trying vers=3, prot=17
mount.nfs: trying 192.168.0.62 prog 100005 vers 3 prot UDP port 39588
mount.nfs: mount(2): Operation not permitted
mount.nfs: Operation not permitted

总之就是权限问题,因为容器是非特权容器,在容器内使用root并不是真正的特权用户,因此仍然无法挂载NFS文件系统,CIFS也是一样的问题。
简单的解决办法就是将容器设置为特权容器:

1
2
3
$ lxc config set container raw.lxc "lxc.apparmor.profile=unconfined"
$ lxc config set container security.privileged true
$ lxc restart container

restart容器之后挂载一切如常。
注意一定要同时关闭apparmor

默认配置的非特权lxd容器内,即使以特权用户运行dmesg

1
2
# dmesg
dmesg: read kernel buffer failed: Operation not permitted

也是不允许访问内核缓冲区的,这是因为目前容器尚不能做到只读取自己相关的dmesg信息,如果允许容器运行dmesg,容器则会读取到主机全部的信息,包括主机和其他容器以及apparmor的信息,这是安全问题,lxd以后应该会支持每容器的dmesg信息,现在只能在主机上简单粗暴的设置内核参数kernel.dmesg_restrict,特权容器不受此参数限制。

如果允许容器运行dmesg,则需要关闭此参数

1
$ sudo sysctl kernel.dmesg_restrict=0

References:
[1]deny access to dmesg or use SYSLOG namespace