<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Pyats on K-Life Hack | 韓国ハイエンド・ライフスタイルガイド</title><link>https://klifehack.com/tags/pyats/</link><description>Recent content in Pyats on K-Life Hack | 韓国ハイエンド・ライフスタイルガイド</description><generator>Hugo -- gohugo.io</generator><language>ja</language><lastBuildDate>Fri, 22 May 2026 17:34:52 +0900</lastBuildDate><atom:link href="https://klifehack.com/tags/pyats/index.xml" rel="self" type="application/rss+xml"/><item><title>NetmikoのSSHタイムアウトによるAnsibleプロビジョニング失敗の解決</title><link>https://klifehack.com/p/netmiko-ssh-timeout-ansible-fix/</link><pubDate>Fri, 22 May 2026 17:34:52 +0900</pubDate><guid>https://klifehack.com/p/netmiko-ssh-timeout-ansible-fix/</guid><description>&lt;img src="https://klifehack.com/" alt="Featured image of post NetmikoのSSHタイムアウトによるAnsibleプロビジョニング失敗の解決" /&gt;&lt;h1 id="cisco-iosスイッチ200台へのacl一括適用におけるnetmikoタイムアウト対策とpyats検証自動化"&gt;Cisco IOSスイッチ200台へのACL一括適用におけるNetmikoタイムアウト対策とpyATS検証自動化
&lt;/h1&gt;&lt;p&gt;2026年5月31日の本番デプロイにおいて、200台のCisco IOSスイッチに対する一括ACL適用中に発生した&lt;b&gt;&lt;mark&gt;Netmiko&lt;/mark&gt;&lt;/b&gt;のSSHタイムアウトエラー（&lt;code&gt;NetmikoTimeoutException&lt;/code&gt;）およびそれに伴う構成ドリフトの解決手順を記録します。この問題は、制御ノードの並行処理セマフォ制御の導入と、Netmikoの接続パラメータ（&lt;code&gt;global_delay_factor&lt;/code&gt;および&lt;code&gt;read_timeout_override&lt;/code&gt;）の最適化、そして&lt;b&gt;&lt;mark&gt;pyATS&lt;/mark&gt;&lt;/b&gt;による事後検証自動化によって解決されました。&lt;/p&gt;
&lt;p&gt;本システムは、Gitを信頼の唯一の情報源（Source of Truth）とするNetDevOpsのアーキテクチャを採用しています。&lt;/p&gt;
&lt;img alt="System operational pipeline topology flow description" fetchpriority="high" height="376" loading="eager" src="https://raw.githubusercontent.com/bbobboyya00-cmyk/k-life-assets/main/assets/2026/05/31/netmiko-ssh-timeout-ansible-fix/khack_1780194891_0.webp" style="width:auto;max-width:100%;height:auto;object-fit:contain;border-radius:12px;margin:35px auto;display:block;box-shadow:0 4px 15px rgba(0,0,0,0.1);" width="672"/&gt;
&lt;h2 id="大規模デプロイ時に発生したssh接続切断と部分適用の検知"&gt;大規模デプロイ時に発生したSSH接続切断と部分適用の検知
&lt;/h2&gt;&lt;p&gt;GitLab CI/CDパイプライン経由でAnsibleプレイブックを実行した際、特定のレガシースイッチ群においてタスクが中断し、以下のエラーログが出力されました。これにより、一部のデバイスにのみ設定が適用され、ネットワーク全体で構成の不整合（構成ドリフト）が発生しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;netmiko.exceptions.NetmikoTimeoutException: Connection to device timed-out: cisco_ios 192.168.10.15:22
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このエラーにより、パイプラインは異常終了し、デプロイ対象の200台中15台のスイッチが中間状態で放置される事態となりました。&lt;/p&gt;
&lt;h2 id="cpuリソース飽和とコマンド応答遅延の相乗効果"&gt;CPUリソース飽和とコマンド応答遅延の相乗効果
&lt;/h2&gt;&lt;p&gt;事後解析の結果、タイムアウトの原因は以下の2点に集約されました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;制御ノードにおける並行処理数の過多&lt;/b&gt;
Ansibleの&lt;code&gt;forks&lt;/code&gt;パラメータがデフォルトのままであったため、制御ノードが同時に多数のSSHセッションを確立しようとし、CPU使用率が100%に達しました。これにより、SSHハンドシェイクの遅延が発生しました。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;b&gt;レガシーハードウェアのコマンド処理遅延&lt;/b&gt;
対象のCisco IOSスイッチ（Catalyst 2960シリーズ等）は、大規模なACL（100行以上）のコンパイル時にCPU負荷が上昇し、コマンド応答に通常以上の時間を要します。Netmikoのデフォルトの読み取りタイムアウト（100秒）を超過したため、接続が切断されました。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="タイムアウト値の動的調整とセマフォによる流量制御"&gt;タイムアウト値の動的調整とセマフォによる流量制御
&lt;/h2&gt;&lt;p&gt;この問題を解決するため、接続パラメータの最適化と、並行処理数を制限するセマフォ制御を導入しました。&lt;/p&gt;
&lt;h3 id="1-netmiko接続スクリプトのパラメータチューニング-"&gt;1. Netmiko接続スクリプトのパラメータチューニング 🛠️
&lt;/h3&gt;&lt;p&gt;Pythonによる並行実行スクリプトにおいて、&lt;code&gt;global_delay_factor&lt;/code&gt;を&lt;code&gt;2.0&lt;/code&gt;に引き上げ、さらに&lt;code&gt;read_timeout_override&lt;/code&gt;を&lt;code&gt;300&lt;/code&gt;秒に設定しました。これにより、低速なデバイスからの応答を十分に待機できるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; netmiko &lt;span style="color:#f92672"&gt;import&lt;/span&gt; ConnectHandler
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;device_params &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;device_type&amp;#39;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;cisco_ios&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;host&amp;#39;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;192.168.10.15&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;username&amp;#39;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;admin&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;password&amp;#39;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;secure_password&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;global_delay_factor&amp;#39;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2.0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;read_timeout_override&amp;#39;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; ConnectHandler(&lt;span style="color:#f92672"&gt;**&lt;/span&gt;device_params) &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; net_connect:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;output &lt;span style="color:#f92672"&gt;=&lt;/span&gt; net_connect&lt;span style="color:#f92672"&gt;.&lt;/span&gt;send_config_set(config_commands)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(output)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-ansibleにおける接続設定の最適化-"&gt;2. Ansibleにおける接続設定の最適化 💡
&lt;/h3&gt;&lt;p&gt;Ansibleプレイブック側でも、&lt;code&gt;ansible.cfg&lt;/code&gt;およびインベントリ変数に変数を追加し、SSHのキープアライブとタイムアウトを制御しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ansible.cfg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;[defaults]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;forks&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;timeout&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;300&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;[ssh_connection]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;ssh_args&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;-o ControlMaster=auto -o ControlPersist=60s -o ServerAliveInterval=30 -o ServerAliveCountMax=3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="pyatsによる状態検証とデプロイ時間の測定"&gt;pyATSによる状態検証とデプロイ時間の測定
&lt;/h2&gt;&lt;p&gt;修正適用後、テスト環境および本番環境において以下の検証手順を実施しました。&lt;/p&gt;
&lt;h3 id="1-パイプラインの再実行と実行ログの確認-"&gt;1. パイプラインの再実行と実行ログの確認 ⚠️
&lt;/h3&gt;&lt;p&gt;並行数を10に制限した状態でスクリプトを実行し、CPU使用率が安定していることを確認しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ansible-playbook -i inventory.ini deploy_acl.yml --forks=10
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PLAY [Deploy ACL to Cisco IOS Switches] &amp;lt;b&amp;gt;TASK [Gathering Facts]&amp;lt;/b&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ok: [switch-01]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ok: [switch-02]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TASK [Apply ACL Configuration] &amp;lt;b&amp;gt;&amp;lt;/b&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;changed: [switch-01]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;changed: [switch-02]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PLAY RECAP &amp;lt;b&amp;gt;&amp;lt;/b&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;switch-01 : ok=2 changed=1 unreachable=0 failed=0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;switch-02 : ok=2 changed=1 unreachable=0 failed=0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-pyatsを用いた構成整合性検証"&gt;2. pyATSを用いた構成整合性検証
&lt;/h3&gt;&lt;p&gt;デプロイ完了後、pyATSを使用して全デバイスのACL適用状態をパースし、未適用または不整合な設定が存在しないかを自動検証しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; genie.testbed &lt;span style="color:#f92672"&gt;import&lt;/span&gt; load
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;testbed &lt;span style="color:#f92672"&gt;=&lt;/span&gt; load(&lt;span style="color:#e6db74"&gt;&amp;#39;testbed.yaml&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;device &lt;span style="color:#f92672"&gt;=&lt;/span&gt; testbed&lt;span style="color:#f92672"&gt;.&lt;/span&gt;devices[&lt;span style="color:#e6db74"&gt;&amp;#39;switch-01&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;device&lt;span style="color:#f92672"&gt;.&lt;/span&gt;connect()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;parsed_output &lt;span style="color:#f92672"&gt;=&lt;/span&gt; device&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(&lt;span style="color:#e6db74"&gt;&amp;#39;show ip access-lists&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;assert&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;MY_SECURE_ACL&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;in&lt;/span&gt; parsed_output
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(&lt;span style="color:#e6db74"&gt;&amp;#34;ACL verification passed successfully.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;検証の結果、タイムアウトによる切断は0件となり、全200台のスイッチに対して意図したACLが正常に適用されていることが確認されました。全体の処理時間は、タイムアウト再試行による遅延を含めた従来の1200秒から、安定した並行処理により45秒へと短縮されました。&lt;/p&gt;</description></item></channel></rss>