Introducción
Debemos imaginar una zona de OpenSolaris como un contenedor de procesos, es decir la zona es una jaula cuyo contenido no puede ver lo que hay fuera de ella. Para que los procesos puedan ejecutarse el kernel debe proporcionar una serie de recursos a dicha zona, como pueden ser acceso a discos, interfaces de red, etc. Dichos recursos no pueden ser compartidos entre zonas.La excepción es la zona global con id 0, esta se crea cuando arranca el sistema y tiene asociado todos los recursos sin restricciones de privilegios. Incluso en los sistemas que no se ha definido ninguna zona existe una zona global.
Cada zona esta identificada por un nombre y un id, el nombre global y el id 0 está reservados para la zona global.
Notas sobre el kernel
En nuestro sistema solo tenemos un Kernel ejecutándose, los procesos de las distintas zonas se ejecutan todos en el mismo que, lógicamente es el que se inicia al arrancar la zona global.Esto tiene grandes beneficios a nivel de performance, especialmente si el diseño de las zonas ha sido bien pensado.
Teniendo en cuenta lo anterior interesa, desde el punto de vista de la performance, que las distintas zonas sean los mas parecidas posible y compartan el mayor número de directorios posibles.
P. ej. mientras que levantar el sistema consume en mi equipo 339 megas de la memoria física, arrancar una zona adicional consume solo 79 mb.
####sistema solo con la zona global bash-3.00# mdb -k Loading modules: [ unix genunix specfs dtrace uppc pcplusmp scsi_vhci ufs ip hook neti sctp arp usba fctl nca lofs mpt audiosup zfs random cpc crypto fcip nsctl ptm sppp ipc ] > ::memstat Page Summary Pages MB %Tot ------------ ---------------- ---------------- ---- Kernel 15066 58 12% Anon 52276 204 41% Exec and libs 11141 43 9% Page cache 5927 23 5% Free (cachelist) 24358 95 19% Free (freelist) 20142 78 16% Total 128910 503 Physical 128909 503 ###iniciamos una nueva zona > ::memstat Page Summary Pages MB %Tot ------------ ---------------- ---------------- ---- Kernel 17944 70 14% Anon 69002 269 54% Exec and libs 11305 44 9% Page cache 6139 23 5% Free (cachelist) 18639 72 14% Free (freelist) 5881 22 5% Total 128910 503 Physical 128909 503 >
Notas sobre la seguridad
Si bien ejecutar todos los hilos en el mismo kernel es un beneficio para la performance también supone un reto de cara a la seguridad. Es crítico para la integridad del sistema que los procesos que se ejecutan en una zona estén completamente aislados del resto. Esto se consigue asignando un set de privilegios especifico para los procesos les permite interectuar únicamente con los de su misma zona.
bash-3.00# ppriv -S 11227
11227: bash
flags =
#ps dentro de la zona test bash-3.00# id uid=0(root) gid=0(root) bash-3.00# uname -a SunOS test 5.11 snv_70b i86pc i386 i86pc bash-3.00# ps PID TTY TIME CMD 11227 console 0:01 bash 29665 console 0:02 sh 26806 console 0:00 ps #ps desde la zona global con un grep para ver el proceso bash de la zona test bash-3.00# id uid=0(root) gid=0(root) bash-3.00# ps -ef | grep 11227 root 11227 29665 1 Jan 18 zoneconsole 0:01 bash root 26809 555 1 09:45:14 pts/2 0:00 grep 11227 #ps desde la zona global bash-3.00# ps PID TTY TIME CMD 555 pts/2 0:03 bash 551 pts/2 0:00 sh 26812 pts/2 0:00 ps #ps desde la zona test buscando el pid del bash de la zona global bash-3.00# ps -ef | grep 555 | grep -v grep bash-3.00#
A parte de lo anterior existen algunas tareas que no están permitidas ejecutarse dentro de una zona
Procesos que gestionan una Zona
Existen dos nuevos procesos por cada zona no global que tenemos en el sistema para gestionar los recursos de ellas:El primero es el zoneadmd, Sus tareas son las siguientes:
Hay una completa descripción de este proceso en el fichero zoneadmd.c del código fuente.
El otro proceso es el zsched, sus tareas son:
Ciclo de vida de una zona
Estos son los estados (a nivel de kernel) en los que se puede encontrar una zona, ordenados por el flujo natural de arranque a parada.ZONE_IS_UNINITIALIZED: la zona se ha añadido a la lista de zonas activas pero aun no es accesible.
ZONE_IS_READY: el proceso zsched esta preparado.
ZONE_IS_BOOTING: es un estado de transición el proceso zsched esta tratando de lanzar el init de la zona.
ZONE_IS_RUNNING: zsched a lanzado correctamente el init, la zona esta lista para trabajar. Permanece en este estado hasta que se le haga un shutdown.
ZONE_IS_SHUTTING_DOWN: se ha ejecutado la llamada zone_shutdown(), el sistema esta matando todos los procesos dentro de la zona.
ZONE_IS_EMPTY: no quedan mas procesos de esta zona ejecutándose.
ZONE_IS_DOWN: todos los threads del kernel relacionados con la zona han terminado.
La estructura zone_t
Por cada zona existente en el sistema hay una estructura zone_t en el kernel, en ella tenemos información acerca del estado y configuración de esta. Podemos ver su definición en el fichero zone.h de nuestro sistema.typedef struct zone { /* * zone_name is never modified once set. */ char *zone_name; /* zone's configuration name */ /* * zone_nodename and zone_domain are never freed once allocated. */ char *zone_nodename; /* utsname.nodename equivalent */ char *zone_domain; /* srpc_domain equivalent */ /* * zone_lock protects the following fields of a zone_t: * zone_ref * zone_cred_ref * zone_ntasks * zone_flags * zone_zsd */ kmutex_t zone_lock; /* [...]
Dentro de ella encontramos los parámetros con los que hemos configurado la zona, entre ellos los que limitan el consumo de ella como por ejemplo el máximo de memoria que puede consumir, el número de semáforos, etc. Vamos hacer un breve repaso a los mas destacados:
*zone_name; /* nombre de la zona */ zoneid_t zone_id; /* ID de la zona */ rctl_qty_t zone_locked_mem_ctl; /* límite máximo de memoria*/ rctl_qty_t zone_max_swap_ctl; /* límite máximo de swap */ [...]
También hay información de la zona, como por ejemplo:
char *zone_rootpath; /* path de la raiz de la zona */ zone_status_t zone_status; /* en que estado esta actualmente la zona*/ rctl_qty_t zone_nlwps; /* número de hilos ejecutándose */ [...]
Podemos acceder fácilmente a ella usando mdb:
bash-3.00# mdb -k Loading modules: [ unix genunix specfs dtrace uppc pcplusmp scsi_vhci ufs ip hook neti sctp arp usba fctl nca lofs mpt audiosup zfs random sppp crypto ptm md nfs cpc fcip fcp logindmux nsctl sdbc sv ii rdc ] > ::walk zone fec7f028 d5072b40 d884ac40 > ::walk zone fec7f028 d5072b40 d884ac40 > d5072b40 ::zone ADDR ID NAME PATH d5072b40 1 linux /zone/root/ > d884ac40 ::zone ADDR ID NAME PATH d884ac40 3 test /zone_OS/root/ > d884ac40 ::print zone_t { zone_name = 0xd7ce69c0 "test" zone_nodename = 0xd86e5400 "test" zone_domain = 0xd86e57c0 "" zone_lock = { _opaque = [ 0, 0 ] } zone_linkage = { list_next = zone_active+8 list_prev = 0xd5072b54 } zone_id = 0x3 zone_ref = 0x13 zone_cred_ref = 0x1e zone_rootvp = 0xd5074240 zone_rootpath = 0xd884ed10 "/zone_OS/root/" zone_flags = 0 zone_status = 3 (ZONE_IS_RUNNING) zone_ntasks = 0x11 zone_nlwps_lock = { _opaque = [ 0, 0 ] } [...]