[{"data":1,"prerenderedAt":337},["ShallowReactive",2],{"blog-ja-k3s-cert-manager-servicelb-http01-challenge-renewal-failure":3,"blog-related-ja-k3s-cert-manager-servicelb-http01-challenge-renewal-failure":287,"blog-ja-k3s-cert-manager-servicelb-http01-challenge-renewal-failure-alt":275},{"id":4,"title":5,"author":6,"body":7,"date":269,"description":270,"extension":271,"image":272,"locale":273,"meta":274,"navigation":275,"path":276,"seo":277,"stem":278,"tags":279,"__hash__":286},"blog\u002Fblog\u002Fja\u002Fk3s-cert-manager-servicelb-http01-challenge-renewal-failure.md","K3sでcert-managerの証明書が自動更新されない。HTTP-01チャレンジをServiceLBが奪っていた","Kubo Team",{"type":8,"value":9,"toc":260},"minimark",[10,15,23,30,68,79,83,89,98,101,109,124,128,134,151,166,189,193,199,202,227,230,237,241,244,247],[11,12,14],"h2",{"id":13},"_1-症状-cert-managerのcertificateがready-falseから動かない","1. 症状 — cert-managerのCertificateが「Ready: False」から動かない",[16,17,18,22],"p",{},[19,20,21],"strong",{},"k3s cert-manager 証明書 更新されない"," という状態にハマったとき、多くのチームがまず疑うのはDNS設定かcert-managerのバージョンだ。しかし実際の犯人はもっと足元にある。",[16,24,25],{},[26,27],"img",{"alt":28,"src":29},"section01","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cert-manager-servicelb-http01-challenge-renewal-failure\u002Fsection01.webp",[16,31,32,33,37,38,41,42,49,50,53,54,57,58,57,61,57,64,67],{},"cert-managerでLet's Encrypt証明書を自動更新している構成で、",[34,35,36],"code",{},"kubectl get certificate","が",[34,39,40],{},"Ready: False","のまま変わらないという報告は珍しくない。",[43,44,48],"a",{"href":45,"rel":46},"https:\u002F\u002Fgithub.com\u002Fcert-manager\u002Fcert-manager\u002Fissues\u002F6762",[47],"nofollow","cert-managerのGitHub Issue","では、k3s + Traefik環境でHTTP-01チャレンジ用のPodが「Progressing」のまま進まず、アクセスすると503 Service Unavailableが返るという事例が報告されている。ログには",[34,51,52],{},"propagation check failed","というエラーが残り、",[34,55,56],{},"Certificate"," → ",[34,59,60],{},"CertificateRequest",[34,62,63],{},"Order",[34,65,66],{},"Challenge","というリソースの依存チェーンのどこかで詰まっていることが分かる。",[16,69,70,71,74,75,78],{},"原因の切り分けは、この4つのリソースを",[34,72,73],{},"kubectl describe","で順番に追うところから始まる。だが、Traefikの設定を何度見直しても異常が見つからないケースが少なくない。それもそのはずで、多くの場合、問題はTraefikでもcert-manager自体でもなく、",[19,76,77],{},"K3sが標準搭載しているServiceLBというコンポーネント","にある。こうした「設定はしたはずなのに、実は別のコンポーネントに専有されていた」というK3s特有の落とし穴は、クラスタの状態を普段からどこまで可視化できているかで発見のスピードが大きく変わる。",[11,80,82],{"id":81},"_2-原因1-servicelbがport-80443を専有しチャレンジpodへの到達性を壊す","2. 原因1 — ServiceLBがport 80\u002F443を専有し、チャレンジPodへの到達性を壊す",[16,84,85],{},[26,86],{"alt":87,"src":88},"section02","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cert-manager-servicelb-http01-challenge-renewal-failure\u002Fsection02.webp",[16,90,91,92,97],{},"K3sには、LoadBalancer型のServiceを使えるようにする「ServiceLB」（旧称Klipper LB）という軽量なロードバランサー実装がデフォルトで組み込まれている。",[43,93,96],{"href":94,"rel":95},"https:\u002F\u002Fdocs.k3s.io\u002Fnetworking\u002Fnetworking-services",[47],"K3s公式ドキュメント","によると、ServiceLBはLoadBalancer型ServiceごとにDaemonSetを作成し、クラスタ内の各ノードにPodをデプロイして、hostPortでそのサービスポートを直接専有する。",[16,99,100],{},"デフォルト構成では、K3s同梱のTraefikがLoadBalancerサービスとしてport 80と443をこの仕組みで専有する。結果として、同じノード上で同じポート番号を要求する別のLoadBalancerサービスやHostPort Podは競合し、Pendingのまま残ることになる。",[16,102,103,108],{},[43,104,107],{"href":105,"rel":106},"https:\u002F\u002Fgithub.com\u002Fk3s-io\u002Fk3s\u002Fdiscussions\u002F9927",[47],"k3s-io\u002Fk3sのDiscussion","が解説しているとおり、ServiceLBのPod自体は実はトラフィックを処理していない。各ノードにiptablesルールを設定し、外部IPからClusterIPへのマッピングとノードポートからのフォワーディングをカーネルレベルで行っているだけだ。つまり「見えている構成」と「実際にパケットを処理している層」が一致しないため、port 80への到達性トラブルは通常のPodログやTraefikの設定確認だけでは発見しにくい。",[16,110,111,112,117,118,123],{},"cert-managerのHTTP-01チャレンジは、",[43,113,116],{"href":114,"rel":115},"https:\u002F\u002Fcert-manager.io\u002Fdocs\u002Fconfiguration\u002Facme\u002Fhttp01\u002F",[47],"cert-manager公式ドキュメント","にあるとおり、既存のIngressやGateway設定を利用して一時的なacmesolver Podへのルーティングを行う。この経路のどこかでport 80への到達性が失われていれば、チャレンジは静かに失敗し続ける。",[43,119,122],{"href":120,"rel":121},"https:\u002F\u002Fletsencrypt.org\u002Fdocs\u002Fchallenge-types\u002F",[47],"Let's EncryptのHTTP-01チャレンジ仕様","では、検証は必ずport 80で行うと定められており、任意のポートを指定することはACME標準上許可されていない。つまり、port 80の到達性が壊れている限り、代替ポートで回避することもできない。",[11,125,127],{"id":126},"_3-原因2-ingressclassnameの不一致でtraefikがチャレンジ用ingressを拾わない","3. 原因2 — ingressClassNameの不一致でTraefikがチャレンジ用Ingressを拾わない",[16,129,130],{},[26,131],{"alt":132,"src":133},"section03","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cert-manager-servicelb-http01-challenge-renewal-failure\u002Fsection03.webp",[16,135,136,137,140,141,146,147,150],{},"もう一つ見落とされがちなのが、cert-managerが自動生成するACMEチャレンジ用Ingressの",[34,138,139],{},"ingressClassName","だ。",[43,142,145],{"href":143,"rel":144},"https:\u002F\u002Fkubernetes.io\u002Fdocs\u002Fconcepts\u002Fservices-networking\u002Fingress\u002F",[47],"Kubernetes公式ドキュメント","が説明するとおり、Ingressリソースの",[34,148,149],{},"spec.ingressClassName","は、どのIngressコントローラーがそのリソースを処理するかを決めるフィールドで、デフォルトのIngressClassが定義されていない環境では動作がコントローラーの実装依存になる。",[16,152,153,158,159,162,163,165],{},[43,154,157],{"href":155,"rel":156},"https:\u002F\u002Fgithub.com\u002Fk3s-io\u002Fk3s\u002Fissues\u002F4765",[47],"k3s-io\u002Fk3sのGitHub Issue","では、cert-managerが作成したチャレンジ用Ingressに",[34,160,161],{},"ingressClassName: traefik","が設定されると、K3s同梱のTraefikがそのリソースを認識しないケースが報告されている。回避策はIngressリソースから",[34,164,139],{},"を手動で削除することだが、これは応急処置に過ぎず、次回の証明書更新時に同じIngressが再生成されれば問題は再発する。",[16,167,168,169,174,175,178,179,182,183,188],{},"さらに",[43,170,173],{"href":171,"rel":172},"https:\u002F\u002Fcommunity.traefik.io\u002Ft\u002Fcert-manager-http-01-challenge-failing\u002F15575",[47],"Traefik Labsのコミュニティフォーラム","では、",[34,176,177],{},"\u002F.well-known\u002Facme-challenge\u002F","へのリクエストにTraefikが正しく応答せず、IngressRouteのバックエンドサービスへそのまま転送してしまう事例や、HTTP→HTTPSリダイレクトが有効な場合にチャレンジ自体がリダイレクトされて失敗する事例も報告されている。",[19,180,181],{},"原因1（ServiceLBのポート専有）と原因2（ingressClassNameの不一致）は独立した問題だが、実際の障害では両方が重なって発生することも多く","、片方だけ直しても解決しないケースがあることに注意したい。マネージドK8sサービスの中には、こうしたIngressコントローラーとロードバランサーの整合性を導入時点でテンプレート化しているものもあり、",[43,184,187],{"href":185,"rel":186},"https:\u002F\u002Fkubo.hexabase.io\u002F",[47],"Kubo","もその一つだ。",[11,190,192],{"id":191},"_4-対処法-ノード固定ingressclassname調整disable-servicelbの使い分け","4. 対処法 — ノード固定・ingressClassName調整・disable servicelbの使い分け",[16,194,195],{},[26,196],{"alt":197,"src":198},"section04","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cert-manager-servicelb-http01-challenge-renewal-failure\u002Fsection04.webp",[16,200,201],{},"応急処置としては、詰まっているCertificate・CertificateRequest・Order・Challengeのリソースを削除して再作成し、その際にingressClassNameの指定を見直すことで一時的に復旧できる。ただしこれは対症療法であり、次の更新サイクルで再発するリスクが残る。",[16,203,204,205,208,209,212,213,216,217,220,221,226],{},"恒久対策としては2つの方向性がある。一つは、",[43,206,96],{"href":94,"rel":207},[47],"にあるとおり、",[34,210,211],{},"enablelb","ラベルと",[34,214,215],{},"lbpool","ラベルを使ってServiceLBの対象ノードを固定し、ポート競合が起きにくい構成に変える方法だ。もう一つは、",[34,218,219],{},"--disable=servicelb","でServiceLB自体を無効化し、",[43,222,225],{"href":223,"rel":224},"https:\u002F\u002Fmetallb.io\u002F",[47],"MetalLB","のような、bare-metal\u002Fオンプレ環境向けに設計された本格的なロードバランサー実装に切り替える方法だ。MetalLBはBGPやL2モードで既存のネットワーク機器と連携し、クラウド環境と同等のロードバランシングをオンプレミスでも実現する。",[16,228,229],{},"どちらを選ぶかは、クラスタの規模と運用体制次第だ。小規模なクラスタでノード数が少なく、複雑なネットワーク要件がなければノード固定で十分なことが多い。一方、複数のLoadBalancerサービスを恒常的に運用する本番クラスタでは、MetalLB導入によって根本的にポート競合のリスクを排除したほうが運用は安定する。",[16,231,232,233,236],{},"こうした「デフォルトで動いているつもりが、実は特定のコンポーネントに専有されていた」という設定不整合は、K3sを本番運用する上で繰り返し遭遇するパターンだ。",[43,234,187],{"href":185,"rel":235},[47],"のCaptain UIでは、こうしたクラスタ内の設定状態を可視化できるため、ServiceLBのポート専有やIngressClassの不一致のような「見えない専有者」を事前に発見しやすくなる。",[11,238,240],{"id":239},"_5-まとめ-k3sの省略された当たり前が本番障害の火種になる","5. まとめ — K3sの「省略された当たり前」が本番障害の火種になる",[16,242,243],{},"K3sは軽量なKubernetesディストリビューションとして、ServiceLBやTraefikを標準搭載することで初期構築の手間を大幅に減らしてくれる。しかしその「省略された当たり前」が可視化されないまま本番運用に持ち込まれると、今回のcert-manager証明書更新失敗のような、原因の特定に時間がかかる障害につながる。",[16,245,246],{},"証明書が更新されないという症状に直面したら、cert-manager自体やDNS設定だけでなく、ServiceLBのポート専有とIngressClassの整合性という、K3s特有のレイヤーも合わせて確認してほしい。",[16,248,249,250,253,254,259],{},"EKSやAKSのような高コストなマネージドK8sに悩まされることなく、こうした運用の落とし穴を事前に減らしたいのであれば、K3sベースの",[43,251,187],{"href":185,"rel":252},[47],"が一つの選択肢になる。Let's Encrypt証明書の自動管理を標準搭載しつつ、Captain UIで構成の見落としを可視化できる点は、本記事のような障害を未然に防ぐ助けになるはずだ。同じ落とし穴を踏みたくないチームは、",[43,255,258],{"href":256,"rel":257},"https:\u002F\u002Fwww.hexabase.com\u002Fcontact-us\u002F",[47],"お問い合わせ","から一度相談してみるとよいだろう。",{"title":261,"searchDepth":262,"depth":262,"links":263},"",2,[264,265,266,267,268],{"id":13,"depth":262,"text":14},{"id":81,"depth":262,"text":82},{"id":126,"depth":262,"text":127},{"id":191,"depth":262,"text":192},{"id":239,"depth":262,"text":240},"2026-09-25","K3sでcert-managerの証明書が更新されない原因はTraefikでもcert-manager自体でもなく、port 80\u002F443を専有するServiceLBだった。HTTP-01チャレンジが静かに失敗する仕組みと恒久対処を解説する。","md","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fja\u002Fk3s-cert-manager-servicelb-http01-challenge-renewal-failure\u002Ftitle.webp","ja",{},true,"\u002Fblog\u002Fja\u002Fk3s-cert-manager-servicelb-http01-challenge-renewal-failure",{"title":5,"description":270},"blog\u002Fja\u002Fk3s-cert-manager-servicelb-http01-challenge-renewal-failure",[280,281,282,283,284,285],"k3s","kubernetes","cert-manager","servicelb","tls","lets-encrypt","YlB8azbjDGmMme9oE_WpyMFARTQn8JkrZc9BxbquF6s",[288,295,302,311,319,328],{"path":289,"title":290,"description":291,"date":292,"tags":293},"\u002Fblog\u002Fja\u002Fk3s-cert-manager-acme-renewal-pitfalls","土曜の朝、K3sの本番サイトがTLS証明書切れで落ちた。手動更新から抜け出すACME自動化の設計","K3sの本番環境にcert-managerを導入していても、Issuerの参照ミスやDNS検証失敗、Let's Encryptのレート制限、Secret未リロードといった見落としで証明書は静かに失効する。手動更新時代の属人化と同じ罠に陥らないための、ACME自動更新を本当に機能させる監視・設計のポイントを解説する。","2026-08-27",[280,281,282,284,285,294],"acme",{"path":296,"title":297,"description":298,"date":299,"tags":300},"\u002Fblog\u002Fja\u002Fkubernetes-certificate-management-cert-manager-process-debt","証明書の更新、1行のコードより2ヶ月の会議が長かった。Kubernetesの証明書管理が『技術』ではなく『手続き』の問題である理由","Kubernetesの証明書管理は技術的には数日で終わる。だが実際に時間がかかるのは合意形成という『手続き』だ。cert-managerによる自動化と、組織的負債をなくす設計を解説する。","2026-08-09",[280,281,282,284,301],"security",{"path":303,"title":304,"description":305,"date":306,"tags":307},"\u002Fblog\u002Fja\u002Fcert-manager-automatic-tls","cert-manager で Kubernetes の TLS 証明書を自動管理する","cert-manager を使って Kubernetes 環境の TLS 証明書を自動発行・自動更新する方法を解説。Let's Encrypt、ACME チャレンジ、Ingress 連携まで。","2026-05-27",[282,281,284,285,294,308,309,310],"cncf","セキュリティ","証明書",{"path":312,"title":313,"description":314,"date":315,"tags":316},"\u002Fblog\u002Fja\u002Fk3s-pod-security-admission-restricted-servicelb-outage","restrictedを有効にしたらServiceLBが死んだ。K3sのPod Security Admissionに潜む、汎用ガイドにない設定差分","K3sでPod Security Admissionのrestrictedプロファイルを有効化したら、標準Kubernetesのガイド通りに進めたのにServiceLBが機能停止した。原因と安全な導入手順をK3s公式ハードニングガイドの記述とともに解説する。","2026-10-16",[280,281,317,318,283,301],"pod-security-admission","pod-security-standards",{"path":320,"title":321,"description":322,"date":323,"tags":324},"\u002Fblog\u002Fja\u002Fk3s-networkpolicy-dual-stack-kube-router-ipv6-gap","「K3sはNetworkPolicyを無視する」は嘘だった。それでも通信が漏れていた、ServiceLBという死角","K3sはkube-router内蔵コントローラでNetworkPolicyをデフォルト強制する。それでもLoadBalancer経由の通信だけが漏れる理由は、ServiceLBの実装とNetworkPolicy APIの恒久的な制約が組み合わさった結果だった。検証手順と対処法を解説する。","2026-09-24",[280,281,325,283,326,327],"networkpolicy","kube-router","network-security",{"path":329,"title":330,"description":331,"date":332,"tags":333},"\u002Fblog\u002Fja\u002Fk3s-traefik-servicelb-ingress-nginx-port-conflict","K3sのTraefikを無効化したはずなのに、ingress-nginxが443番を取れない。ServiceLBという見えない同居人","K3sでTraefik無効化を実行したのにingress-nginxが443番ポートを取れない――原因はServiceLB(klipper-lb)というもう一つのデフォルトコンポーネント。診断から正しい無効化手順、MetalLB併用時の注意まで解説する。","2026-09-19",[280,281,334,283,335,336],"traefik","ingress-nginx","load-balancer",1792592603308]