先日久々に起動したSwarm環境が何やらおかしいということで調べてみると、証明書切れによりSwarmが構成されていない状態になっていました。実はこの辺りの詳細な仕組みを理解していないなと思い、自分の理解のためにも、これを機に少し調べたのでまとめてみました。
検証環境
今回の検証環境については下記の通りです。
- OS: Linux (CentOS7)
- docker: docker-ce 20.10.5
検証
Swarmを構成
構成手順については割愛します。証明書関係は/var/lib/docker/swarm/certificates
配下に作成されます。証明書のデフォルトの有効期間は2160h0m0s
、つまり90日間です。
期限を短くして基本動作確認
基本動作を確認するため、証明書の有効期限を下記のコマンドで短くし、再生成してみます。
# docker swarm update --cert-expiry 1h
# docker swarm ca --rotate
# openssl x509 -text -noout -in /var/lib/docker/swarm/certificates/swarm-node.crt | grep Not
Not Before: Jan 18 00:08:00 2022 GMT
Not After : Jan 18 02:08:00 2022 GMT
これを少し待つと、、、
# openssl x509 -text -noout -in /var/lib/docker/swarm/certificates/swarm-node.crt | grep Not
Not Before: Jan 18 00:38:00 2022 GMT
Not After : Jan 18 02:38:00 2022 GMT
の通り自動で更新されているのが確認できます。ログとしてはこんな感じです。
1月 17 20:38:00 swarm1 dockerd[14932]: time="2022-01-17T20:38:00.000127970-05:00" level=info msg="renewing certificate" module=node/tls node.id=a5v3geh16xvqejhirx3bb2586 node.role=swarm-manager
自動更新のタイミングは「Random retry time between 50% and 80% of the total time to expiration」となっており、Not BeforeとNot Afterをベースに算出されます。例えば、今回の例ですと、Jan 18 01:08:00 2022 GMT
からJan 18 01:44:00 2022 GMT
の間で実行されることになります。コードとしてはこのあたりを参照ください。
エラーの再現
最初の話に戻り、今回落ち入った事象を再現させるためにdockerを一時的に落として、再度起動してみます。起動時は証明書が失効するまで待つか、時間を調整してください。docker info
を実行すると下記のようにエラーが出るのが確認できます。
Swarm: error
NodeID:
Error: error while loading TLS certificate in /var/lib/docker/swarm/certificates/swarm-node.crt: certificate (1 - a5v3geh16xvqejhirx3bb2586) not valid after Tue, 18 Jan 2022 04:31:00 UTC, and it is currently Tue, 18 Jan 2022 22:00:08 EST: x509: certificate has expired or is not yet valid
こうなるとmanagerであってもrotateしようにも下記の通りのエラーになります。
# docker swarm ca --rotate
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.
復旧方法
復旧手順としては
- すべてのノードの時間を証明書の有効期限内に変更
- dockerの再起動でSwarmが再構成されていることを確認
-
docker swarm ca --rotate --cert-expiry <duration>
を実行し、現在時刻でも有効となるように証明書の有効期限を延長 - すべてのノードの時間を現在時刻に修正
となります。もしくは、許されるならばSwarm再構成です。
最後に
今回の話はそもそも長期間運用していれば自動で更新してくれるため、あまり気にしなくても良いですが、検証環境等で久々に起動した際に同じ事象を観測した人の助けに少しでもなればなと思います。