Introducción
La seguridad de la cadena de suministro comienza antes de que una carga de trabajo se ejecute en el clúster. Si una imagen contiene herramientas innecesarias, una procedencia poco clara o una etiqueta no aprobada, los controles de tiempo de ejecución que aprendiste anteriormente tienen un mayor riesgo de verse comprometidos. Una imagen mínima aprobada debe tener un contexto de construcción pequeño, una imagen base clara, un punto de entrada de aplicación explícito, etiquetas de metadatos útiles y evidencia de que puede ejecutarse en el clúster de destino.
En este laboratorio, crearás un contexto de construcción de imagen local pequeño, construirás la imagen dentro del perfil de minikube labex-v134, inspeccionarás los metadatos de la imagen resultante, la desplegarás con imagePullPolicy: Never y verificarás el contenido en tiempo de ejecución desde Kubernetes. Este laboratorio mantiene un enfoque práctico: aún no estás escaneando imágenes ni aplicando políticas de registro. Estás aprendiendo el primer hábito de la cadena de suministro: construir una imagen pequeña, nombrada e inspeccionable, y demostrar qué contiene.
Crear un contexto de construcción de imagen pequeño
En este paso, crearás los archivos que formarán la imagen. Un contexto de construcción es el directorio que se envía al constructor de imágenes. Mantener el contexto de construcción pequeño es importante porque cada archivo adicional es una oportunidad para copiar algo innecesario en una imagen más adelante.
Comienza en el espacio de trabajo del laboratorio:
cd /home/labex/project/minimal-approved-image
Lee las notas del laboratorio:
sed -n '1,160p' IMAGE_BUILD_NOTES.md
Confirma el contexto de CKS y el espacio de nombres (namespace):
kubectl config current-context | tee context-check.txt
kubectl get namespace cks-prep-image | tee namespace-check.txt
Crea el script de la aplicación. Este script imprime un mensaje de preparación, imprime el UID de tiempo de ejecución y luego entra en espera para que Kubernetes pueda mantener el contenedor en ejecución para su inspección.
cat > app.sh <<'EOF'
#!/bin/sh
set -eu
echo "minimal approved image ready"
echo "runtime uid: $(id -u)"
sleep 300
EOF
chmod 0755 app.sh
Crea el Dockerfile. busybox:1.36 es la imagen base pequeña para este laboratorio. Las etiquetas de estilo OCI registran por qué esta imagen está aprobada en el laboratorio, y USER 65534:65534 hace que la imagen se ejecute como un usuario numérico no root de forma predeterminada.
cat > Dockerfile <<'EOF'
FROM busybox:1.36
LABEL org.opencontainers.image.title="minimal-approved-app"
LABEL org.opencontainers.image.source="local-cks-prep"
LABEL security.labex.io.approved="true"
WORKDIR /app
COPY app.sh /app/app.sh
RUN chmod 0555 /app/app.sh
USER 65534:65534
ENTRYPOINT ["/app/app.sh"]
EOF
Guarda el inventario del contexto de construcción y una suma de verificación (checksum) del script de la aplicación:
find . -maxdepth 1 -type f -printf '%f\n' | sort | tee build-context-files.txt
sha256sum app.sh | tee app-sha256.txt
sed -n '1,120p' Dockerfile | tee dockerfile-review.txt
Tu directorio ahora contendrá Dockerfile, app.sh, las notas y los archivos de evidencia que estás guardando. El límite importante de la imagen es la línea COPY en el Dockerfile: solo app.sh se copia en /app/app.sh dentro de la imagen.
Construir la imagen dentro del perfil de Minikube
En este paso, construirás la imagen en el perfil de minikube labex-v134. Construirla allí es importante porque Kubernetes ejecutará contenedores desde el tiempo de ejecución del nodo de minikube. Si solo construyes una imagen en el demonio de Docker de la máquina virtual externa, es posible que el nodo de minikube no pueda verla.
Construye la imagen con una etiqueta local clara:
minikube -p labex-v134 image build -t labex/minimal-approved:1.0 .
Inspecciona la imagen dentro del perfil de minikube. El primer comando confirma que la imagen existe en el tiempo de ejecución del nodo. El segundo comando guarda metadatos clave, incluido el usuario configurado, el punto de entrada y las etiquetas.
minikube -p labex-v134 ssh -- 'docker image ls labex/minimal-approved:1.0' | tee built-image-list.txt
minikube -p labex-v134 ssh -- 'docker image inspect labex/minimal-approved:1.0' | tee built-image-inspect.json
Usa jq para extraer los campos que importan para la evidencia de aprobación:
jq '.[0].Config | {User, Entrypoint, Labels}' built-image-inspect.json | tee built-image-approval.json
Deberías ver la etiqueta de la imagen en built-image-list.txt, el User configurado como 65534:65534, el Entrypoint configurado como /app/app.sh y la etiqueta de aprobación configurada como true.
Ejecutar la imagen aprobada en Kubernetes
En este paso, ejecutarás la imagen local en Kubernetes. El Pod utiliza imagePullPolicy: Never porque la imagen se construyó dentro del perfil de minikube en lugar de enviarse a un registro. Esa configuración le indica a Kubernetes que use la imagen del nodo local y falle si no está presente.
Crea el manifiesto del Pod:
cat > approved-image-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: approved-image-app
namespace: cks-prep-image
labels:
app: approved-image-app
supply-chain.labex.io/approved: "true"
spec:
restartPolicy: Never
securityContext:
runAsNonRoot: true
runAsUser: 65534
runAsGroup: 65534
containers:
- name: app
image: labex/minimal-approved:1.0
imagePullPolicy: Never
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
EOF
Aplica el Pod y espera a que esté listo:
kubectl apply -f approved-image-pod.yaml
kubectl wait --for=condition=Ready pod/approved-image-app -n cks-prep-image --timeout=120s
Guarda los registros del Pod y el YAML actual del Pod:
kubectl logs approved-image-app -n cks-prep-image | tee approved-image-logs.txt
kubectl get pod approved-image-app -n cks-prep-image -o yaml | tee approved-image-pod.current.yaml
Los registros deberían mostrar minimal approved image ready y runtime uid: 65534. Eso demuestra que Kubernetes está ejecutando el punto de entrada de la imagen como el usuario no root previsto.
Verificar el contenido en tiempo de ejecución
En este paso, inspeccionarás el contenedor en ejecución desde Kubernetes. La aprobación de la imagen no debe detenerse en el nombre de una etiqueta. Quieres evidencia de que el tiempo de ejecución contiene la ruta de la aplicación esperada y no contiene archivos adicionales obvios que nunca debieron ser parte de la imagen.
Inspecciona el directorio de la aplicación:
kubectl exec -n cks-prep-image approved-image-app -- sh -c 'ls -la /app; test -f /app/app.sh; echo APP_PATH_OK' | tee runtime-app-path.txt
Verifica el usuario de tiempo de ejecución y realiza una pequeña comprobación negativa para detectar archivos de depuración innecesarios:
kubectl exec -n cks-prep-image approved-image-app -- sh -c 'id -u; test ! -e /app/debug-tool && echo NO_DEBUG_TOOL' | tee runtime-content-check.txt
Guarda un registro de aprobación final compacto que combine el estado de Kubernetes con los metadatos de la imagen:
kubectl get pod approved-image-app -n cks-prep-image -o json | jq '{image: .spec.containers[0].image, imagePullPolicy: .spec.containers[0].imagePullPolicy, podSecurityContext: .spec.securityContext, containerSecurityContext: .spec.containers[0].securityContext}' | tee final-pod-approval.json
jq '.[0].Config | {User, Entrypoint, Labels}' built-image-inspect.json | tee final-image-approval.json
La evidencia final debería mostrar la etiqueta de la imagen local aprobada, imagePullPolicy: Never, la configuración de tiempo de ejecución no root, el punto de entrada /app/app.sh y la etiqueta de aprobación.
Resumen
Has practicado el primer flujo de trabajo de la cadena de suministro en este curso de preparación para el CKS: construir y probar una imagen mínima aprobada. Creaste un contexto de construcción pequeño, construiste labex/minimal-approved:1.0 dentro del perfil de minikube labex-v134, inspeccionaste los metadatos y etiquetas de la imagen, desplegaste la imagen local con imagePullPolicy: Never y verificaste el usuario de tiempo de ejecución y el contenido de la aplicación desde Kubernetes. Los laboratorios posteriores sobre la cadena de suministro se basarán en esta base con escaneo de manifiestos, revisión de salida de Helm, evidencia de SBOM y sumas de verificación, controles de registro confiables y limpieza de secretos de construcción.



