{"id":"IL-0473","org":"Jenkins project","date":"2023-07-07","docs":[],"title":{"en":"Jenkins infrastructure went fully down after a pod IP range fix deleted every AKS node pool and could not recreate them","ko":"Azure 공개 쿠버네티스 클러스터의 노드 풀이 모두 지워지고 다시 만들어지지 않아 Jenkins 인프라 서비스가 4시간 넘게 멈췄다"},"domain":["kubernetes","azure","networking"],"impact":{"scope":"Complete downtime of accounts.jenkins.io, fallback.get.jenkins.io, get.jenkins.io, incrementals.jenkins.io, javadoc.jenkins.io, plugin-health.jenkins.io, plugin-site-issues.jenkins.io, plugins.origin.jenkins.io, plugins.jenkins.io, rating.jenkins.io, repo.azure.jenkins.io, reports.jenkins.io, stories.jenkins.io, uplink.jenkins.io, weekly.ci.jenkins.io and www.origin.jenkins.io, and of the internal ldap.jenkins.io and the previews of *.jenkins.io pull requests on infra.ci.jenkins.io; partial or complete disruption of ci.jenkins.io, infra.ci.jenkins.io, issues.jenkins.io, plugins.jenkins.io, repo.jenkins-ci.org and www.jenkins.io; the public IPs of these services changed","users":"Jenkins users and contributors, including users behind corporate firewalls with an allow-list","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"The team said that changing one node pool at a time would have shown the problem after the first pool and avoided a full outage, and that the public IPs should change as little as possible because users behind corporate firewalls with allow-lists depend on them. The team also noted that it could rebuild, in under 4 hours, the cluster that hosts almost all public services.","ko":"허용 목록을 둔 회사 방화벽 뒤의 사용자가 있어서 공개 IP 는 되도록 바뀌지 않아야 한다. 그런데 원래 클러스터를 지우면서 노드 리소스 그룹과 함께 공개 IP 가 지워졌다. 노드 풀 설정을 한꺼번에 바꾸지 않았다면 첫 노드 풀에서 문제를 잡아 전체 장애를 피할 수 있었다. 팀은 거의 모든 공개 서비스를 담은 클러스터가 완전히 무너져도 4시간 안에 복구할 수 있다는 것을 이번에 확인했다. 그 바탕은 여러 해 동안 함께 해 온 아키텍처 정의, 인프라 구축, 데이터 백업 작업이라고 했다."},"related":[],"sources":[{"url":"https://www.jenkins.io/blog/2023/07/12/jenkins-mirrors-postmortem-outage/","kind":"blog","archived":"https://web.archive.org/web/20260409223411/https://www.jenkins.io/blog/2023/07/12/jenkins-mirrors-postmortem-outage/"}],"summary":{"en":"The Jenkins infrastructure team runs most public jenkins.io services on a public Kubernetes cluster in Azure. On 7 July 2023, after a successful upgrade of that cluster to 1.25 under help desk ticket 3582, services in the cluster could no longer reach the LDAP service, because the pods' originating IP was in a different range than before and IP restrictions blocked it. At 10:55 UTC the team deployed a fix, Azure PR 431, to give the pods a proper set of IP ranges. The change removed all node pools, the virtual machines that ran the containers, and failed to re-create them, which took down every service in the cluster from 11:05 UTC.\n\nThe node pools could not be re-created because of an address overlap the team had not known about. The cluster had been created with the 10.244.0.0/16 virtual network and a 10.245.0.0/24 subnet, but 10.244.0.0/24 is the default pod CIDR in Azure when the kubenet network is used to support IPv6 instead of the default CNI. The team had assumed the two ranges could communicate and deployed an invalid setup. From 11:16 to 13:16 UTC the team built the cluster again from scratch with a fixed network setup, and once a custom pod CIDR in a separate range was set, everything worked. Deleting the original cluster had also removed its node resource group and the public IPs in it, so the services came back on new IP addresses and DNS records. At 15:17 UTC a pull request recorded the manual rebuild, including the IP setup, in code, and at 15:25 UTC all services were back to normal.","ko":"2023-07-07 10:30 UTC 에 Jenkins 인프라 팀은 Azure 의 공개 쿠버네티스 클러스터를 1.25 로 올린 뒤, accounts.jenkins.io 처럼 클러스터 안에서 도는 서비스가 LDAP 서비스에 닿지 못한다는 것을 알았다. 파드의 출발 IP 가 전과 다른 대역이어서 IP 제한에 막혔다. 10:55 UTC 에 파드 IP 대역을 제대로 지정하는 수정인 Azure PR 431 을 배포했다. 이 변경으로 노드 풀이 모두 지워진 뒤 다시 만들어지지 않아, 클러스터에서 돌던 서비스가 모두 멈췄다.\n\n클러스터를 처음 만들 때 가상 네트워크 대역으로 10.244.0.0/16 을, 서브넷으로 10.245.0.0/24 를 골랐다. 그런데 팀은 한 가지를 놓쳤다. IPv6 를 지원하려고 기본 CNI 대신 kubenet 네트워크를 쓰면, Azure 에서는 10.244.0.0/24 대역이 쿠버네티스 파드 네트워크의 기본 CIDR 이다. 팀은 두 대역이 서로 통신할 수 있다고 가정하고 잘못된 구성을 배포하려 했고, 그래서 노드 풀을 다시 만들지 못했다. 원래 클러스터를 지우자 공개 IP 를 담고 있던 노드 리소스 그룹도 함께 지워져 공개 IP 가 사라졌다.\n\n팀은 11:16 부터 13:16 UTC 까지 두 시간 동안 네트워크 설정을 고쳐 클러스터를 처음부터 다시 만들었다. 파드 CIDR 을 겹치지 않는 대역으로 따로 지정하자 모든 것이 제대로 동작했다. 15:17 UTC 에 손으로 한 재구성 작업을 PR 로 올려 반영했고, 15:25 UTC 에 모든 서비스가 정상으로 돌아왔다. 서비스의 공개 IP 는 20.7.178.24 와 2603:1030:408:5::15a 로 바뀌었다."},"trigger":{"en":"After the upgrade to Kubernetes 1.25 changed the range of the pods' originating IP and LDAP access was blocked, a fix (Azure PR 431) deployed at 10:55 UTC to set a proper set of pod IP ranges removed all node pools of the cluster.","ko":"1.25 업그레이드 뒤 파드의 출발 IP 대역이 바뀌어 LDAP 접근이 막히자, 파드 IP 대역을 지정하는 수정인 Azure PR 431 을 10:55 UTC 에 배포했다. 이 변경으로 노드 풀이 모두 지워졌고 다시 만들어지지 않았다."},"severity":"unknown","symptoms":["network-unreachable","resources-deleted","cluster-creation-stuck","service-unavailable"],"timeline":{"detected_after":null,"resolved_after":"4h 20m"},"date_kind":"incident","detection":{"en":"After the upgrade, at 10:30 UTC, the team noticed that services inside the cluster, such as accounts.jenkins.io, could not reach the LDAP service.","ko":"10:30 UTC 에 1.25 업그레이드를 마친 뒤 팀이 클러스터 안 서비스가 LDAP 서비스에 닿지 못한다는 것을 알아챘다."},"components":["node-pool","cni-plugin","cloud-load-balancer"],"root_cause":"config-change","remediation":[{"text":{"en":"Created the cluster again from scratch with a fixed network setup","ko":"네트워크 설정을 고쳐 클러스터를 처음부터 다시 만들었다. 11:16 부터 13:16 UTC 까지 두 시간이 걸렸다."}},{"text":{"en":"Set a custom pod CIDR in a range separate from the virtual network","ko":"파드 CIDR 을 가상 네트워크와 겹치지 않는 별도 대역으로 지정했다."}},{"text":{"en":"Moved the services and their DNS records to new public IPs","ko":"서비스의 공개 IP 와 DNS 레코드를 새 주소 20.7.178.24 와 2603:1030:408:5::15a 로 바꿨다."}},{"text":{"en":"Pushed a pull request that recorded the manual rebuild, including the IP setup, in code","ko":"15:17 UTC 에 IP 설정을 포함해 클러스터를 손으로 다시 만든 작업을 PR 로 올려 코드에 반영했다."}}],"action_items":[{"text":{"en":"Protect the public IPs from deletion with a Management Lock","ko":"Management Lock 을 걸어 공개 IP 가 지워지지 않게 한다."}},{"text":{"en":"Keep the public IPs in a separate resource group and point the Kubernetes-managed load balancers to it with the service.beta.kubernetes.io/azure-load-balancer-resource-group annotation","ko":"공개 IP 를 별도 리소스 그룹에 두고, 쿠버네티스가 관리하는 로드 밸런서가 그 그룹을 쓰도록 service.beta.kubernetes.io/azure-load-balancer-resource-group 애너테이션으로 설정한다."}},{"text":{"en":"Improve network diagrams and documentation so possible overlaps are visible when preparing operations","ko":"작업을 준비할 때 네트워크 구성과 대역이 겹칠 가능성을 쉽게 볼 수 있도록 네트워크 다이어그램과 문서를 개선한다."}},{"text":{"en":"Avoid changing the configuration of all AKS node pools at once","ko":"AKS 노드 풀 설정을 한꺼번에 바꾸지 않는다. 첫 노드 풀에서 문제를 잡았다면 전체 장애를 피할 수 있었다. arm64 노드 풀에서 PR-3623 으로 이 작업을 하고 있다."}}],"contributing":["assumption-unverified","no-staged-rollout","no-safeguard-on-destructive-change"],"recurrence_of":null,"symptoms_text":{"en":"On 7 July 2023 from 11:05 to 15:25 UTC many public Jenkins infrastructure services were completely down, including get.jenkins.io, plugins.jenkins.io, accounts.jenkins.io, javadoc.jenkins.io and incrementals.jenkins.io, while ci.jenkins.io, issues.jenkins.io, repo.jenkins-ci.org and www.jenkins.io were partly or completely disrupted.\n\nIt started at 10:30 UTC, after a successful upgrade of the public Kubernetes cluster in Azure to 1.25: services inside the cluster, such as accounts.jenkins.io, could not reach the LDAP service. The pods' originating IP was now in a different range than before, and IP restrictions blocked the requests.\n\nThe fix deployed at 10:55 UTC to set a proper set of pod IP ranges removed all the node pools and failed to re-create them, so every service in the cluster went down. The re-creation failed because the cluster's virtual network, 10.244.0.0/16, overlapped 10.244.0.0/24, the default pod CIDR in Azure when kubenet is used.\n\nWhen the original cluster was deleted, its public IP addresses were removed with it, so the services came back on new addresses, 20.7.178.24 and 2603:1030:408:5::15a, and users behind corporate networks had to update their DNS, proxy and firewall settings.","ko":"2023-07-07 11:05 UTC 부터 15:25 UTC 까지 Jenkins 인프라의 공개 서비스 여럿이 완전히 멈췄다. accounts.jenkins.io, get.jenkins.io, plugins.jenkins.io 를 비롯해 Azure 의 공개 쿠버네티스 클러스터에서 돌던 서비스가 모두 내려갔다.\n\n완전히 멈춘 공개 서비스는 accounts.jenkins.io, fallback.get.jenkins.io, get.jenkins.io, incrementals.jenkins.io, javadoc.jenkins.io, plugin-health.jenkins.io, plugin-site-issues.jenkins.io, plugins.origin.jenkins.io, plugins.jenkins.io, rating.jenkins.io, repo.azure.jenkins.io, reports.jenkins.io, stories.jenkins.io, uplink.jenkins.io, weekly.ci.jenkins.io, www.origin.jenkins.io 였다. 내부 서비스인 ldap.jenkins.io 와 infra.ci.jenkins.io 의 *.jenkins.io PR 미리보기도 완전히 멈췄다. ci.jenkins.io, infra.ci.jenkins.io, issues.jenkins.io, plugins.jenkins.io, repo.jenkins-ci.org, www.jenkins.io 는 일부 또는 전부 끊겼다.\n\n그보다 앞서 10:30 UTC 에 클러스터를 1.25 로 올린 뒤 accounts.jenkins.io 같은 클러스터 안 서비스가 LDAP 서비스에 닿지 못했다. 파드의 출발 IP 가 전과 다른 대역이어서 IP 제한에 막혔다.\n\n이를 고치려고 10:55 UTC 에 파드 IP 대역을 지정하는 변경을 배포하자 노드 풀이 모두 지워졌고 다시 만들어지지 않았다. 그 클러스터에서 돌던 서비스가 모두 멈췄다.\n\n복구 뒤 서비스들의 공개 IP 가 20.7.178.24 와 2603:1030:408:5::15a 로 바뀌었다. 허용 목록을 쓰는 회사 방화벽 뒤의 사용자는 DNS, 프록시, 방화벽 설정을 바꿔야 서비스에 닿을 수 있었다."},"updated_at":"2026-11-14T12:34:12.039875Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0473","org_slug":"jenkins-project"}