Pregunta 9 | Perfil AppArmor
Usar contexto: kubectl config use-context workload-prod
Algunos contenedores necesitan ejecutarse de manera más segura y restringida. Hay un perfil AppArmor existente ubicado en /opt/course/9/profile para esto.
Instala el perfil AppArmor en el Nodo cluster1-node1. Conéctate usando ssh cluster1-node1
Agrega la etiqueta security=apparmor al Nodo
Crea un Deployment llamado apparmor en el Namespace default con:
Una réplica de la imagen nginx:1.19.2
NodeSelector para security=apparmor
Contenedor único llamado c1 con el perfil AppArmor habilitado solo para este contenedor
El Pod podría no ejecutarse correctamente con el perfil habilitado. Escribe los logs del Pod en /opt/course/9/logs para que otro equipo pueda trabajar en hacer que la aplicación funcione.
Respuesta:
https://kubernetes.io/docs/tutorials/clusters/apparmor
Parte 1
Primero echamos un vistazo al perfil proporcionado:
vim /opt/course/9/profile
# /opt/course/9/profile
#include <tunables/global>
profile very-secure flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Denegar todas las escrituras de archivos.
deny /** w,
}
Perfil muy simple llamado very-secure que deniega todas las escrituras de archivos. A continuación lo copiamos en el Nodo:
➜ scp /opt/course/9/profile cluster1-node1:~/
Warning: Permanently added the ECDSA host key for IP address '192.168.100.12' to the list of known hosts.
profile 100% 161 329.9KB/s 00:00
➜ ssh cluster1-node1
➜ root@cluster1-node1:~# ls
profile
# Y lo instalamos:
➜ root@cluster1-node1:~# apparmor_parser -q ./profile
# Verificamos que se haya instalado:
➜ root@cluster1-node1:~# apparmor_status
apparmor module is loaded.
17 profiles are loaded.
17 profiles are in enforce mode.
/sbin/dhclient
...
man_filter
man_groff
very-secure
0 profiles are in complain mode.
56 processes have profiles defined.
56 processes are in enforce mode.
...
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
Allí vemos entre muchos otros el very-secure, que es el nombre del perfil especificado en /opt/course/9/profile.
Parte 2
Etiquetamos el Nodo:
k label -h # mostrar ejemplos
k label node cluster1-node1 security=apparmor
Parte 3
Ahora podemos seguir adelante y crear el Deployment que usa el perfil.
k create deploy apparmor --image=nginx:1.19.2 --dry-run=client -o yaml > 9_deploy.yaml
vim 9_deploy.yaml
# 9_deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: apparmor
name: apparmor
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: apparmor
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: apparmor
spec:
nodeSelector: # agregar
security: apparmor # agregar
containers:
- image: nginx:1.19.2
name: c1 # cambiar
securityContext: # agregar
appArmorProfile: # agregar
type: Localhost # agregar
localhostProfile: very-secure # agregar
k -f 9_deploy.yaml create
¿Cuál es el daño?
➜ k get pod -owide | grep apparmor
apparmor-85c65645dc-jbch8 0/1 CrashLoopBackOff ... cluster1-node1
➜ k logs apparmor-85c65645dc-w852p
/docker-entrypoint.sh: 13: /docker-entrypoint.sh: cannot create /dev/null: Permission denied
/docker-entrypoint.sh: No files found in /docker-entrypoint.d/, skipping configuration
2021/09/15 11:51:57 [emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
Esto se ve bien, el Pod se está ejecutando en cluster1-node1 debido al nodeSelector. El perfil AppArmor simplemente deniega todas las escrituras del sistema de archivos, pero Nginx necesita escribir en algunas ubicaciones para ejecutarse, de ahí los errores.
Parece que nuestro perfil se está ejecutando pero también podemos confirmarlo inspeccionando el contenedor:
➜ ssh cluster1-node1
➜ root@cluster1-node1:~# crictl pods | grep apparmor
be5c0aecee7c7 4 minutes ago Ready apparmor-85c65645dc-jbch8 ...
➜ root@cluster1-node1:~# crictl ps -a | grep be5c0aecee7c7
e4d91cbdf72fb ... Exited c1 6 be5c0aecee7c7
➜ root@cluster1-node1:~# crictl inspect e4d91cbdf72fb | grep -i profile
"apparmor_profile": "localhost/very-secure",
"apparmorProfile": "very-secure",
Primero encontramos el Pod por su nombre y obtenemos el pod-id. Luego usamos crictl ps -a para también mostrar contenedores detenidos. Entonces crictl inspect muestra que el contenedor está usando nuestro perfil AppArmor. Nota que debes ser rápido entre ps e inspect ya que K8s reiniciará el Pod periódicamente cuando esté en estado de error.
Para completar la tarea escribimos los logs en la ubicación requerida:
k logs apparmor-85c65645dc-jbch8 > /opt/course/9/logs
Arreglar los errores es el trabajo de otro equipo, somos afortunados.