자체 빌드 이미지 3종(cloudnative-pg/cnpg-postgresql/etcd) + 대응 헬름 차트 도입
security-catalog 프로젝트에서 첫 실사용 자체 빌드 이미지 3종을 포팅한다 — 전부
상위 태그·베이스 OS 교체로 해소 안 되는 CVE(Go 모듈 정적 링크 또는 미수정 CRITICAL/
HIGH)를 자체 빌드(소스 컴파일 또는 SUSE BCI 재설치)로 대응한다:
- images/cloudnative-pg: CNPG operator, release-1.30 소스 컴파일 + bci-micro
- images/cnpg-postgresql: PostgreSQL 18.4, bci-base + zypper 재설치
- images/etcd: etcd v3.7.1, 소스 컴파일(x/text 강제 업그레이드) + bci-micro
함께 추가:
- manifests/helm/{cloudnative-pg,cnpg-cluster,etcd} — 위 이미지를 참조하는 카탈로그 차트
- scripts/deploy-test/*.sh, .claude/deploy-test-procedure.md — CVE 0건과 별개로
"실제로 뜨는가"를 검증하는 배포 스모크 테스트
- .claude/pitfalls.md — 자체 빌드/배포 테스트 중 실측한 함정 모음
검토 중 발견해 반영한 수정:
- cloudnative-pg 차트의 image 블록을 etcd와 동일한 registry/repository/tag 3필드+
따옴표 포맷으로 통일 — 기존 포맷(repository에 registry+repo 결합, 따옴표 없음)은
patch-catalog-tag.py 의 split 패처가 tag만 갱신하고 repository는 그대로 남기는
조용한 부분 치환을 일으켜, 향후 레지스트리 마이그레이션 시 깨진 참조를 만들 수 있었다
- cnpg-cluster 차트의 SLES 커버리지 코멘트를 최신 실측(trivy가 SLES 15.7을 정상
커버함, 2026-07-29 재측정)에 맞게 정정 — 폐기된 "측정 불가/OVAL 우회 필요" 결론이
남아있었다
- CLAUDE.md/MEMORY.md 의 "images/ 디렉토리 없음" 서술을 갱신하고, 레지스트리
마이그레이션(docker.io/wbsong111 → docker.io/paasup)·decisions/analysis 문서 이관·
리소스 프로파일 추가를 다음 작업으로 기록
이 3개 이미지는 아직 dip-catalog 자체 CI(build-image.yml)로 빌드·게이트·push 를
실행해본 적이 없다 — 현재 참조 태그는 security-catalog 쪽에서 이미 검증된 것이다.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
# Default values for Etcd deployment
|
||||
|
||||
## Etcd container image
|
||||
image:
|
||||
registry: "quay.io/coreos"
|
||||
repository: "etcd"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: ""
|
||||
|
||||
# Default Init container image
|
||||
initImage:
|
||||
registry: "docker.io"
|
||||
repository: "busybox"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "stable"
|
||||
|
||||
## Pull secrets and name override options
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
## Additional labels for Deployment or StatefulSet
|
||||
customLabels: {}
|
||||
|
||||
## Additional annotations for Deployment or StatefulSet
|
||||
customAnnotations: {}
|
||||
|
||||
## Number of etcd replicas in the cluster
|
||||
## Due to the nature of etcd cluster initialization this value must be set before deploying the cluster
|
||||
## Automatic scaling or manually scaling the etcd cluster after first deployment is not supported
|
||||
replicas: 1
|
||||
|
||||
## Optional service account
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: false
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
# Specifies whether a service account token should be automatically mounted
|
||||
automountServiceAccountToken: true
|
||||
|
||||
## Additional pod annotations
|
||||
podAnnotations: {}
|
||||
|
||||
## Additional pod labels
|
||||
podLabels: {}
|
||||
|
||||
## Pod management policy
|
||||
podManagementPolicy: Parallel
|
||||
|
||||
## Pod update strategy
|
||||
updateStrategyType: RollingUpdate
|
||||
|
||||
## Pod security context uses file system group 999 (postgres)
|
||||
podSecurityContext:
|
||||
fsGroup: 999
|
||||
supplementalGroups:
|
||||
- 999
|
||||
|
||||
## Default security options to run PostgreSQL as non-root (postgres user), read only container without privilege escalation
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsGroup: 999
|
||||
runAsUser: 999
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
|
||||
## Etcd service ports (default: Client port 2379, Peer port 2380)
|
||||
service:
|
||||
type: ClusterIP
|
||||
## Client service port
|
||||
client:
|
||||
port: 2379
|
||||
## The node port (only relevant for type LoadBalancer or NodePort)
|
||||
nodePort:
|
||||
## Peer service port
|
||||
peer:
|
||||
port: 2380
|
||||
## The node port (only relevant for type LoadBalancer or NodePort)
|
||||
nodePort:
|
||||
## Prometheus service port
|
||||
prometheus:
|
||||
port: 12379
|
||||
## The node port (only relevant for type LoadBalancer or NodePort)
|
||||
nodePort:
|
||||
## The cluster ip address (only relevant for type LoadBalancer or NodePort)
|
||||
clusterIP:
|
||||
## The loadbalancer ip address (only relevant for type LoadBalancer)
|
||||
loadBalancerIP:
|
||||
## The list of IP CIDR ranges that are allowed to access the load balancer (only relevent for type LoadBalancer)
|
||||
loadBalancerSourceRanges: []
|
||||
## Annotations to add to the service
|
||||
annotations: {}
|
||||
## Labels to add to the service
|
||||
labels: {}
|
||||
|
||||
## Service monitor configuration for Prometheus metrics
|
||||
serviceMonitor:
|
||||
## Enable service monitor
|
||||
enabled: false
|
||||
## Additional labels for the service monitor object
|
||||
additionalLabels: {}
|
||||
## Annotations for the service monitor object
|
||||
annotations: {}
|
||||
## The scrape interval for prometheus
|
||||
# interval:
|
||||
## The scrape timeout value
|
||||
# scrapeTimeout:
|
||||
## Extra parameters rendered to the service monitor endpoint
|
||||
extraEndpointParameters: {}
|
||||
## Extra parameters rendered to the service monitor
|
||||
extraParameters: {}
|
||||
|
||||
resources: {}
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
## Pod priority class name
|
||||
priorityClassName: ""
|
||||
|
||||
## Additional node selector
|
||||
nodeSelector: {}
|
||||
|
||||
## Tolerations for pod assignment
|
||||
tolerations: []
|
||||
|
||||
## Affinity for pod assignment
|
||||
affinity: {}
|
||||
|
||||
## Topology spread constraints for pods
|
||||
topologySpreadConstraints: {}
|
||||
|
||||
## Maximum number of revisions maintained in revision history
|
||||
revisionHistoryLimit:
|
||||
|
||||
## Custom startup probe (overwrites default startup probe)
|
||||
customStartupProbe: {}
|
||||
|
||||
## Default startup check
|
||||
startupProbe:
|
||||
enabled: true
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 30
|
||||
successThreshold: 1
|
||||
periodSeconds: 10
|
||||
|
||||
## Custom liveness probe (overwrites default liveness probe)
|
||||
customLivenessProbe: {}
|
||||
|
||||
## Default health check
|
||||
livenessProbe:
|
||||
enabled: true
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
periodSeconds: 10
|
||||
|
||||
## Custom readiness probe (overwrites default readiness probe)
|
||||
customReadinessProbe: {}
|
||||
|
||||
## Default readiness probe
|
||||
readinessProbe:
|
||||
enabled: true
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
successThreshold: 1
|
||||
periodSeconds: 10
|
||||
|
||||
## Extra init containers
|
||||
extraInitContainers: []
|
||||
|
||||
## Extra containers for usage as sidecars
|
||||
extraContainers: []
|
||||
|
||||
## Additional environment variables
|
||||
env: []
|
||||
|
||||
## Arguments for the container entrypoint process
|
||||
args: []
|
||||
|
||||
## A list of existing secrets that will be mounted into the container as environment variables
|
||||
extraEnvSecrets: []
|
||||
|
||||
## A list of additional existing secrets that will be mounted into the container
|
||||
## The mounted files of the secrets can be used for advanced configuration (see settings.https.enabled)
|
||||
extraSecrets: []
|
||||
## Name of the existing K8s secret
|
||||
# - name:
|
||||
## Mount default mode (0440 if parameter is omitted)
|
||||
# defaultMode: 0440
|
||||
## Mount path where the secret should be mounted into the container (f.e. /mysecretfolder)
|
||||
# mountPath:
|
||||
|
||||
## A list of additional existing configMaps that will be mounted into the container
|
||||
extraConfigs: []
|
||||
## Name of the existing K8s configMap
|
||||
# - name:
|
||||
## Mount default mode (0440 if parameter is omitted)
|
||||
# defaultMode: 0440
|
||||
## Mount path where the configMap should be mounted into the container (f.e. /mysecretfolder)
|
||||
# mountPath:
|
||||
|
||||
## Default Kubernetes cluster domain
|
||||
clusterDomain: cluster.local
|
||||
|
||||
## Etcd specific settings
|
||||
settings:
|
||||
## Unique cluser token
|
||||
clusterToken: "etcd-cluster-0"
|
||||
## Configure secure transport
|
||||
## Certificates must be mounted into the container using `extraSecrets:` or generated automatically using autoTls: true
|
||||
## Other tls options have to be added manually using environment variables or args: (see https://etcd.io/docs/v3.5/op-guide/clustering/#tls and https://etcd.io/docs/v3.5/op-guide/configuration/)
|
||||
https:
|
||||
## Enable HTTPS
|
||||
enabled: false
|
||||
## Automatic TLS mode of etcd (TLS certs. created automaically)
|
||||
autoTls: false
|
||||
|
||||
## Delay after termination request to give etcd process time for graceful shutdown
|
||||
shutdownDelay: 3
|
||||
|
||||
## Storage parameters
|
||||
storage:
|
||||
## Set persistentVolumenClaimName to reference an existing PVC
|
||||
persistentVolumeClaimName:
|
||||
|
||||
## Internal volume name and prefix of a created PVC
|
||||
volumeName: "etcd-data"
|
||||
|
||||
## Alternative set requestedSize to define a size for a dynmaically created PVC
|
||||
requestedSize:
|
||||
|
||||
## the storage class name
|
||||
className:
|
||||
|
||||
## Default access mode (ReadWriteOnce)
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
|
||||
## Additional storage annotations
|
||||
annotations: {}
|
||||
|
||||
## Additional storage labels
|
||||
labels: {}
|
||||
|
||||
## Mount existing extra PVC
|
||||
extraStorage: {}
|
||||
## Internal volume name
|
||||
# - name:
|
||||
## Container mount path
|
||||
# mountPath:
|
||||
## Name of existing PVC
|
||||
# pvcName:
|
||||
|
||||
## Network policies
|
||||
networkPolicy: {}
|
||||
## Ingress and Egress policies
|
||||
# ingress: {}
|
||||
# egress: {}
|
||||
Reference in New Issue
Block a user