Skip to content

fix: alice/ionosのVIP・BGP prefix・WireGuard AllowedIPs・/etc/wireguard権限の不一致を修正 - #62

Open
kigawa01 wants to merge 2 commits into
mainfrom
fix-alice-vip-mismatch
Open

fix: alice/ionosのVIP・BGP prefix・WireGuard AllowedIPs・/etc/wireguard権限の不一致を修正#62
kigawa01 wants to merge 2 commits into
mainfrom
fix-alice-vip-mismatch

Conversation

@kigawa01

Copy link
Copy Markdown
Member

緊急度: 高(本番Webサイト障害の修正、既に適用・復旧確認済み)

背景

k8s4の192.168.1.x→10.0.0.x移行(PR #59, #61)後、https://kigawa.net がCloudflare経由で525エラー(オリジンとのTLSハンドシェイク失敗)を返し、外部からアクセス不能になった。

発見・修正した問題

  1. hardware/alice のVIP不一致: inuyama_ingress_vip/minecraft_backend_vip192.168.1.240/241 のままで、K8s側のService(alice-ingress)は既に 10.0.0.240/241 に移行済みだった。
  2. BGP prefix-listの不一致: alice/k8s4双方の prefix-list が 10.0.0.0/16 を指定していたが、実際のルーティングテーブルには /24 しか存在せず、export filter(完全一致)が何もマッチせず経路が一切広告されていなかった。/24 に修正。
  3. WireGuard AllowedIPsの不足: aliceの wireguard_peer_allowed_ips10.0.0.0/24 が含まれておらず、たとえBGP経路があってもWireGuardトンネル内で暗号化できなかった(sendmsg: Required key not available)。
  4. bwsカラー出力バグの未修正: hardware/alice/main.tf 自体に、他モジュールで対応済みの --color no が適用されていなかった。このままapplyするとinuyama/k8s1/k8s2の公開鍵が空文字にフォールバックし、WireGuard設定を壊すリスクがあった。
  5. /etc/wireguard の権限バグ: hardware/modules/wireguard, alice, ionos, k8s4 の全てで install -d -m 700 /etc/wireguard となっており、design doc(docs/network.md)記載の 711 と食い違っていた。700だと非rootユーザー(kigawa)が publickey を読めず(Permission denied)、alice/ionosからのk8s1/k8s2公開鍵取得(SSH経由)が失敗して空文字にフォールバックしていた。ionos経由の接続不能はこれが原因だった。

適用・検証済み

  • alice: VIP・prefix-list・AllowedIPs・bwsカラー修正を全て適用。BGP Established・経路受信(PfxRcd: 1)・バックエンドVIPへのHTTP疎通(404、接続成功)・https://kigawa.net の外部アクセス(200 OK)を確認
  • ionos: 同様にAllowedIPs・prefix-list修正を適用。BGP Established・経路受信・バックエンドVIPへのHTTP疎通を確認
  • k8s1/k8s2: /etc/wireguard の権限を 711 に修正(直接SSH、緊急対応)
  • k8s4: BGP export_prefixes を /24 に修正・適用済み

Test plan

  • terraform fmt -check / terraform validate(alice, ionos, k8s4)
  • 実際にapply、BGP/WireGuard/HTTP疎通を確認
  • 外部からの実サイトアクセス復旧確認(200 OK)

🤖 Generated with Claude Code

kigawa01 and others added 2 commits July 29, 2026 20:59
k8s4の192.168.1.x→10.0.0.x移行(PR #59)でalice-ingress Serviceの
loadBalancerIPが10.0.0.240/241に変わったが、hardware/aliceモジュール
(inuyama_ingress_vip, minecraft_backend_vip, inuyama_accepted_prefixes)
は192.168.1.240/241, 192.168.1.0/24のまま据え置かれていたため、
aliceのHAProxyが新VIPに到達できず(BGP prefix-listでも拒否されており
経路自体が無い状態)、外部からWebサイトにアクセスできなくなる
障害が発生した。

あわせて、hardware/alice/main.tf の bws secret get 呼び出しに --color no
が無く、k8s1/k8s2/k8s4/ionosで対応済みの色出力バグが未修正だった
(このままapplyするとinuyama/k8s1/k8s2の公開鍵が全て空文字に
フォールバックし、WireGuard設定を壊す可能性があった)ため修正。
k8s1_wireguard_public_key/k8s2_wireguard_public_key変数も
デフォルトが空文字のままcommitされていたため、実際の値を
デフォルトとして設定した。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…d権限バグを修正

k8s4の192.168.1.x→10.0.0.x移行後、以下の障害が連鎖的に発生した
(https://kigawa.net が525エラーで到達不能に):

1. hardware/alice の inuyama_ingress_vip/minecraft_backend_vip が
   192.168.1.240/241のままで、K8s側は10.0.0.240/241に移行済みだった
2. alice/k8s4双方のBGP prefix-listが "10.0.0.0/16" を指定していたが、
   実際のルーティングテーブルには/24しか存在せず(export filterが
   完全一致のため)経路が一切広告されていなかった。"/24"に修正。
3. aliceのWireGuard AllowedIPsに10.0.0.0/24が含まれておらず、経路が
   あってもトンネル内で暗号化できなかった
   ("sendmsg: Required key not available")
4. hardware/alice/main.tf 自体にbwsカラー出力バグの修正が
   未適用だった(alice/ionos/k8s1/k8s2/k8s4で対応済みの--color no)

同様の問題をionos側にも適用(k8s1/k8s2向けピア追加時に発見した
別バグ経由で発覚): hardware/modules/wireguard, alice, ionos, k8s4の
`install -d -m 700 /etc/wireguard` が、design doc
(docs/network.md記載の711)と食い違っており、非rootユーザーが
publickeyを読めず(Permission denied)、alice/ionosからのk8s1/k8s2
公開鍵取得が失敗して空文字にフォールバックしていた。711に修正。

全て実際にapplyし、alice・ionos双方でBGP Established・経路受信・
バックエンドVIPへのHTTP疎通・外部からの実サイトアクセス(200 OK)を
確認済み。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Terraform Plan hardware/alice

data.external.ssh_key: Reading...
data.external.inuyama_wireguard_public_key: Reading...
data.external.sudo_password: Reading...
data.external.inuyama_wireguard_public_key: Read complete after 0s [id=-]
data.external.ssh_key: Read complete after 0s [id=-]
data.external.sudo_password: Read complete after 0s [id=-]
null_resource.alice_gateway: Refreshing state... [id=5837086620168430854]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.

@github-actions

Copy link
Copy Markdown

Terraform Plan hardware/ionos

data.external.k8s1_wireguard_public_key: Reading...
data.external.sudo_password: Reading...
data.external.ssh_key: Reading...
data.external.k8s2_wireguard_public_key: Reading...
data.external.inuyama_wireguard_public_key: Reading...
data.external.inuyama_wireguard_public_key: Read complete after 0s [id=-]
data.external.sudo_password: Read complete after 0s [id=-]
data.external.ssh_key: Read complete after 0s [id=-]
data.external.k8s2_wireguard_public_key: Read complete after 1s [id=-]
data.external.k8s1_wireguard_public_key: Still reading... [10s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [20s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [30s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [40s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [50s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [1m0s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [1m10s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [1m20s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [1m30s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [1m40s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [1m50s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [2m0s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [2m10s elapsed]
data.external.k8s1_wireguard_public_key: Still reading... [2m20s elapsed]
data.external.k8s1_wireguard_public_key: Read complete after 2m27s [id=-]
null_resource.ionos_gateway: Refreshing state... [id=5468791671309335735]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.

@github-actions

Copy link
Copy Markdown

Terraform Plan hardware/k8s1

data.external.ssh_key: Reading...
data.external.join_info: Reading...
data.external.sudo_password: Reading...
data.external.ssh_key: Read complete after 0s [id=-]
data.external.sudo_password: Read complete after 0s [id=-]
module.keepalived.null_resource.keepalived: Refreshing state... [id=7637171177745551209]
module.node_exporter.null_resource.node_exporter: Refreshing state... [id=5720328708674827767]
module.wireguard_ionos[0].null_resource.wireguard: Refreshing state... [id=6628577406890648213]
module.control_plane.null_resource.disable_swap: Refreshing state... [id=2884415110834909690]
module.wireguard[0].null_resource.wireguard: Refreshing state... [id=6656762921329990223]
module.dual_stack_network.null_resource.dual_stack_network: Refreshing state... [id=1932623077735172172]
data.external.join_info: Read complete after 1s [id=-]
module.control_plane.null_resource.control_plane: Refreshing state... [id=8957225143565195658]
module.kube_vip.null_resource.kube_vip: Refreshing state... [id=7758168106548197620]
module.knot.null_resource.knot: Refreshing state... [id=1087168737206409085]
module.bgp.null_resource.bird: Refreshing state... [id=7710895868079908516]
module.knot_resolver.null_resource.knot_resolver: Refreshing state... [id=6307309063132079256]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.node_exporter.null_resource.node_exporter is tainted, so must be replaced
-/+ resource "null_resource" "node_exporter" {
      ~ id       = "5720328708674827767" -> (known after apply)
        # (1 unchanged attribute hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"

@github-actions

Copy link
Copy Markdown

Terraform Plan hardware/k8s2

data.external.sudo_password: Reading...
data.external.ssh_key: Reading...
data.external.join_info: Reading...
data.external.sudo_password: Read complete after 1s [id=-]
data.external.ssh_key: Read complete after 1s [id=-]
module.keepalived.null_resource.keepalived: Refreshing state... [id=77951099548562352]
module.control_plane.null_resource.disable_swap: Refreshing state... [id=2078522867301445248]
module.wireguard[0].null_resource.wireguard: Refreshing state... [id=2269961954052301461]
module.dual_stack_network.null_resource.dual_stack_network: Refreshing state... [id=5451387125518665062]
module.wireguard_ionos[0].null_resource.wireguard: Refreshing state... [id=5499479373548988130]
module.node_exporter.null_resource.node_exporter: Refreshing state... [id=8947209831206120089]
data.external.join_info: Read complete after 2s [id=-]
module.control_plane.null_resource.control_plane: Refreshing state... [id=3058245187027734364]
module.knot.null_resource.knot: Refreshing state... [id=298362026524776807]
module.kube_vip.null_resource.kube_vip: Refreshing state... [id=3718697180889100482]
module.bgp.null_resource.bird: Refreshing state... [id=6967168182303976108]
module.knot_resolver.null_resource.knot_resolver: Refreshing state... [id=4610183504413275223]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.node_exporter.null_resource.node_exporter is tainted, so must be replaced
-/+ resource "null_resource" "node_exporter" {
      ~ id       = "8947209831206120089" -> (known after apply)
        # (1 unchanged attribute hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"

@github-actions

Copy link
Copy Markdown

Terraform Plan hardware/k8s4

data.external.inuyama_wireguard_private_key: Reading...
data.external.inuyama_wireguard_public_key: Reading...
data.external.sudo_password: Reading...
data.external.join_info: Reading...
data.external.ssh_key: Reading...
data.external.sudo_password: Read complete after 0s [id=-]
data.external.inuyama_wireguard_public_key: Read complete after 0s [id=-]
data.external.ssh_key: Read complete after 0s [id=-]
module.control_plane.null_resource.disable_swap: Refreshing state... [id=2329390693052091540]
module.dual_stack_network.null_resource.dual_stack_network: Refreshing state... [id=1439211189376407669]
module.keepalived.null_resource.keepalived: Refreshing state... [id=5824191557159964081]
module.node_exporter.null_resource.node_exporter: Refreshing state... [id=6858918750130305665]
data.external.inuyama_wireguard_private_key: Read complete after 0s [id=-]
data.external.join_info: Read complete after 1s [id=-]
module.control_plane.null_resource.control_plane: Refreshing state... [id=5585367606577211439]
null_resource.inuyama_wireguard: Refreshing state... [id=3885716026194835594]
null_resource.alice_gateway_services: Refreshing state... [id=3940773195772703657]
module.knot.null_resource.knot: Refreshing state... [id=6183639464161112917]
module.kube_vip.null_resource.kube_vip: Refreshing state... [id=7338728135863286924]
null_resource.ionos_wireguard: Refreshing state... [id=8774253257334007016]
module.knot_resolver.null_resource.knot_resolver: Refreshing state... [id=3897163815884797760]
module.bgp.null_resource.bird: Refreshing state... [id=3571465568012680806]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.node_exporter.null_resource.node_exporter is tainted, so must be replaced
-/+ resource "null_resource" "node_exporter" {
      ~ id       = "6858918750130305665" -> (known after apply)
        # (1 unchanged attribute hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant