入門DCOS,剛開始安裝,碰到了一個異常:
Bind for 0.0.0.0:9000 failed: port is already allocated.
調試這個問題花費了好長時間,因為無法通過netstat以及lsof看到究竟是什么應用占用了程序;后來我才發現原來是因為docker的原因;如果docker被run了兩次
docker run -it -p 9000:80 mesosphere/dcos-genconf:d932fc405eb80d8e5b-b7c22f7cfb481d9f95 /bin/bash
第一次失敗,那么這個端口將會被一直占用,即使docker容器並沒有創建並沒有。解決辦法就是重啟docker服務:
service docker restart
(也有人說要sudo rm /var/lib/docker/network/files/local-kv.db,但是在我看來並不需要)
這個是docker里面的bug,看到這個issue在論壇里面討論的熱火朝天,但是這是2014年的事了。
再回過頭來,那么既然是run兩次失敗會爆這個異常,那么,docker run失敗原因是什么呢?
exec: "docker-proxy": executable file not found in $PATH.
這個異常的原因是docker啟動后將會執行docker-proxy指令,但是在shell中加載的$PATH中無法找到對應的指令。與之類似是docker-runc無法找到,這個原因是在/usr/libexec/docker下面,在安裝的時候可能因為沒有完全安裝導致的兩個link沒有安裝上,用如下方法進行修補:
1 cd /usr/libexec/docker/ 2 sudo ln -s docker-proxy-current /usr/bin/docker-proxy
daocker執行應該首先回到/usr/libexec/docker下面找執行文件,沒有,再到$PATH定義的路徑下找,再沒有,則報錯。
另外,當發生以下異常:
/usr/bin/docker-current: Error response from daemon: shim error: docker-runc not installed on system.
也是需要創建軟連接方式來解決:
sudo ln -s docker-runc-current /usr/bin/docker-runc
prestart hook 1 caused \\\"error running hook: exit status 1
這個問題如果這樣貼出來,是沒有意義的,想要看更加詳細的錯誤信息:
1 service docker status -l 2 journalctl -xe
這樣結合起來可以看到更加詳細的信息。
看到的錯誤信息:Failed to open file '/sys/class/net/vethf6a3cb0/operstate'
vethXXX應該是docker內部的網絡接口的名稱;初步推測應該是因為某個異常導致的docker內部的網卡沒有啟動起來。
在調查的過程中發現了一個命令:brctl show,用來顯示網橋,其實docker默認的網橋是docker0(docker0並不是一個網絡接口,而是一個網橋)。
至於如何來創建網橋
https://docs.docker.com/engine/userguide/networking/default_network/build-bridges/
以及相關docker的文檔:
https://docs.docker.com/v1.7/articles/networking/
https://forums.docker.com/t/relationship-between-interface-vethxxxxx-and-container/12872/22
后來深入跟蹤這個問題,發現其實是因為不知道什么原因會增加一個override.conf,這個override.conf將storage-driver設置成了overlay(難道是因為設docker_proxy?),至於發現這個的過程是這樣的,比較docker info的差異,發現有問題的機器采用的是overlay的方式,OK機器采用的是devicemapper的方式;然后我又嘗試修改為devicemapper,方式就是在/etc/docker/daemon.json文件中寫入
{"storage-driver": "devicemapper"}
但是啟動docker的時候爆了一個異常:
unable to configure the Docker daemon with file /etc/docker/daemon.json: the following directives are specified both as a flag and in the configuration file: storage-driver: (from flag: overlay, from file: devicemapper)\n"
這里關於option我還想了半天,最后是懷疑是啟動docker服務的時候應該指定了storage-driver參數,和我在配置文件中的沖突了。我還手動啟動了一下dockerd --storage-drive=devicemapper,在docker run dcos的image沒有問題。
然后我使用了service docker status,來查看docer服務的詳細內容,才發現status里面包含了非常豐富的內容,之前只是記得會顯示執行的指令以及參數選項(option)
1 Redirecting to /bin/systemctl status docker.service 2 ● docker.service - Docker Application Container Engine 3 Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled) 4 Drop-In: /etc/systemd/system/docker.service.d 5 └─override.conf 6 Active: activating (auto-restart) (Result: exit-code) since Sat 2017-11-11 22:28:38 CST; 2s ago 7 Docs: http://docs.docker.com 8 Process: 31055 ExecStart=/usr/bin/dockerd --storage-driver=overlay (code=exited, status=1/FAILURE) 9 Process: 31050 ExecStartPre=/sbin/ip link del docker0 (code=exited, status=0/SUCCESS) 10 Main PID: 31055 (code=exited, status=1/FAILURE)
注意加粗三句話,所有的問題都是通過三句話來解開的:
第一句話是說明服務啟動的文件,我進去看了,發現里面的storage-driver的配置文件里面默認配置的就是devicemapper。這個過程稍微有點復雜:/usr/lib/systemd/system/docker.service里面指定了storage的配置文件(/etc/sysconfig/docker-storage),需要查看storage的配置文件,但是呢這個配置文件還是多重繼承的意思,總是最后根上是/usr/share/container-storage-setup/container-storage-setup文件,打開一看:STORAGE_DRIVER=devicemapper,這說明默認就是devicemapper的方式,那么為什么通過docker info看到的方式是overlay呢?
第二句話是說明配置項已經被覆蓋了,覆蓋的配置文件是 /etc/systemd/system/docker.service.d/override.conf,里面內容是:
1 art=always 2 StartLimitInterval=0 3 RestartSec=15 4 ExecStartPre=-/sbin/ip link del docker0 5 ExecStart= 6 ExecStart=/usr/bin/dockerd --storage-driver=overlay
第三句話(還有下面的process語句)是真正的執行的指令和參數,其實就是override.conf里面定義的內容。
看到這里我明白了,原來docker的啟動過程被覆蓋了。於是我將override.conf文件重命名了,然后重啟docker服務,爆了提示:
Warning: docker.service changed on disk. Run 'systemctl daemon-reload' to reload units.
daemon-reload是指重新加載服務的核心配置文件,即單元文件(里面定義了服務以來單元以及服務定義),這里因為我已經把服務的單元文件給刪掉了,所以需要重新加載配置文件(看來linux是把單元文件加載到內存中,每次重啟服務並不重新讀取單元文件)。重啟之后,搞定了。
再看service docker status:
1 Redirecting to /bin/systemctl status -l docker.service 2 ● docker.service - Docker Application Container Engine 3 Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled) 4 Active: active (running) since Sat 2017-11-11 22:37:20 CST; 19s ago 5 Docs: http://docs.docker.com 6 Main PID: 34181 (dockerd-current) 7 CGroup: /system.slice/docker.service 8 ├─34181 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --selinux-enabled --log-driver=journald --signature-verification=false 9 └─34186 /usr/bin/docker-containerd-current -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shim docker-containerd-shim --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --runtime docker-runc --runtime-args --systemd-cgroup=true
別問我為什么會有override.conf,我也不知道他是怎么出現的。
但是如果提到了override.conf,則需要提到了systemd,其實systemd是Linux的一組基礎組建的工具集合(替代centos之前的initd),用於啟動守護進程,監控服務等一系列操作系統的基礎功能。
服務(屬於單元的一種)一般是打包安裝,為了不需要修改打包原生的配置文件,systemd提供了一種可以在外部覆蓋原生配置文件的方式,這種就是:
systemctl edit unit
修改之后,就會生成/etc/systemd/system/unit.d/override.conf(unit.d在我們這里就是docker.service.d)
后來,安裝dcos熟練了,才知道,這是因為dcos在安裝的時候會把master以及agent節點都配置為overlay,而修改配置侵入最小的方式就是采用override.conf的方式。我之前的問題就是在於把boot節點(setup節點)同時作為了master節點,所以有此問題。