Hateburo: kazeburo hatenablog

SRE / 運用系小姑 / Goを書くPerl Monger

resolv.conf におけるDNS名前解決のタイムアウト

resolv.confに記述したDNSサーバへの名前解決のタイムアウトとリトライ回数について改めて確認したので忘備録

CentOS7系およびRocky Linux 9系で確認しています。

/etc/resolv.confDNSサーバが次のように指定されている場合、

nameserver 198.51.100.3
nameserver 198.51.100.4

以下の順で利用されます。

  1. 198.51.100.3タイムアウト 5秒
  2. 198.51.100.45秒 ✖️ 2 ➗ サーバ台数 (小数点切り捨て)のタイムアウト=5 秒

これを2回繰り返し、両方接続不可能な場合、合計20秒間名前解決しようとします。

3台ある場合、

nameserver 198.51.100.3
nameserver 198.51.100.4
nameserver 198.51.100.5
  1. 198.51.100.3タイムアウト 5秒
  2. 198.51.100.45秒 x 2 ➗ サーバ台数 (小数点切り捨て)のタイムアウト=3 秒
  3. 198.51.100.52. の倍のタイムアウト=6秒

これを2回繰り返し、5秒→3秒→6秒を2回の28秒間試行します。

3台以上DNSサーバがある場合は、4台目以降は無視されます。

タイムアウトoptions timeout:N 、試行回数は options attempts:M 指定できます。それぞれ一般的なデフォルトは 5秒2回 となります。

タイムアウトを短くして試行回数を増やすのであれば、次のようにするのが良さそうです。

nameserver 198.51.100.3
nameserver 198.51.100.4
options timeout:1 attempts:3

デフォルト5秒はWebサーバ用途では長すぎるかもしれません。

また、ubuntu 22.04などでは systemd-resolvedが動作しています。こちらではローカルでキャッシュをもっていたり、接続できないDNSサーバにしばらくのアクセスをしない機能があるようです。

straceで確認

2台の場合

11:56:02.580141 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 4
11:56:02.580190 setsockopt(4, SOL_IP, IP_RECVERR, [1], 4) = 0
11:56:02.580237 connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.3")}, 16) = 0
11:56:02.580294 poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
11:56:02.580337 sendto(4, "tC\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
11:56:02.580428 poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
11:56:07.585638 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 5
11:56:07.585726 setsockopt(5, SOL_IP, IP_RECVERR, [1], 4) = 0
11:56:07.585766 connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.4")}, 16) = 0
11:56:07.585807 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
11:56:07.585837 sendto(5, "tC\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
11:56:07.585924 poll([{fd=5, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
11:56:12.591058 poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
11:56:12.591182 sendto(4, "tC\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
11:56:12.591282 poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
11:56:17.596483 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
11:56:17.596563 sendto(5, "tC\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
11:56:17.596629 poll([{fd=5, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
11:56:22.601778 close(4)                = 0
11:56:22.601824 close(5)                = 0

3台の場合

12:14:57.572565 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 4
12:14:57.572597 setsockopt(4, SOL_IP, IP_RECVERR, [1], 4) = 0
12:14:57.572626 connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.3")}, 16) = 0
12:14:57.572682 poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
12:14:57.572731 sendto(4, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:14:57.572795 poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
12:15:02.577947 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 5
12:15:02.578009 setsockopt(5, SOL_IP, IP_RECVERR, [1], 4) = 0
12:15:02.578045 connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.4")}, 16) = 0
12:15:02.578101 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
12:15:02.578138 sendto(5, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:02.578216 poll([{fd=5, events=POLLIN}], 1, 3000) = 0 (Timeout)
# 3秒
12:15:05.581337 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 6
12:15:05.581406 setsockopt(6, SOL_IP, IP_RECVERR, [1], 4) = 0
12:15:05.581443 connect(6, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("198.51.100.5")}, 16) = 0
12:15:05.581484 poll([{fd=6, events=POLLOUT}], 1, 0) = 1 ([{fd=6, revents=POLLOUT}])
12:15:05.581512 sendto(6, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:05.581568 poll([{fd=6, events=POLLIN}], 1, 6000) = 0 (Timeout)
# 6秒
12:15:11.587696 poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
12:15:11.587759 sendto(4, "\366\237\1\0\0\1\0\0\0\0\0\0\6sakura\2ad\2jp\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:11.587830 poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
# 5秒
12:15:16.592954 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}])
12:15:16.593015 sendto(5, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:16.593077 poll([{fd=5, events=POLLIN}], 1, 3000) = 0 (Timeout)
# 3秒
12:15:19.596238 poll([{fd=6, events=POLLOUT}], 1, 0) = 1 ([{fd=6, revents=POLLOUT}])
12:15:19.596327 sendto(6, "\366\237\1\0\0\1\0\0\0\0\0\0\6example\2com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
12:15:19.596422 poll([{fd=6, events=POLLIN}], 1, 6000) = 0 (Timeout)
# 5秒
12:15:25.602566 close(4)                = 0
12:15:25.602637 close(5)                = 0
12:15:25.602668 close(6)                = 0

「さくらのクラウドシェル」でWebサーバを起動する(ngrok編)

さくらインターネットから新しいサービス、「さくらのクラウドシェル」がリリースされました。 ブラウザからワンクリックで利用できるオンラインのシェル環境が起動できます。無料で使えます!!

こちら無料で試すボタンを押すと、次のモーダルが現れます。

ここで「会員IDで利用する」を選んだ場合、アウトバウンド向けの各ポート(22/53/80/443/1024-65535)の通信が利用できます。会員IDでログインしない場合は通信ができない環境が起動します。

ボタンを押すとすぐにシェルが立ち上がります。

フォントや文字色、背景画像が選べたりします。

シェルとしてはZSHが起動し、Go、PythonRuby、Node.js などの開発言語のほかに、VimEmacs、tmux、Git、Ansible、Terraform、さくらのクラウドコマンドラインから操作できる usacloud があらかじめ導入されています。

さくらのクラウドシェルでWebサーバを起動する

さくらのクラウドシェルは外から通信を受けることはできないので、ちょっとしたツールを試したりすることはできますが、Webサーバなどサーバとして利用することは通常できません。 そこで、Ngrokというトンネルサービスを使用して、Webサーバを起動してみます。

ngrok.com

ソースコードgistにおきました。

gist.github.com

このコードではGo言語とNgrokのライブラリを使っています。

ngrok.com

クラウドシェルを起動後、

sakura@cloud-shell% mkdir server
sakura@cloud-shell% cd server
sakura@cloud-shell% curl -LO https://gist.githubusercontent.com/kazeburo/795c8602e26aca66301e0142bcc024ea/raw/b9b22dbb4b23d38d37e59dadceeec418d69ed499/main.go
sakura@cloud-shell% go mod init server
sakura@cloud-shell% go mod tidy
sakura@cloud-shell% go run main.go

でサーバが起動します。

表示されたURLがクリッカブルになっている(便利!)なのでクリックして動作確認ができます。

さくらのクラウドシェルでは20分操作しないと自動終了されるので、Webサーバも20分で終了します。はい。

dnsdist のパフォーマンスを引き出すネットワーク設定

YAPC::Kyoto 2023、JANOG51 MeetingではDNSへの水責めの攻撃とその対策について話をさせていただきました。その中で DNS攻撃をフィルタリングするために利用している dnsdist についてチューニングにより大きくパフォーマンス向上できることがわかってきたので紹介します。

YAPCの記事 kazeburo.hatenablog.com

JANOG51 Meetingについての記事 knowledge.sakura.ad.jp

Linuxのネットワークパラメータのチューニング

Linuxのチューニングでよくある設定ですが、sysctl.conf で以下のカーネルパラメータをチューニングをします。

net.core.somaxconn = 65535
net.core.netdev_max_backlog = 16384
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728

ここでは rmem_maxwmem_max だけを設定しています。 net.core.rmem_defaultnet.core.wmem_default については後述します。

dnsdistのチューニング

listenするスレッド数を増やす

dnsdistでは addLocal を増やすことでlistenerスレッドの数を増やせます。

addLocal("0.0.0.0:53", {reusePort=true})
addLocal("0.0.0.0:53", {reusePort=true})
addLocal("0.0.0.0:53", {reusePort=true})
addLocal("0.0.0.0:53", {reusePort=true})

この際に reusePort を有効にするとそれぞれのスレッドにListen Queueが分散されるので高速化が見込めます。

また、CPU affinityを固定するのも良いでしょう

addLocal("0.0.0.0:53", {reusePort=true,cpus={0}})
addLocal("0.0.0.0:53", {reusePort=true,cpus={1}})
addLocal("0.0.0.0:53", {reusePort=true,cpus={2}})
addLocal("0.0.0.0:53", {reusePort=true,cpus={3}})

さらにTCPの接続が多い場合、キューのサイズを増やしておくと良いかもしれません

addLocal("0.0.0.0:53", {reusePort=true,cpus={0},tcpListenQueueSize=4096})
addLocal("0.0.0.0:53", {reusePort=true,cpus={1},tcpListenQueueSize=4096})
addLocal("0.0.0.0:53", {reusePort=true,cpus={2},tcpListenQueueSize=4096})
addLocal("0.0.0.0:53", {reusePort=true,cpus={3},tcpListenQueueSize=4096})

UDPのバッファサイズの調整

UDPの読み書きのバッファのサイズを大きくします。デフォルトはカーネルパラメータの net.core.rmem_defaultnet.core.wmem_default になります。なのでsysctlで設定することもできます。

setUDPSocketBufferSizes(8388608,8388608)

カーネルパラメータの net.core.rmem_maxnet.core.wmem_maxが設定できる最大値となります。

複数のUDPによるクエリを1度のシステムコールで読み込む

recvmmsg(2) を使うことで1度のシステムコールで複数のUDPによるクエリを読み込むことができます。 setUDPMultipleMessagesVectorSize はその最大個数を指定します。

setUDPMultipleMessagesVectorSize(100)

デフォルトは1で、通常の recvmsg(2) を使います。

ベンチマークの効果

さくらのクラウドの8コアの仮想サーバにて自作のDNS水責めベンチマークツールを使い検証を行いました。

dnsdistのみの検証のため、設定に

addAction(
  AllRule(),
  RCodeAction(DNSRCode.REFUSED)
)

を設定し、すべてのクエリに即時 REFUSED を返すように設定してあります。

初期状態

Listenerスレッドが1個の状態です。

# GOGC=500 ./prsd-bench4 -P 53 -H 192.168.10.50 --max-workers 1000 --max-length 8 --label 1 --zone example.com 2> /dev/null
2023-05-24 16:09:52.842209747 +0900 JST m=+10.002875416 resolved: 0.000000 query/sec, refused 231067.300000 query/sec, failed 72.200000 query/sec
2023-05-24 16:10:02.842144106 +0900 JST m=+20.002809775 resolved: 0.000000 query/sec, refused 220423.400000 query/sec, failed 144.400000 query/sec
2023-05-24 16:10:12.842143685 +0900 JST m=+30.002809354 resolved: 0.000000 query/sec, refused 230264.600000 query/sec, failed 144.400000 query/sec
2023-05-24 16:10:22.84215706 +0900 JST m=+40.002822729 resolved: 0.000000 query/sec, refused 220053.900000 query/sec, failed 144.400000 query/sec
2023-05-24 16:10:32.842160142 +0900 JST m=+50.002825810 resolved: 0.000000 query/sec, refused 227706.300000 query/sec, failed 144.400000 query/sec
2023-05-24 16:10:42.840047568 +0900 JST m=+60.000713237 resolved: 0.000000 query/sec, refused 232174.600000 query/sec, failed 144.400000 query/sec

20万qps以上は出ていますが、エラーもちらほらあります。

チューニング後

listenerスレッドを仮想コア数と同じ8個として、紹介したチューニングを全て入れている状態です。

# GOGC=500 ./prsd-bench4 -P 53 -H 192.168.10.50 --max-workers 1000 --max-length 8 --label 1 --zone example.com 2> /dev/null
2023-05-24 16:21:29.396835468 +0900 JST m=+10.001673734 resolved: 0.000000 query/sec, refused 417461.100000 query/sec, failed 0.000000 query/sec
2023-05-24 16:21:39.396746836 +0900 JST m=+20.001585106 resolved: 0.000000 query/sec, refused 445043.800000 query/sec, failed 0.000000 query/sec
2023-05-24 16:21:49.396666734 +0900 JST m=+30.001505003 resolved: 0.000000 query/sec, refused 431644.600000 query/sec, failed 0.000000 query/sec
2023-05-24 16:21:59.396818157 +0900 JST m=+40.001656423 resolved: 0.000000 query/sec, refused 438897.200000 query/sec, failed 0.000000 query/sec
2023-05-24 16:22:09.396665403 +0900 JST m=+50.001503669 resolved: 0.000000 query/sec, refused 440108.300000 query/sec, failed 0.000000 query/sec
2023-05-24 16:22:19.395664578 +0900 JST m=+60.000502848 resolved: 0.000000 query/sec, refused 425201.300000 query/sec, failed 0.000000 query/sec

エラーなく40万qps以上処理できるようになりました。

まとめ

権威DNSサーバであるNSDでは、UDPのバッファサイズ、recvmmsgの利用などはデフォルトで行われており、dnsdistパフォーマンスの調査をするにあたり参考にしました。

www.nlnetlabs.nl

この記事がDNSサーバのパフォーマンスで困った際にお役に立てれば幸いです。

YAPC::Kyoto 2023でDNS水責め攻撃とGoによるベンチマーカの発表をしてきました #yapcjapan

YAPC::Kyoto 2023 に参加してきました!

数年ぶりに開かれたYAPCで、数年ぶりに会うエンジニアの同窓会みたいな雰囲気ありつつ、新しい参加者も多く最高でした。オフラインイベント楽しいです。スタッフの皆様ありがとうございました!! 京都まで行かせてくれた家族にも感謝

会場のKRPは2006年まで働いていた場所で、17年も経ってそこで発表する機会をいただいたのは個人的に感慨深いものがあります。はてなの大西さんの発表は自分にとってもとても懐かしく聞いておりました。

発表してきた

私の発表はこちら

speakerdeck.com

DNS水責め攻撃とその対策については1月に開催されたJANOG51 Meeting in 富士吉田でも紹介しております。発表について記事にしていただいているので詳しくはこちらを。

knowledge.sakura.ad.jp

YAPC::Kyotoではここから派生して、Goによるベンチマーカ作りと高速なベンチマーカをつくるためのチューニングポイントを紹介しています。ベンチマークをとる、プロファイルを行うなども簡単ですが詰め込んでいます。ベンチマーカ自体のコードは公開していませんが、この資料が何かの参考になれば幸いです。

資料中に出てくるISUCON本はこちら

Go言語のベンチマークやプロファイリングについては mattn さんが書かれた「Go言語プログラミングエッセンス」がわかりやすくおすすめです。参考にさせていただきました。

オフラインイベントの体験をもっとたくさんのエンジニアに

いやぁ、ほんと行ってよかった。

この体験をたくさんのエンジニアに、特にコロナ禍で一度も経験していない若いエンジニアに味わって欲しい。YAPCは次回広島開催の話もあるし、他のカンファレンスでもオフライン増えてきているので積極的に参加するよう背中を押していきたい。そのためさくらインターネットや自分がお手伝いできることがあればお声がけいただけると嬉しいです。

YAPC::Kyoto 2023で話します! そしてチケットを今すぐに購入しましょう!!

YAPC::Kyoto 2023の採択トークが決まったようですね。面白そうなトークが沢山あってすごいですね。

blog.yapcjapan.org

私のトークも採択されました。ありがとうございます。ありがとうございます!!

こういう話をします。

クラウドファースト、クラウドバイデフォルトなどと言われるようにクラウドサービス前提にシステムの構築運用がなっています。インターネットにおける重要な基盤技術のひとつであるDNSにおいてもクラウドサービスが使われるようになっています。

トークでは、さくらのクラウドDNSアプライアンスサービスに行われたDNS水責め攻撃と呼ばれるDDoS攻撃の内容およびその対策について紹介します。また、対策にあたって作成したDNSサーバへ負荷をかけるベンチマーカを題材にハイパフォーマンスなベンチマーカを作る上で必要な要素も紹介します。

アジェンダ
* さくらのクラウド DNSアプライアンスとは(Perlも使っているよ)
* DNS水責め攻撃とその実際
* GoによるハイパフォーマンスなDNSのベンチマーカ作成

この話は、JANOG51 Meetingにて発表して内容に関連しているものとなります。資料の公開もしていますので、ぜひご覧ください。

speakerdeck.com

発表のアーカイブ動画もこちらで公開されています。

www.janog.gr.jp

チケットを買ってくれ

それはそうとして、そんなYAPC::Kyoto 2023ですがチケット販売が今月1月の31日までとなっています。

passmarket.yahoo.co.jp

今月中にチケットを買わないと参加ができないのです! 今、まさにこの瞬間、すぐに買いましょう!!!!! 豪華ノベルティがついてくる個人スポンサーチケットは残席わずかとのこと!!

買いましたか?買いましたね。それでは会場でお会いいたしましょう!

yapcjapan.org

今回会場となる、京都リサーチパークは以前働いていた場所で、そちらに久しぶりに行って、エンジニア仲間と会い、またしゃべれる機会があるということで非常に楽しみにしております。YAPC::Kyoto今からワクワクが止まりません!!

オマージュ元

tamamemo.hatenablog.com

買ってよかった2022

年末恒例

kazeburo.hatenablog.com

テレビ前に置くスピーカーを買った

www.sonos.com

Apple AirPlay 2対応でBluetoothのような煩雑なことがなく、すぐに音楽を鳴らせるし、音にも満足。

Dolby Atmos対応になったので、2本(?)ほど4K ULTRA HD Blu-rayを買った。

ロード・オブ・ザ・リングの方は劇場版とスペシャル・エクステンデッド・エディションのHDと4Kあわせて18枚セット。当然まだ全部みきれてない。

次はサブウーファーが欲しいな。Sonos Sub Miniかわいい。いつかのMac Proみたい。

ランニンググッズ

走るのは無料だと言ったな。あれは嘘だ。

前半は On の CloudMonster を履いていた。

www.on-running.com

何種類も履き比べてないのですが、地面に足を着いた時の安定性があった。今は普段履きとして使ってる。

後半はasicsのGlideRide 3。みなとみらいのスポーツゼビオで足の形を測ってお勧めされた中から選んだ。

www.asics.com

足の運びはこちらの方がスムーズで走り方に合ってる気がする。

去年買った走る時のポーチもだいぶボロボロになってきたので新しくした。YURENIKUIのベルトタイプ。

yurenikui.jp

体を挟むような形状になっていて安定しやすい。いつもは前に鍵、後ろにスマホをいれてます。

あと膝が痛くなることがあり、サポーターを買ってみた

タイツタイプと

膝サポーター

どちらも走るのが楽になってとてもよかった。

ただ、無理はよくない。1-2月、10月あたりは膝が痛く走るのをやめてウォーキングなどに切り替えていた。

12月はここまで133km程度。

体重も減ってる。

1月にハーフマラソン挑戦なのでがんばるぞー

hitech-half-marathon.net

今年つくったSRE室でチーム開発の体制もよくしていくための取り組みを開始している。そのひとつとして、「LeanとDevOpsの科学」は、さくらのクラウドのバックエンドチームのリーダーと一緒に読書会を始めた。

チームトポロジーは読みやすく、図もあるので社内で話するときにイメージが合わせやすいという利点ある。

社内で書籍購入制度が整備されたのでしっかり有効につかっていく所存。

来年は何買うかな~

sleepy コマンド

さくらのアドベントカレンダー2022 13日目の記事です。

qiita.com

サーバ運用を行なっていると、非同期で行われるサーバの設定反映や起動を待ったり、メンテナンス後に監視を再開する前にすこし待つなんてこともあるかと思います。

そんな時に、人力で3分待ったらコマンドを打つ、Webコンソールを操作するなんてやっていると人間「必ず」忘れます。監視のメンテナンスモードの解除などを忘れてしまうとそれこそ事故につながります。チェックリストを利用した対策もありますが、技術的に解決するのが望ましい姿です。

そこで、よくやってきたのがsleepコマンドと組み合わせて

sleep 180 && mkr update --st working 

とする方法。(サンプルとしてMackerelでサーバのステータスを変更しています)

このように実行しておけば、自動で3分後にmkrコマンドが実行され、サーバの監視をもとに戻してくれます。この方法をしばしば使っていたのですが、ひとつだけ不満がありました。

それは、今どれくらいsleepしたのか分からない、あとどれくらいでmkrコマンドが動くのかを知りたいというものです。

date && sleep 180 && mkr update --st working 

このようにdateコマンドを最初に実行すれば、あとどれくらいだろーと気になった時にターミナルに表示された時間と今の時間と見比べれば、あとどれくらいで完了するのかわかるかもしれません。が、もう少し怠惰にしたいです。

ということで、なんか作るかなと思いつつ、twitterでぼやいてみました。

すると、わずか19分後に完成していました。チャットAIさんもびっくりな速さです

mattnさん速すぎです。

せっかくなので、自分の利用に合うように、小数点を含む秒数infinityのサポートと経過時間の表示を追加してもらい、お仕事でも使ってます。

以下は監視を一時的に止めつつ、さくらのクラウドでサーバのスペックを変更する例。

mkr update --st maintenance <hostId>
usacloud server shutdown <hostID> —zone <zone> -y
usacloud server update <hostID> --zone <zone> --cpu 3 --memory 4 -y
usacloud server boot <hostID>--zone <zone> -y
sleepy 360
mkr update --st working <hostId>

複数台のサーバのスペックを変更していくような場合には状況が可視化されていると、心理的安全性高く作業にあたれますね。