Certified Kubernetes Security Specialist (CKS) #14 Image scan: Trivy, Kubesec, KubeLinter
CKS 시리즈는 도메인 Supply Chain Security를 다루는 중입니다. 앞선 #13 Minimal images: distroless, scratch에서 이미지에 들어가는 것을 최소로 줄여 공격 표면을 좁혔다면, 이번 글은 그 이미지 안에 어떤 취약점이 남아 있는지를 어떻게 찾아내는가를 정리하겠습니다.
이미지를 아무리 작게 만들어도, 그 안의 OS 패키지나 언어 라이브러리에 알려진 취약점(CVE)이 박혀 있으면 그 이미지는 위험합니다. 공급망 보안의 핵심은 무엇이 들어 있는지 알고, 알려진 취약점을 배포 전에 걸러내는 것입니다. 이 글에서는 이미지의 CVE를 찾는 Trivy, 매니페스트의 보안 설정을 점수로 평가하는 Kubesec, 매니페스트의 안티패턴을 정적 분석하는 KubeLinter를 다루겠습니다.
두 종류의 스캔: 이미지 vs 매니페스트 #
이미지 스캔이라고 뭉뚱그려 부르지만, CKS에서 다루는 도구는 검사하는 대상이 둘로 나뉩니다. 이 구분을 먼저 잡아야 어떤 작업에 어떤 도구를 꺼낼지 헷갈리지 않습니다.
| 검사 대상 | 무엇을 찾는가 | 도구 |
|---|---|---|
| 이미지 내용 | OS 패키지,라이브러리에 박힌 알려진 취약점(CVE) | Trivy |
| 매니페스트 설정 | securityContext,권한 등 위험한 워크로드 설정 | Kubesec, KubeLinter |
Trivy는 이미지 안에 든 소프트웨어의 버전을 취약점 데이터베이스와 대조해 CVE를 찾습니다. 반면 Kubesec과 KubeLinter는 이미지 자체가 아니라 YAML 매니페스트의 설정을 봅니다. 같은 nginx 이미지라도 Trivy는 그 안의 CVE를 보고, Kubesec은 그것을 어떤 securityContext로 돌리는지를 봅니다. 둘은 서로를 대체하지 않고 보완합니다.
Trivy: 이미지 취약점 스캐너 #
Trivy는 Aqua Security가 만든 오픈소스 스캐너로, CKS 시험에서 이미지 취약점을 다루는 표준 도구입니다. 빠르고, 설치가 단순하고, 결과가 읽기 쉬워 시험 환경에 잘 맞습니다.
무엇을 스캔하는가 #
Trivy는 한 가지가 아니라 여러 대상을 스캔합니다. 시험에서는 주로 첫 번째인 image 스캔이 나오지만, 나머지도 한 번씩 봐 두면 좋습니다.
| 하위 명령 | 대상 | 용도 |
|---|---|---|
trivy image | 컨테이너 이미지 | OS 패키지,언어 라이브러리의 CVE |
trivy filesystem | 로컬 디렉터리,파일 | 소스 트리나 추출한 루트 파일시스템 |
trivy repo | Git 저장소 | 원격,로컬 리포지토리의 의존성 |
trivy config | IaC,매니페스트 | Dockerfile,쿠버네티스 설정의 오설정 |
기본 이미지 스캔 #
가장 기본 형태는 이미지 이름만 넘기는 것입니다.
trivy image nginx:1.18이렇게 하면 그 이미지에 든 모든 패키지의 취약점을 전부 출력합니다. 그런데 LOW나 UNKNOWN까지 다 나오면 결과가 너무 길어 정작 중요한 것을 놓치기 쉽습니다. 그래서 시험에서는 거의 항상 심각도를 좁혀서 봅니다.
trivy image --severity HIGH,CRITICAL nginx:1.18--severity로 HIGH와 CRITICAL만 추리면, 즉시 조치가 필요한 취약점만 남습니다. 심각도 값은 UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL 다섯 단계입니다.
결과 읽기 #
Trivy의 출력은 이미지에 든 타깃(예: OS 패키지, 언어 라이브러리)별로 표를 나눠서 보여줍니다. 각 행의 핵심 열은 다음과 같습니다.
| 열 | 의미 |
|---|---|
| Library | 취약점이 있는 패키지 이름 |
| Vulnerability | CVE 식별자(예: CVE-2023-12345) |
| Severity | 심각도 등급 |
| Installed Version | 현재 이미지에 설치된 버전 |
| Fixed Version | 취약점이 고쳐진 버전(비어 있으면 아직 패치 없음) |
여기서 가장 중요한 것은 Severity로 위험을 가늠하고, Fixed Version으로 조치 가능 여부를 판단하는 것입니다. Fixed Version이 있으면 그 버전 이상으로 패키지나 베이스 이미지를 올리면 되고, 비어 있으면 아직 패치가 없는 취약점이라 다른 완화책이 필요합니다.
출력 형식과 개수만 세기 #
기본은 사람이 읽기 좋은 표(table)지만, 자동화에는 JSON이 편합니다. 시험에서 “취약점 개수"를 요구하면 형식을 바꿔 세는 것이 빠릅니다.
# JSON으로 출력
trivy image --format json --output result.json nginx:1.18
# CRITICAL만 추려 표로
trivy image --severity CRITICAL nginx:1.18exit-code로 CI gate 만들기 #
Trivy의 진가는 CI 파이프라인에서 취약점이 있으면 빌드를 멈추는 데 있습니다. --exit-code를 주면, 조건에 맞는 취약점이 발견될 때 Trivy가 0이 아닌 종료 코드를 반환합니다.
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:1.0이 명령은 HIGH 또는 CRITICAL 취약점이 하나라도 있으면 종료 코드 1로 끝납니다. CI에서 이 종료 코드를 검사하면, 취약한 이미지가 배포 단계로 넘어가는 것을 자동으로 막을 수 있습니다. --ignore-unfixed를 함께 주면 아직 패치가 없는 취약점은 게이트에서 제외해, 당장 고칠 수 있는 것에만 빌드를 멈추게 할 수 있습니다.
trivy image --exit-code 1 --ignore-unfixed --severity CRITICAL myapp:1.0DB 갱신과 오프라인 #
Trivy는 처음 실행할 때 취약점 DB를 내려받습니다. 시험 환경에서는 네트워크가 제한될 수 있으므로, DB가 이미 받아져 있는지 확인하는 감각이 필요합니다. --skip-db-update로 갱신을 건너뛰면 받아 둔 DB로만 스캔합니다.
Kubesec: 매니페스트 보안 점수 #
Kubesec은 이미지가 아니라 쿠버네티스 매니페스트의 보안 설정을 점수로 평가하는 도구입니다. 매니페스트를 넣으면 점수와 함께, 점수를 깎은 위험 항목과 점수를 올릴 권고 항목을 알려줍니다.
kubesec scan pod.yaml출력은 JSON이며 핵심은 다음과 같습니다.
score. 매니페스트의 보안 점수. 높을수록 안전scoring.advise. 점수를 올리려면 더하면 좋은 설정(권고)scoring.passed. 이미 잘 적용된 설정scoring.critical. 즉시 고쳐야 할 위험 설정
Kubesec이 점수를 매기는 기준은 대부분 securityContext의 강화 항목입니다. 예를 들어 다음 같은 설정이 점수를 올립니다.
| 설정 | 효과 |
|---|---|
runAsNonRoot: true | root로 실행하지 않음 |
readOnlyRootFilesystem: true | 루트 파일시스템을 읽기 전용으로 |
capabilities.drop: ["ALL"] | 모든 리눅스 capability 제거 |
allowPrivilegeEscalation: false | 권한 상승 차단 |
privileged: true (감점) | 특권 컨테이너는 큰 감점 |
즉 Kubesec의 권고를 따라가면, #9 Pod Security Admission에서 본 securityContext 강화와 같은 방향으로 매니페스트가 단단해집니다. Trivy가 “이미지 안에 무엇이 위험한가"를 본다면, Kubesec은 “이 워크로드를 얼마나 안전하게 돌리는가"를 봅니다.
KubeLinter: 매니페스트 정적 분석 #
KubeLinter는 StackRox가 만든 도구로, 매니페스트와 Helm 차트를 정적 분석해 보안,운영 안티패턴을 잡아냅니다. Kubesec이 점수를 매긴다면, KubeLinter는 린터답게 규칙 위반을 목록으로 보여줍니다.
kube-linter lint deployment.yaml기본 규칙에는 다음 같은 항목이 포함됩니다.
- 컨테이너가 root로 실행되는지
readOnlyRootFilesystem이 설정되지 않았는지- resource requests,limits가 빠졌는지
- latest 태그를 쓰는지
- 위험한 capability를 가졌는지
KubeLinter는 CI에 붙여 매니페스트가 머지되기 전에 안티패턴을 거르는 용도로 잘 맞습니다. 위반이 있으면 종료 코드가 0이 아니므로, Trivy의 exit-code와 같은 방식으로 게이트를 만들 수 있습니다.
세 도구의 역할 차이 #
이 글에서 다룬 세 도구를 한 표로 정리하면, 시험에서 작업의 키워드만 보고 어떤 도구를 꺼낼지 바로 판단할 수 있습니다.
| 도구 | 검사 대상 | 찾는 것 | 출력 형태 | 게이트 |
|---|---|---|---|---|
| Trivy | 컨테이너 이미지 | OS,라이브러리의 CVE | 취약점 표/JSON | --exit-code |
| Kubesec | 매니페스트 | securityContext 강화 정도 | 보안 점수 | 점수 임계값 |
| KubeLinter | 매니페스트,Helm | 보안,운영 안티패턴 | 위반 목록 | 종료 코드 |
핵심 구분은 Trivy는 이미지 CVE, 나머지 둘은 매니페스트 설정입니다. 작업 지문에 “CVE”, “취약점”, “심각도”, “이미지 스캔"이 나오면 Trivy이고, “securityContext”, “보안 점수”, “매니페스트 검사"가 나오면 Kubesec이나 KubeLinter입니다.
시험 단골 작업 #
1) 특정 심각도의 취약점을 가진 이미지 찾기 #
여러 이미지가 주어지고, 그중 CRITICAL 취약점이 있는 이미지를 골라내라는 유형이 자주 나옵니다. 각 이미지를 심각도를 좁혀 스캔하면 됩니다.
trivy image --severity CRITICAL nginx:1.18
trivy image --severity CRITICAL nginx:1.27CRITICAL이 나오는 이미지가 위험한 이미지입니다. “취약점이 가장 적은 이미지를 고르라"는 변형도 있으므로, 결과 개수를 비교하는 감각이 필요합니다.
2) 취약한 이미지를 안전한 버전으로 교체 #
위험한 이미지를 찾았으면, 그 이미지를 쓰는 Deployment를 CVE가 없거나 더 적은 버전으로 바꾸는 것이 다음 작업입니다.
# 후보 버전들을 스캔해 안전한 것을 확인
trivy image --severity HIGH,CRITICAL nginx:1.27
# 매니페스트의 이미지 태그를 안전한 버전으로 교체 후 적용
kubectl set image deployment/web nginx=nginx:1.27교체한 뒤에는 새 이미지를 다시 한번 스캔해, 의도한 대로 심각도 높은 취약점이 사라졌는지 확인하는 것이 좋습니다.
3) 매니페스트를 점수로 점검하기 #
매니페스트가 주어지고 보안 점수를 확인하거나, 권고 항목을 적용해 점수를 올리라는 유형도 있습니다.
kubesec scan pod.yamlscoring.advise에 나온 항목(runAsNonRoot, readOnlyRootFilesystem 등)을 securityContext에 더하면 점수가 올라갑니다.
시험 포인트 #
- Trivy는 이미지 CVE 스캐너입니다.
trivy image --severity HIGH,CRITICAL <이미지>가 기본형이고,--severity로 심각도를 좁히는 것이 시험의 거의 모든 작업에 쓰입니다. - 결과는 Severity와 Fixed Version으로 읽습니다. Fixed Version이 있으면 그 버전 이상으로 올려 조치하고, 비어 있으면 아직 패치가 없는 취약점입니다.
--exit-code 1로 CI gate를 만듭니다. 지정 심각도의 취약점이 있으면 0이 아닌 종료 코드로 끝나, 취약한 이미지의 배포를 막습니다.--ignore-unfixed로 패치 없는 취약점은 제외할 수 있습니다.- Kubesec은 매니페스트 보안 점수입니다.
kubesec scan이 securityContext 강화 정도를 점수로 매기고,scoring.advise가 권고를 줍니다. - KubeLinter는 매니페스트 정적 분석입니다.
kube-linter lint가 root 실행,읽기 전용 미설정,latest 태그 같은 안티패턴을 위반 목록으로 보여줍니다. - 검사 대상으로 도구를 구분합니다. CVE,취약점이면 Trivy, securityContext,매니페스트 설정이면 Kubesec이나 KubeLinter입니다.
정리 #
이번 글에서 잡은 것:
- 이미지 스캔은 두 종류입니다. Trivy는 이미지 내용의 CVE를, Kubesec,KubeLinter는 매니페스트 설정을 봅니다.
- Trivy는
image,filesystem,repo,config를 스캔하며,--severity로 심각도를 좁히고--exit-code로 CI gate를 만듭니다. - Kubesec은 매니페스트의 securityContext 강화 정도를 점수로 평가하고 권고를 줍니다.
- KubeLinter는 매니페스트와 Helm 차트를 정적 분석해 안티패턴을 위반 목록으로 잡습니다.
- 시험 단골은 특정 심각도의 취약점을 가진 이미지를 찾고, 안전한 버전으로 교체하는 작업입니다.
#13 Minimal images에서 이미지를 줄이고, 이번 글에서 그 이미지의 취약점을 찾아냈습니다. 이제 남은 질문은 그 이미지가 정말 내가 만든 것이 맞는지, 그리고 그 안에 무엇이 들어 있는지를 어떻게 증명하는가입니다.
다음: 이미지 서명 #
이미지를 스캔해 취약점을 걸러냈더라도, 누군가 중간에서 이미지를 바꿔치기하면 스캔은 무의미해집니다. 다음 글에서는 이미지의 출처와 무결성을 증명하는 장치를 다루겠습니다.
#15 이미지 서명: cosign, SBOM에서는 cosign으로 이미지에 서명하고 admission 단계에서 서명을 검증해 서명되지 않은 이미지의 배포를 막는 법, 그리고 이미지에 든 모든 구성요소의 목록인 SBOM(Software Bill of Materials)을 생성,활용하는 법까지 직접 만들어 보며 정리하겠습니다.