1. 存储问题
1.1 挂载目录权限问题
- 在使用swarm创建服务的时候要挂载存储来获取运行文件,及写日志出去。
- 可运行文件相当于在集群中所有地方应该都能访问到,所以使用了NFS文件系统,在集群中所有机器上都挂载
- 写日志出去,挂载一个可读可写的目录,在容器内部生成日志目录结构。
- 但是发现打出来的日志权限都是root:root,其他用户可能无法查看,故查看挂载设置。挂载设置上唯有RW相关,比的都不相干
"Mounts": [
{
"Type": "bind",
"Source": "/data/service/0_yztest_0-0-4",
"Destination": "/home/service/0_yztest_0-0-4",
"Mode": "",
"RW": false,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/log/container",
"Destination": "/home/service/0_yztest_0-0-4/log",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
- 发现容器内是root运行的,导致创建的文件是root:root。发现在运行容器或服务的时候可以指定运行用户,但是发现该用户指的是容器内部镜像的用户,如果用宿主机用户,会报错。参考:https://github.com/moby/moby/issues/22323
[container]$ docker run --help | grep user
-u, --user string Username or UID (format: <name|uid>[:<group|gid>])
--userns string User namespace to use
[container]$ docker service create --help | grep user
--group list Set one or more supplementary user groups for the container
-u, --user string Username or UID (format: <name|uid>[:<group|gid>])
在运行服务的时候如果指定宿主机用户和用户组,而容器内部又没有该用户的时候会报错:
"starting container failed: linux spec user: unable to find user cloud: no matching entries in passwd file"
- 只能尝试容器内部使用的log4j框架写日志的时候修改格式了。
- 参考:解决log4j.properties配置文件生成的log日志文件读写权限问题
- 而要想对文件权限修改,框架版本当前太低又不支持(T_T),filePermissions只有在2.9以上的版本才有,参考:log4j2设置日志文件读写权限(filePermissions)
1.2 容器启动失败read-only file system错误
- 容器启动报错如下,奇怪的是基本一样的服务,有些能成功,有些却报错失败了。而且看不出来规律。
- 容器启动不成功,报错:read-only file system。以多个关键字搜索都无果。最后没办法把挂载的volume改成了可读可写,可以启动成功了。
time="2018-04-18T10:25:06.513315356+08:00" level=error msg="fatal task error" error="starting container failed: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused \"rootfs_linux.go:58: mounting \\\"/data/docker/volumes/log-724_5703.0.11416.1523967154/_data\\\" to rootfs \\\"/data/docker/overlay2/39f5cf87ad44b70665f4ebbd30be797606b281e47bf86aadece71b1c1f4290d0/merged\\\" at \\\"/data/docker/overlay2/39f5cf87ad44b70665f4ebbd30be797606b281e47bf86aadece71b1c1f4290d0/merged/home/service/0_test_0-0-10/log\\\" caused \\\"mkdir /data/docker/overlay2/39f5cf87ad44b70665f4ebbd30be797606b281e47bf86aadece71b1c1f4290d0/merged/home/service/0_test_0-0-10/log: read-only file system\\\"\"": unknown" module=node/agent/taskmanager node.id=21grc3cvehywhuz9paqqcv7hr service.id=6aop0ts679fva758dattmlxjt task.id=mni2i8crkj6ijg72jgh17xt5i
2. 网络问题
- 背景:容器启动不成功,容器没有状态,docker start 容器的时候报错提示:Cannot start container exit status 1,FATA[0000] Error: failed to start one or more containers,docker "ExitCode": 128。在docker daemon的日志里有: Failed to allocate and map port: iptables failed: iptables -t nat -A DOCKER -p tcp -d 0/0 --dport 54052 ! -i docker0 -j DNAT --to-destination 192.168.42.70:14129: iptables: No chain/target/match by that name.错误。
- 原因:暴露端口的时候需要iptables的规则链做转发,但是放假前改动了那个规则链没了。所以容器创建处理不能启动,不能暴露端口了,所以启动不成功。
- 正常情况下,docker在bridge网络模式下暴露端口的时候会在iptables的规则链上做转发,如下:
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 192.168.42.2 tcp dpt:14129
ACCEPT tcp -- anywhere 192.168.42.3 tcp dpt:14129
ACCEPT tcp -- anywhere 192.168.42.4 tcp dpt:14129
ACCEPT tcp -- anywhere 192.168.42.5 tcp dpt:14129
ACCEPT tcp -- anywhere 192.168.42.6 tcp dpt:14129
ACCEPT tcp -- anywhere 192.168.42.7 tcp dpt:14129
-
如果iptables规则链修改了,没有了名为DOCKER的链,就会出现上面的问题。
-
原理:
-
docker 服务启动的时候,docker服务会向iptables注册一个链,以便让docker服务管理的containner所暴露的端口之间进行通信。通过命令iptables -L可以查看iptables 链。
-
在开发环境中,如果你删除了iptables中的docker链,或者iptables的规则被丢失了(例如重启firewalld),docker就会报iptables error例如:failed programming external connectivity … iptables: No chain/target/match by that name
-
要解决这个问题,只要重启docker服务,之后,正确的iptables规则就会被创建出来