
👀 쿠버네티스 클러스터 리소스 정리 도구
Popeye는 라이브 Kubernetes 클러스터를 스캔하여 배포된 리소스 및 구성의 잠재적 문제를 보고하는 유틸리티입니다. Kubernetes 환경이 성장함에 따라 클러스터를 조율하는 수많은 매니페스트와 정책을 사람이 추적하는 것이 점점 어려워지고 있습니다. Popeye는 디스크에 있는 것이 아니라 배포된 내용을 기준으로 클러스터를 스캔합니다. 클러스터를 린팅하여 잘못된 구성, 오래된 리소스를 감지하고 모범 사례가 적용되었는지 확인하여 향후 문제를 방지합니다. 실제 Kubernetes 클러스터를 운영할 때 직면하는 인지적 과부하를 줄이는 것을 목표로 합니다. 또한 클러스터에서 메트릭 서버를 사용하는 경우 잠재적인 리소스 과다/부족 할당을 보고하고 클러스터 용량이 부족할 때 경고를 시도합니다. Popeye는 읽기 전용 도구이며 어떤 식으로든 Kubernetes 리소스를 변경하지 않습니다!
스캔 보고서를 HTML로 덤프할 수 있습니다.
Popeye는 Prometheus 메트릭을 게시합니다. 이 저장소에는 시작할 수 있는 샘플 Popeye 대시보드를 제공했습니다.
Popeye는 Linux, OSX 및 Windows 플랫폼에서 사용할 수 있습니다.
Linux, Windows 및 Mac용 바이너리는 릴리스 페이지에서 tarball로 제공됩니다.
Homebrew/LinuxBrew를 사용하는 OSX/Unit의 경우 ```shell brew install derailed/popeye/popeye
go install 사용하기
go install github.com/derailed/popeye@latest
소스에서 빌드하기 Popeye는 go 1.21+로 빌드되었습니다. 소스에서 Popeye를 빌드하려면 다음을 수행해야 합니다:
저장소를 클론합니다.
go.mod 파일에 다음 명령어를 추가합니다.
replace (
github.com/derailed/popeye => MY_POPEYE_CLONED_GIT_REPO
)
실행 파일을 빌드하고 실행합니다.
go run main.go
급한 분들을 위한 빠른 레시피: ```shell
git clone https://github.com/derailed/popeye cd popeye
make build
popeye
Popeye는 256색 터미널 모드를 사용합니다. `Nix 시스템에서는 TERM이 적절히 설정되었는지 확인하세요.
export TERM=xterm-256color
Popeye를 광범위하게 사용하거나 spinach yaml 구성을 사용하여 린터를 조정할 수 있습니다. Popeye 구성 파일에 대한 자세한 내용은 아래에 있습니다.```shell
popeye version
popeye
fred namespacepopeye -n fred
popeye -A
popeye -f spinach.yaml
popeye --context olive
popeye -n ns1 -s pod,svc --logs none
popeye -n ns1 --logs /tmp/fred.log -v4
popeye help
---
## 린터(Linters)
Popeye는 모범 사례와 잠재적인 문제를 위해 클러스터를 스캔합니다.
현재 Popeye는 선별된 특정 Kubernetes 리소스 집합만 검사합니다.
더 많은 것이 곧 추가될 예정입니다!
Popeye를 더욱 향상시키기 위해 Kubernetes 커뮤니티의 기여를 기대합니다.
린터의 목표는 잘못된 구성을 찾아내는 것입니다. 예를 들어
포트 불일치, 죽었거나 사용되지 않는 리소스, 메트릭 사용량,
프로브, 컨테이너 이미지, RBAC 규칙, 네이키드 리소스 등이 있습니다.
Popeye는 또 다른 정적 분석 도구가 아닙니다. 실제 클러스터에서 Kubernetes 리소스를 실행하고 검사하여
실제 환경의 리소스를 린트합니다!
다음은 사용 가능한 린터 목록입니다:
| | 리소스 | 린터 | 별칭 |
|----|-------------------------|------------------------------------------------------------------------------|-------------|
| 🛀 | Node | | no |
| | | 조건 (준비 안 됨, 메모리/디스크 부족, 네트워크, PID 등) | |
| | | 노드 테인트를 참조하는 Pod 톨러레이션 | |
| | | CPU/MEM 사용량 메트릭, 한도 초과 시 알림 (기본 CPU/MEM 80%) | |
| 🛀 | Namespace | | ns |
| | | 비활성 | |
| | | 죽은 네임스페이스 | |
| 🛀 | Pod | | po |
| | | Pod 상태 | |
| | | 컨테이너 상태 | |
| | | ServiceAccount 존재 여부 | |
| | | 설정된 CPU/MEM 한도를 초과하는 컨테이너의 CPU/MEM (기본 CPU/MEM 80%) | |
| | | 태그가 없는 컨테이너 이미지 | |
| | | `latest` 태그를 사용하는 컨테이너 이미지 | |
| | | 리소스 요청/제한 존재 여부 | |
| | | 프로브 활성화/준비 상태 존재 여부 | |
| | | 명명된 포트와 그 참조 | |
| 🛀 | Service | | svc |
| | | 엔드포인트 존재 여부 | |
| | | 일치하는 Pod 레이블 | |
| | | 명명된 포트와 그 참조 | |
| 🛀 | ServiceAccount | | sa |
| | | 사용되지 않음, 잠재적으로 사용되지 않는 SA 감지 | |
| 🛀 | Secrets | | sec |
| | | 사용되지 않음, 잠재적으로 사용되지 않는 시크릿 또는 관련 키 감지 | |
| 🛀 | ConfigMap | | cm |
| | | 사용되지 않음, 잠재적으로 사용되지 않는 ConfigMap 또는 관련 키 감지 | |
| 🛀 | Deployment | | dp, deploy |
| | | 사용되지 않음, Pod 템플릿 검증, 리소스 사용량 | |
| 🛀 | StatefulSet | | sts |
| | | 사용되지 않음, Pod 템플릿 검증, 리소스 사용량 | |
| 🛀 | DaemonSet | | ds |
| | | 사용되지 않음, Pod 템플릿 검증, 리소스 사용량 | |
| 🛀 | PersistentVolume | | pv |
| | | 사용되지 않음, 볼륨 바인딩 또는 볼륨 오류 확인 | |
| 🛀 | PersistentVolumeClaim | | pvc |
| | | 사용되지 않음, 바인딩 또는 볼륨 마운트 오류 확인 | |
| 🛀 | HorizontalPodAutoscaler | | hpa |
| | | 사용되지 않음, 사용량, 최대 버스트 검사 | |
| 🛀 | PodDisruptionBudget | | |
| | | 사용되지 않음, minAvailable 설정 확인 | pdb |
| 🛀 | ClusterRole | | |
| | | 사용되지 않음 | cr |
| 🛀 | ClusterRoleBinding | | |
| | | 사용되지 않음 | crb |
| 🛀 | Role | | |
| | | 사용되지 않음 | ro |
| 🛀 | RoleBinding | | |
| | | 사용되지 않음 | rb |
| 🛀 | Ingress | | |
| | | 유효성 검사 | ing |
| 🛀 | NetworkPolicy | | |
| | | 유효성, 오래됨, 보호 상태 확인 | np |
| 🛀 | PodSecurityPolicy | | |
| | | 유효성 검사 | psp |
| 🛀 | Cronjob | | |
| | | 유효성, 일시 중단됨, 실행 확인 | cj |
| 🛀 | Job | | |
| | | Pod 검사 | job |
| 🛀 | GatewayClass | | |
| | | 유효성, 사용되지 않음 | gwc |
| 🛀 | Gateway | | |
| | | 유효성, 사용되지 않음 | gw |
| 🛀 | HTTPRoute | | |
| | | 유효성, 사용되지 않음 | gwr |
전체 코드 목록은 [코드 문서](https://github.com/derailed/popeye/blob/HEAD/docs/codes.md)에서 확인할 수 있습니다.
---
## 스캔 저장
Popeye 보고서를 파일로 저장하려면 명령에 `--save` 플래그를 전달하세요.
기본적으로 임시 디렉토리를 생성하고 그곳에 스캔 보고서를 저장합니다.
임시 디렉토리 경로는 STDOUT에 출력됩니다.
보고서 출력 디렉토리를 직접 지정해야 하는 경우
`POPEYE_REPORT_DIR` 환경 변수를 사용할 수 있습니다. 최종 경로는 `<POPEYE_REPORT_DIR>/<cluster>/<context>`가 됩니다.
기본적으로 출력 파일 이름은 `lint_<cluster-name>_<time-UnixNano>.<output-extension>` 형식을 따릅니다 (예: "lint-mycluster-1594019782530851873.html").
보고서 출력 파일 이름도 지정하려면 `--output-file` 플래그에 원하는 파일 이름을 매개변수로 전달하면 됩니다.
작업 디렉토리에 보고서를 저장하는 예시:```shell
POPEYE_REPORT_DIR=$(pwd) popeye --save
작업 디렉토리에 보고서를 HTML 형식으로 "report.html"이라는 이름으로 저장하는 예 :```shell POPEYE_REPORT_DIR=$(pwd) popeye --save --out html --output-file report.html
### S3 객체 스토리지에 저장
또한, `--s3-bucket` 플래그를 제공하여 생성된 보고서를 AWS S3 또는 Minio 객체 스토리지에 푸시할 수 있습니다.
매개변수의 경우 보고서를 저장할 S3 버킷의 이름을 제공해야 합니다.
버킷 하위 디렉터리에 보고서를 저장하려면 버킷 매개변수를 `bucket/path/to/report`로 제공하세요.
S3에 보고서 저장 예시:```shell
# AWS S3
# NOTE: You must provide env vars for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
# This will create bucket my-popeye if not present and upload a popeye json report to /fred/scan.json
popeye --s3-bucket s3://my-popeye/fred --s3-region us-west-2 --out json --save --output-file scan.json
# Minio Object Store
# NOTE: You must provide env vars for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and a minio server URI
# This will create bucket my-popeye if not present and upload a popeye json report to /fred/scan.json
popeye --s3-bucket minio://my-popeye/fred --s3-region us-east --s3-endpoint localhost:9000 --out json --save --output-file scan.json
또한 공식 Quay Docker 저장소에서 직접 컨테이너를 실행하여 Popeye를 컨테이너로 실행할 수 있습니다. Docker 컨테이너를 실행할 때 기본 명령은 popeye이므로 지원되는 CLI 플래그를 사용하여 스캔을 사용자 정의할 수 있습니다. 클러스터에 액세스하려면 -v를 사용하여 로컬 kubeconfig 디렉토리를 컨테이너에 매핑하십시오:```shell
docker run --rm -it -v $HOME/.kube:/root/.kube quay.io/derailed/popeye --context foo -n bar
위의 docker 명령을 `--rm`과 함께 실행하면 Popeye가 종료될 때 컨테이너가 삭제됩니다.
`--save`를 사용하면 컨테이너 내 /tmp에 출력을 기록한 후 popeye가 종료될 때 컨테이너를 삭제하므로 출력을 잃게 됩니다 ;(
이를 해결하려면 호스트의 /tmp를 컨테이너의 /tmp에 마운트하세요.
> 참고: `POPEYE_REPORT_DIR` 환경 변수를 설정하여 기본 출력 디렉터리 위치를 재정의할 수 있습니다.```shell
docker run --rm -it \
-v $HOME/.kube:/root/.kube \
-e POPEYE_REPORT_DIR=/tmp/popeye \
-v /tmp:/tmp \
quay.io/derailed/popeye --context foo -n bar --save --output-file my_report.txt
# Docker has exited, and the container has been deleted, but the file
# is in your /tmp directory because you mapped it into the container
cat /tmp/popeye/my_report.txt
<snip>
Popeye는 다양한 형식으로 린터 보고서를 생성할 수 있습니다. -o CLI 옵션을 사용하여 원하는 형식을 선택할 수 있습니다.
Popeye는 스캔 결과에서 직접 프로메테우스 메트릭을 게시할 수 있습니다. 프로메테우스 푸시게이트웨이와 자격 증명에 접근할 수 있어야 합니다.
참고! 이는 사용자 피드백과 사용량에 따라 변경될 수 있습니다!!
메트릭을 게시하려면 추가 CLI 인수가 있어야 합니다.```shell
popeye --push-gtwy-url http://localhost:9091
popeye -o html --save --push-gtwy-url http://localhost:9091
### PopProm 메트릭
다음 Popeye prometheus 메트릭이 게시됩니다:
* `popeye_severity_total` [게이지] 심각도에 따른 다양한 카운트를 추적합니다.
* `popeye_code_total` [게이지] Popeye의 린터 코드별 카운트를 추적합니다.
* `popeye_linter_tally_total` [게이지] 린터별 카운트를 추적합니다.
* `popeye_report_errors_total` [게이지] 스캔 오류 총계를 추적합니다.
* `popeye_cluster_score` [게이지] 스캔 보고서 점수를 추적합니다.
### PopGraf
시작하는 데 도움이 되도록 이 저장소에서 샘플 [Grafana](https://grafana.com) 대시보드를 찾을 수 있습니다.
> 참고! 작업 진행 중입니다. UX/grafana/promql 능력이 있으시면 자유롭게 기여해 주세요.
---
## SpinachYAML
`-f` 옵션을 통해 스피낙 YAML 구성 파일을 지정하여 린터를 추가로 구성할 수 있습니다. 이 파일은 컨테이너 사용률 임계값, 특정 린터 구성, 그리고 린터에서 제외할 리소스 및 코드를 지정할 수 있습니다.
> 참고! 이 파일은 Popeye가 성숙함에 따라 변경될 수 있습니다.
`excludes` 키 아래에서 특정 리소스 또는 린터 코드를 건너뛰도록 구성할 수 있습니다.
Popeye의 린터는 k8s 리소스 이름을 따서 명명됩니다.
예를 들어 PodDisruptionBudget 린터는 `poddisruptionbudgets`으로 명명되며 `policy/v1/poddisruptionbudgets`를 스캔합니다.
> 참고! 린터는 복수 리소스 `kind` 형식을 사용하며 모든 것은 소문자로 표기됩니다.
리소스의 정규화된 이름(FQN)은 스피낙 파일에서 리소스 이름을 식별하는 데 사용됩니다. 즉, `namespace/resource_name`입니다.
예를 들어 `blee` 네임스페이스의 `fred-1234`라는 파드의 FQN은 `blee/fred-1234`가 됩니다. 이는 `fred/p1`과 `blee/p1`을 구분할 수 있게 해줍니다.
클러스터 전체 리소스의 경우 FQN은 이름과 동일합니다.
제외 규칙은 단순 문자열 일치 또는 정규 표현식일 수 있습니다. 후자의 경우 정규 표현식은 `rx:` 접두사로 지정해야 합니다.
> 참고! 정규 표현식에 주의하세요. *느슨한* 정규식 규칙으로 인해 예상보다 많은 리소스가 보고서에서 제외될 수 있습니다.
> 클러스터 리소스가 변경되면 이로 인해 최적이 아닌 스캔이 발생할 수 있습니다.
> 따라서 때때로 Popeye를 `wide open`으로 실행하여 클러스터에서 발생할 수 있는 새로운 문제를 놓치지 않도록 권장합니다.
다음은 이 릴리스에서 사용되는 예시 스피낙 파일입니다.
이 저장소의 `spinach` 디렉토리 아래에 더 완전한 eks 및 aks 기반 스피낙 파일이 있습니다.
(참고로: 프로젝트에 처음 오신 분이라면 클러스터별 스피낙 파일 PR을 추가하여 기여하는 좋은 방법이 될 수 있습니다...)```yaml
# spinach.yaml
# A Popeye sample configuration file
popeye:
# Checks resources against reported metrics usage.
# If over/under these thresholds a linter warning will be issued.
# Your cluster must run a metrics-server for these to take place!
allocations:
cpu:
underPercUtilization: 200 # Checks if cpu is under allocated by more than 200% at current load.
overPercUtilization: 50 # Checks if cpu is over allocated by more than 50% at current load.
memory:
underPercUtilization: 200 # Checks if mem is under allocated by more than 200% at current load.
overPercUtilization: 50 # Checks if mem is over allocated by more than 50% usage at current load.
# Excludes excludes certain resources from Popeye scans
excludes:
# [NEW!] Global exclude resources and codes globally of any linters.
global:
fqns: [rx:^kube-] # => excludes all resources in kube-system, kube-public, etc..
# [NEW!] Exclude resources for all linters matching these labels
labels:
app: [bozo, bono] #=> exclude any resources with labels matching either app=bozo or app=bono
# [NEW!] Exclude resources for all linters matching these annotations
annotations:
fred: [blee, duh] # => exclude any resources with annotations matching either fred=blee or fred=duh
# [NEW!] Exclude scan codes globally via straight codes or regex!
codes: ["300", "206", "rx:^41"] # => exclude issue codes 300, 206, 410, 415 (Note: regex match!)
# [NEW!] Configure individual resource linters
linters:
# Configure the namespaces linter for v1/namespaces
namespaces:
# [NEW!] Exclude these codes for all namespace resources straight up or via regex.
codes: ["100", "rx:^22"] # => exclude codes 100, 220, 225, ...
# [NEW!] Excludes specific namespaces from the scan
instances:
- fqns: [kube-public, kube-system] # => skip ns kube-pulbic and kube-system
- fqns: [blee-ns]
codes: [106] # => skip code 106 for namespace blee-ns
# Skip secrets in namespace bozo.
secrets:
instances:
- fqns: [rx:^bozo]
# Configure the pods linter for v1/pods.
pods:
instances:
# [NEW!] exclude all pods matching these labels.
- labels:
app: [fred,blee] # Exclude codes 102, 105 for any pods with labels app=fred or app=blee
codes: [102, 105]
resources:
# Configure node resources.
node:
# Limits set a cpu/mem threshold in % ie if cpu|mem > limit a lint warning is triggered.
limits:
# CPU checks if current CPU utilization on a node is greater than 90%.
cpu: 90
# Memory checks if current Memory utilization on a node is greater than 80%.
memory: 80
# Configure pod resources
pod:
# Restarts check the restarts count and triggers a lint warning if above threshold.
restarts: 3
# Check container resource utilization in percent.
# Issues a lint warning if about these threshold.
limits:
cpu: 80
memory: 75
# [New!] overrides code severity
overrides:
# Code specifies a custom severity level ie critical=3, warn=2, info=1
- code: 206
severity: 1
# Configure a list of allowed registries to pull images from.
# Any resources not using the following registries will be flagged!
registries:
- quay.io
- docker.io
Popeye는 컨테이너화되어 있으며, Kubernetes 클러스터에서 일회성 또는 CronJob으로 직접 실행할 수 있습니다.
다음은 샘플 설정입니다. 필요에 따라 수정하십시오. 이에 대한 매니페스트는 이 리포지토리의 k8s 디렉토리에 있습니다.```shell kubectl apply -f k8s/popeye
NIST Inspekt는 문서를 다양한 표준에 대해 검증하는 명령줄 도구로, 특히 미국 국립표준기술연구소(NIST)에서 발행한 표준에 중점을 둡니다. 표준별 가이드라인 외에도 문서의 내용과 형식의 여러 측면을 세밀하게 제어할 수 있습니다.
이 도구를 사용하면 특정 작성 규칙에 대해 다음 간행물을 기준으로 문서를 검증할 수 있습니다:```yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: popeye
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: popeye
namespace: popeye
spec:
schedule: "* */1 * * *" # Fire off Popeye once an hour
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
serviceAccountName: popeye
restartPolicy: Never
containers:
- name: popeye
image: derailed/popeye:vX.Y.Z
imagePullPolicy: IfNotPresent
args:
- -o
- yaml
- --force-exit-zero
resources:
limits:
cpu: 500m
memory: 100Mi
--force-exit-zero가 설정되어야 합니다. 그렇지 않으면 포드가 오류 상태가 됩니다.
참고! Popeye는 린트 오류가 감지되면 0이 아닌 종료 코드를 반환합니다.
Popeye가 작업을 수행하려면 로그인한 사용자에게 위에서 언급한 리소스를 가져오고 나열할 수 있는 충분한 RBAC 권한이 있어야 합니다.
샘플 Popeye RBAC 규칙 (이 규칙은 변경될 수 있음에 유의하세요.)
참고! 클러스터 정책에 따라 검토 및 조정하십시오.```yaml
apiVersion: v1 kind: ServiceAccount metadata: name: popeye namespace: popeye
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: popeye rules:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: popeye subjects:
---
## 보고서 형태 (Report Morphology)
lint 보고서는 각 리소스 그룹과 해당 그룹의 잠재적 문제를 스캔한 결과를 출력합니다.
보고서는 린트 심각도 수준에 따라 색상/이모지로 표시됩니다.
| 레벨 | 아이콘 | Jurassic | 색상 | 설명 |
|-------|------|----------|-----------|-------------------|
| Ok | ✅ | OK | 녹색 | 좋아요! |
| Info | 🔊 | I | 청록색 | 참고 |
| Warn | 😱 | W | 노란색 | 잠재적 문제 |
| Error | 💥 | E | 빨간색 | 조치 필요 |
각 스캔된 쿠버네티스 리소스의 제목 섹션에는 위의 각 범주에 대한 요약 개수가 제공됩니다.
요약 섹션은 주어진 클러스터에 대한 린트 통과 결과를 기반으로 **Popeye 점수**를 제공합니다.
---
## 알려진 문제 (Known Issues)
이 초기 버전은 취약합니다. Popeye는 다음과 같은 상황에서 대부분 문제를 일으킬 수 있습니다…
* 오래된 버전의 쿠버네티스를 사용하는 경우. Popeye는 Kubernetes 1.25.X에서 가장 잘 작동합니다.
* 클러스터를 관리하기에 충분한 RBAC 권한이 없는 경우 (RBAC 섹션 참조)
---
## 면책 조항 (Disclaimer)
이 프로젝트는 진행 중인 작업입니다! 쿠버네티스 커뮤니티의 충분한 관심이 있다면
여러분의 추천/기여에 따라 더욱 발전시킬 예정입니다.
또한 이 노력이 마음에 드신다면 그 사실도 알려주세요!
---
## ATTA 소녀들/소년들! (ATTA Girls/Boys!)
Popeye는 많은 오픈 소스 프로젝트와 라이브러리 위에 구축되었습니다.
이 프로젝트를 현실로 만들기 위해 밤낮으로 일하는 모든 OSS 기여자분들께 *진심으로* 감사드립니다!
### 연락처 정보 (Contact Info)
1. **이메일**: [email protected]
2. **트위터**: [@kitesurfer](https://twitter.com/kitesurfer?lang=en)
---
<img src="https://raw.githubusercontent.com/derailed/popeye/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2025 Imhotep Software LLC.
모든 자료는 [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)에 따라 사용이 허가되었습니다.
| 형식 | 설명 | 기본값 | 크레딧 |
|---|
| standard | 아이콘과 색상이 적용된 완전한 출력 | 예 | |
| jurassic | 1979년처럼 아이콘이나 색상 없음 | ||
| yaml | YAML 형식 | ||
| html | HTML 형식 | ||
| json | JSON 형식 | ||
| junit | 자바를 그리워하는 사람들을 위한 형식 | ||
| prometheus | 프로메테우스 메트릭으로 보고서 덤프 | dardanel | |
| score | 단일 클러스터 린터 점수 값(0-100) 반환 | kabute |