What Does apt Look At to Decide
한국어 원문으로 표시합니다.
한 줄 요약
apt 의 모든 판단은 로컬에 캐시된 저장소 색인에서 나온다. 색인이 낡으면 apt 는 낡은 세계를 본다.
왜 이게 필요했나
apt-get install nginx 를 쳤는데 "패키지를 찾을 수 없습니다" 가 나온다. 저장소에는 분명히 있다. 이때 십중팔구 원인은 apt-get update 를 안 한 것이다.
apt 는 설치할 때 저장소에 물어보지 않는다. /var/lib/apt/lists/ 에 받아 둔 색인 파일만 보고 의존성을 계산한 다음, 계산이 끝난 뒤에야 실제 .deb 를 내려받는다. 이 분리가 apt 를 빠르게 만들지만, 동시에 "저장소에는 있는데 안 보인다" 의 원인이 된다.
어떻게 동작하나
한 번의 설치는 네 단계다.
- 색인 읽기 —
/etc/apt/sources.list와sources.list.d/*.list에 적힌 저장소의Packages파일을 읽는다. - 후보 선정 — 같은 패키지가 여러 저장소에 있으면 핀 우선순위(priority) 로 고른다.
apt-cache policy <패키지>가 이 판단 결과를 그대로 보여 준다. - 의존성 해결 — Depends 와 Recommends 를 따라가며 설치 집합을 만든다.
- 내려받기와 unpack/configure — dpkg 에게 넘긴다.
apt-cache policy 출력을 읽는 법이 핵심이다.
nginx:
Installed: (none)
Candidate: 1.24.0-2ubuntu7
Version table:
1.24.0-2ubuntu7 500
500 http://archive.ubuntu.com/ubuntu noble/main amd64 Packages
왼쪽 숫자가 버전, 오른쪽 숫자가 우선순위다. 기본값은 500 이고, 여기에 손을 대는 방법이 두 가지 있다.
- hold (
apt-mark hold) — "이 패키지는 건드리지 마라". dpkg 레벨의 표시라서 업그레이드에서 통째로 제외된다. 되돌리려면apt-mark unhold. - pin (
/etc/apt/preferences.d/*.pref) — "이 출처/버전을 이만큼 선호하라". 우선순위 1001 이상이면 다운그레이드까지 허용한다.
둘은 목적이 다르다. hold 는 "지금 이 버전에서 멈춰" 이고, pin 은 "여러 저장소 중 이쪽을 봐" 다. 사내 미러와 공식 저장소를 함께 쓰는 환경에서는 pin 이 필수다.
현장에서 만나는 모습
쿠버네티스 노드의 kubelet. 클러스터 버전을 통제해야 하므로 apt-mark hold kubelet kubeadm kubectl 은 사실상 표준 절차다. 이걸 안 걸어 두면 어느 날 무심코 실행한 apt-get upgrade 가 노드 하나만 마이너 버전을 올려 버리고, 그 노드에서만 파드가 안 뜬다.
사내 미러의 배신. 사내 미러를 sources.list 에 추가했는데 여전히 공식 저장소에서 받아 온다. 우선순위가 같으면 apt 는 버전이 높은 쪽을 고르기 때문이다. 미러를 강제하려면 pin 을 걸어야 한다.
업그레이드가 무엇을 하는지 알고 친다
apt-get upgrade 와 apt-get dist-upgrade(요즘은 apt full-upgrade)는 이름이 비슷하지만 하는 일이 다르고, 그 차이가 운영에서 사고로 이어진다.
upgrade— 이미 깔린 패키지를 새 버전으로 올리되, 무언가를 지워야 하거나 새로 깔아야 하면 그 패키지는 건너뛴다. 그래서 안전하지만, "업그레이드했는데 몇 개가 그대로 남았다" 는 상태가 된다.full-upgrade— 필요하면 지우고 깐다. 커널 메타패키지처럼 의존성이 바뀌는 것을 실제로 올리려면 이쪽이 필요하지만, 무엇이 지워지는지 반드시 눈으로 확인해야 한다.
그래서 운영 서버에서는 두 단계로 나눈다. 먼저 -s(모의 실행)로 무엇이 바뀌는지 보고, 목록에 낯선 것이 없을 때만 실제로 친다. 특히 The following packages will be REMOVED 줄은 매번 읽어야 한다. 의존성이 꼬인 상태에서 apt 가 제안하는 해법이 "이 서비스를 지우면 됩니다" 인 경우가 실제로 있다.
무인 업그레이드도 짚어 둔다. 보안 갱신을 자동으로 적용하는 것은 대개 옳은 선택이지만, 재시작이 필요한 갱신을 어떻게 처리할지 정해 두지 않으면 두 가지 중 하나가 된다. 재시작하지 않아 갱신된 라이브러리가 적용되지 않은 채로 남거나(취약점이 그대로다), 아무 때나 재시작해 서비스가 끊긴다. 어느 프로세스가 옛 라이브러리를 들고 있는지 확인하는 도구가 있으니, 그것으로 목록을 뽑아 계획된 창에서 재시작하는 편이 낫다.
마지막으로 apt 와 apt-get 의 차이. 사람이 쓸 때는 apt 가 편하지만, 스크립트에는 apt-get 을 쓴다. apt 는 사람이 읽기 좋게 출력 형식과 동작을 바꿀 수 있다고 명시되어 있어서, 어느 날 형식이 달라지면 그것을 파싱하던 스크립트가 조용히 깨진다.
다음 실습에서 할 것
/opt/localrepo 오프라인 저장소를 상대로 검색·설치·제거를 하고, hold 와 pin 을 직접 걸어 apt-cache policy 출력이 어떻게 바뀌는지 확인한다.