关于osd的主从复制:
说明:
- 如此架构,写入性能取决于三个osd中最慢的osd的性能,似乎有些不妥;不过,每个osd都在同时担任多种角色,就不应该允许有问题的osd提供服务;另外,有工具可以发现那个osd响应慢
在一共4台机器,13个osd的情况下,某osd已经和其它osd创建了60个连接了:
DevOps
关于osd的主从复制:
说明:
在一共4台机器,13个osd的情况下,某osd已经和其它osd创建了60个连接了:
题记:
尽信书则不如无书
按照书上说的配置完cephfs后,无法mount成功,ceph-fuse的错误信息为:
1 |
handle_connect_reply connect got BADAUTHORIZER |
mds 日志错误信息为:
1 |
mds.client.cephfs ms_verify_authorizer: cannot decode auth caps bl of length 0 |
从代码来看,就是caps给的不够。
书上关于caps的命令为:
1 |
#ceph auth get-or-create client.cephfs mon 'allow r' osd 'allow rwx pool=cephfs_metadata, allow rwx pool=cephfs_data' |
实际上,还需要添加关于mds的授权,如果对mds之授权r, 则可以挂载,但是不可写;所以正常情况下,需要添加对mds的rw,更新授权信息如下:
1 |
# ceph auth caps client.cephfs mds 'allow rw' mon 'allow r' osd 'allow rwx pool=cephfs_metadata,allow rwx pool=cephfs_data' |
如果我们只想让client.cephfs 访问 /data 目录,则可以添加更新授权信息如下:
1 |
# ceph auth caps client.cephfs mds 'allow r, allow rw path=/data' mon 'allow r' osd 'allow rwx pool=cephfs_metadata,allow rwx pool=cephfs_data' |
注意: 这里似乎并未指定是哪个fs,如何区分不同的fs呢?
关于限制用户访问指定目录的问题,有更加方便的做法: http://docs.ceph.com/docs/master/cephfs/client-auth/)
eg:
其实,该操作也是反映在ceph auth里面的,如下:
如此来看,具体是哪个cephfs,其实不是本质的东西,本质上还是对pool的授权
另外:ceph fs authorize 命令目前似乎不能操作现有用户(不能修改、也不能删除),该命令只能添加新用户;需要修改删除啥的还是要使用ceph auth的
下面使用client.phpor 尝试挂载,验证权限是否生效:
权限设置生效
结论:
关于授权这部分,官方文档似乎并未提及
参考:http://www.yangguanjun.com/2017/07/01/cephfs-client-authentication/
前言
openstack是个很不错的东西,结合ceph之后,openstack就如同插上了翅膀,更加强大了。
ceph的好处:
我遇到的问题:
解决办法:
参考配置文件 /etc/glance/glance-api.conf 得知,show_multiple_locations = True使得image的地址直接暴露给了client,client就可以直接操作image了,可能存在一定的安全问题;当我们认为这不是问题的时候,我们就可以修改该配置,现在,我正是想利用rbd的一些特性,就需要将给选项设置为True;
总结:
两者功能一样,效果也没啥差别,只是实现方式有所不同; 前者使用内核的rbd模块访问ceph存储,当ceph较新(内核较旧)时,可能会有一些image的feature内核不支持,就不能map;后者使用librbd来访问ceph存储,基本不会存在feature不支持的情况,但是需要nbd内核模块(关于nbd内核模块的担心似乎也多余,nbd早就进入内核了,就算没有加载,rbd-nbd也会帮你加载的)。
同一个rbd image可以同时在一台服务器上map多次;但是只能mount一次,因为多次挂载后设备的uuid是同一个,文件系统不允许同时挂载两个相同uuid的设备的
同一个rbd image可以同时挂载到多个服务器上; (rbd的 –shared –image-shared 选项可以控制是否允许重复挂载)
–shared 允许给镜像加锁,避免写坏,实现特定条件下的共享
–image-shared 允许定义是否可以共享
也就是说,ceph的image是可以作为共享存储使用的(但是最好别这么做,没有任何机制保证并发写不会出问题)。
注意:
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 |
#define _GNU_SOURCE #include <sched.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <unistd.h> static char child_stack[1048576]; static int child_fn() { printf("PID: %ld\n", (long)getpid()); sleep(100000); return 0; } int main(int ac, char** av) { int ch; int flag = SIGCHLD; while((ch = getopt(ac, av, "pmnuU")) != -1) { switch(ch) { case 'p': flag |= CLONE_NEWPID;break; case 'm': flag |= CLONE_NEWNS;break; case 'n': flag |= CLONE_NEWNET;break; case 'u': flag |= CLONE_NEWUTS;break; case 'U': flag |= CLONE_NEWUSER;break; } } pid_t child_pid = clone(child_fn, child_stack+1048576, flag, NULL); printf("clone() = %ld\n", (long)child_pid); waitpid(child_pid, NULL, 0); return 0; } |
功能: 创建新的名字空间,并使得进程处于sleep状态,可以随时nsenter进来
测试 mnt 时发现,似乎并没有实现mount的隔离; 测试方法:
./new-namespace -m &
然后使用nsenter,分别在名字空间内外查看 /proc/self/mountinfo 的内容,发现如何操作,内外都是一致的。
注意: 需要和pid名字空间一起使用:
1 2 |
./new-namespace -m -p & nsenter -m -p -t $pid |
参考: https://www.toptal.com/linux/separation-anxiety-isolating-your-system-with-linux-namespaces
有时候,我们为了安全,禁用root账号登录,需要root的话,在普通账号登录后再sudo;也有时候,我们期望vnc桌面的时候使用的是root账号,于是,我们在普通账号sudo(或sudo -s )后启动vncserver,于是问题来了,我们vnc看到的桌面是黑色的,而且里面的窗口是没有菜单的
解决办法:
kvm上安装windows虚拟机时,如果起初配置的磁盘就是virtio驱动的,则安装时会发现不到磁盘,需要使用virt-win.iso 来安装驱动; 如果起初使用的是IDE,则可以顺利安装windows,如果安装后才发现IDE其实没有virtio 高效,于是直接修改为virtio,则windows就会启动不了;解决办法:
先不要讲IDE修改为virtio,而是先挂一个virtio的磁盘,然后会在windows的设备管理器中发现缺少驱动,使用virtio-win.iso 安装驱动即可;然后删掉多余的virtio磁盘,并且将系统盘修改为virtio即可
参考: http://blog.chinaunix.net/uid-20776139-id-3481065.html
对于kvm虚拟机,由于宿主机和guest之间的独立性很大,当guest把很多内存用于系统cache的话,宿主机也没有办法识别这部分内存,也没有办法建议guest让出一部分内存。
kvm有个内存气球的概念,原以为可以在不改变guest已定义的内存大小的情况下可以让guest让出一部分非关键性的内存占用,而实际上balloon却是在修改(变大和变小)guest的总内存大小,而且在减小guest内存大小的时候,也是武断地减少内存大小,一点儿不考虑guest的感受,不惜杀死进程来满足宿主机的请求,下面是逐步balloon的过程:
参考资料:
https://www.linux-kvm.org/page/Projects/auto-ballooning 这里有提到选项automatic=true
环境:
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 |
# docker info Containers: 56 Running: 33 Paused: 0 Stopped: 23 Images: 31 Server Version: 1.12.5 Storage Driver: devicemapper Pool Name: data-docker_thinpool Pool Blocksize: 524.3 kB Base Device Size: 32.21 GB Backing Filesystem: xfs Data file: Metadata file: Data Space Used: 516.2 GB Data Space Total: 644.2 GB Data Space Available: 128.1 GB Metadata Space Used: 45.47 MB Metadata Space Total: 16.98 GB Metadata Space Available: 16.93 GB Thin Pool Minimum Free Space: 64.42 GB Udev Sync Supported: true Deferred Removal Enabled: true Deferred Deletion Enabled: false Deferred Deleted Device Count: 0 Library Version: 1.02.135-RHEL7 (2016-11-16) Logging Driver: journald Cgroup Driver: cgroupfs Plugins: Volume: local Network: host bridge null overlay Swarm: inactive Runtimes: runc docker-runc Default Runtime: runc Security Options: seccomp Kernel Version: 3.10.0-514.6.1.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 Number of Docker Hooks: 2 CPUs: 40 Total Memory: 94.14 GiB Name: VM-2-10-12 ID: NYBE:NZML:4KQQ:PF2J:RXCB:IPPI:Y3BI:CY7E:RVAC:WVWV:VDM2:3EEK Docker Root Dir: /data1/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Insecure Registries: docker-registry.i.bbtfax.com:5000 127.0.0.0/8 Registries: docker.io (secure) |
现象:
1 2 |
# docker exec -it c6176f37c4b6 bash rpc error: code = 13 desc = invalid header field value "oci runtime error: exec failed: container_linux.go:247: starting container process caused \"process_linux.go:75: starting setns process caused \\\"fork/exec /proc/self/exe: no such file or directory\\\"\"\n" |
乍一看, /proc/self/exe 文件找不见?
一般来讲,文件找不见并不奇怪,怪就怪在是 /proc/self/exe 找不见就不太应该了;
因为docker exec 最终是由libcontainerd进程来出来的,strace跟进发现,是chdir到 /root/data1/docker/devicemapper/mnt/4723e8178992b32b7284aa48c1c62f4011a6b785aca0c54e18d7ce5cc23b22dc/rootfs 时,找不到目标目录导致的,于是我就迅速地看了一下,该目录确实不存在,但是对于正常的能够exec的容器来讲,相应的rootfs目录也是不存在的
思考中。。。
docker玩的就是名字空间和cgroup,所以不能不想到这些;libcontainerd也有自己的(mnt)名字空间,我们进入libcontainerd进程的文件系统就可以查看到上面目录的存在了,而且,正常的容器存在相应的目录,异常的容器不存在相应的目录;
通过mount命令可以发现mount的规律,从容器的config.json (/var/run/docker/libcontainerd/c6176f37c4b67b03d4187edef6d1131cd44ab80bd0f0c20b24a7a20056967652/config.json) 中查看到对应的mount的位置,通过nsenter进入libcontainerd的mnt名字空间手动mount上去就好了,如下:
1 2 |
# nsenter -m -t 3639 bash # mount /dev/mapper/docker-253\:3-3221225568-4723e8178992b32b7284aa48c1c62f4011a6b785aca0c54e18d7ce5cc23b22dc -o rw,relatime,nouuid,attr2,inode64,sunit=512,swidth=1024,noquota -t xfs /data1/docker/devicemapper/mnt/4723e8178992b32b7284aa48c1c62f4011a6b785aca0c54e18d7ce5cc23b22dc |
写个脚本自动修复之:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#!/bin/bash # author: phpor # LIBCONTAINERD_DIR=/var/run/docker/libcontainerd function main() { local pidOfCotainerd=$(pidof docker-containerd-current) local mountinfo=$(< /proc/$pidOfCotainerd/mountinfo) for config in $LIBCONTAINERD_DIR/*/config.json;do local cid=$(awk -F'/' '{print $6}' <<<$config) local rootpath=$(jq -r .root.path $config|sed 's/\/rootfs$//') grep "$rootpath" <<<$mountinfo >/dev/null if [[ $? -eq 0 ]]; then echo $cid $rootpath OK else echo $cid $rootpath Should repair local device=/dev/mapper/$(docker inspect $cid|jq -r .[0].GraphDriver.Data.DeviceName) nsenter -m -p -t $pidOfCotainerd mount -t xfs -o rw,nouuid,attr2,inode64,sunit=512,swidth=1024,noquota $device $rootpath fi done } main |
那么该mount点是如何丢掉的呢?重启dockerd能否自动修复该问题呢?(应该重启一下容器就行)稍后再研究