Skip to main content

A imagem do NNS

A imagem do NNS é construída pelo Spring Boot, com Cloud Native Buildpacks (Paketo):

./mvnw spring-boot:build-image -Dnn.image.name=<registry>/<repositório>

O console-service-parent já traz a configuração canônica — você não escreve um Dockerfile e não passa builder, run image nem versão de Java. O que o POM fixa:

o quêvalor
builderpaketobuildpacks/builder-noble-java-tiny, por digest
run imagepaketobuildpacks/ubuntu-noble-run-tiny, por digest
runtimeBP_JVM_VERSION=26, BP_JVM_TYPE=JRE — JVM/JIT, sem Native Image e sem AOT
nome${nn.image.name}:${project.version}

O enforcer do pai recusa o build com outro Java que não o 26, com builder ou run image por tag, com os perfis native/nativeTest, com o native-maven-plugin e com Quarkus, GraalVM, JPA/Hibernate, Flyway e Liquibase no classpath.

O que a imagem contém​

Uma imagem real do NNS do módulo iam (iam@0.12.0), inspecionada por digest:

itemvalor
usuário1002:1001 (não-root, da própria imagem)
entrypoint/cnb/process/web
workdir/workspace
baseio.buildpacks.stacks.noble (Ubuntu 24.04, "distroless-like"), run image ubuntu-noble-run-tiny:0.0.138
JREBellSoft Liberica 26.0.2 (26.0.2+13)
launcher0.21.22
camadas20 (~345 MB na soma)
arquivos de SBOM11 (~132 componentes da aplicação)

Os buildpacks que compõem a imagem:

paketo-buildpacks/ca-certificates@3.13.0
paketo-buildpacks/bellsoft-liberica@11.9.0 (o JRE e o memory calculator)
paketo-buildpacks/syft@2.41.0 (o SBOM)
paketo-buildpacks/executable-jar@6.16.0
paketo-buildpacks/dist-zip@5.13.0
paketo-buildpacks/spring-boot@5.37.0

O processo web é o java -jar do launcher do Spring Boot:

java org.springframework.boot.loader.launch.JarLauncher

Para conferir isso na sua imagem:

./nnconsolew image inspect --role nns <registry>/<repositório>@sha256:<digest>

O usuário é da imagem​

O pod roda com o UID numérico da imagem — 1002:1001 nas imagens Paketo do SDK. O chart não define runAsUser/runAsGroup: ele define runAsNonRoot: true e deixa o UID vir da imagem. Se você definir runAsUser no chart, o chart check recusa quando ele difere do UID conferido na imagem:

./nnconsolew chart check --values nns/helm/testdata/injected-values.yaml --namespace <ns> \
--runtime jvm --runtime-user 1002 nns/helm/chart

O chart define fsGroup: 65532: é ele que dá leitura aos Secrets montados com modo 0440.

O sistema de arquivos é somente leitura​

O container roda com readOnlyRootFilesystem: true, sem privilégios de escalada e com todas as capabilities removidas:

{{- define "nns.containerSecurity" -}}
securityContext:
runAsNonRoot: true
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
seccompProfile:
type: RuntimeDefault
{{- end -}}

Na imagem Paketo o único caminho gravável é /tmp — o truststore do buildpack, o diretório de trabalho do Tomcat e o hsperfdata da JVM escrevem lá. Por isso o chart monta um emptyDir de 64 Mi em /tmp:

volumeMounts:
- {name: tmp, mountPath: /tmp}
- {name: trust, mountPath: /etc/nnumbers/trust, readOnly: true}
- {name: role, mountPath: /etc/nnumbers/role, readOnly: true}
volumes:
- name: tmp
emptyDir: {sizeLimit: 64Mi}

A regra do runtime JVM (chart_runtime_mount) aceita montagem em /tmp, /etc/nnumbers/** e /var/run/nnumbers/** — nada fora disso. Precisa gravar em outro lugar? Ou o dado é config/segredo (que têm lugar próprio), ou a plataforma precisa mudar.

O emptyDir tem limite: um processo que enche /tmp é despejado pelo kubelet em vez de derrubar o nó. Se o seu módulo grava arquivo temporário grande, dimensione em .../tmp e conte com o limite.

O que ainda não existe na imagem​

  • Sem OTLP: a telemetria de log e traço é a do SDK; as métricas são do Micrometer, na porta de management. Veja Logs, métricas e saúde.
  • Sem raízes de CA do sistema: quem fala TLS de internet declarada usa as raízes embutidas no SDK. Não conte com ca-certificates do host.

Princípio que você deve levar para o resto​

Nada de host, IP, namespace, cluster ou localhost fixos no código ou no chart. Tudo vem das variáveis NN_* injetadas pelo Module Manager e do Service Registry. É o que o gate confere:

./nnconsolew portability scan --dir .