Jugando con Docker

Últimamente se esta oyendo mucho hablar de Docker. Se trata de una tecnología similar a la que ya existía en Solaris con las zonas, y en Linux con LXC (de hecho utiliza LXC por debajo). Parece que viene patrocinado por algunas de las grandes en internet como eBay, Spotify e incluso Google parece que venia utilizando algo parecido desde hace tiempo.
Docker
La gran ventaja, como en el caso de las zonas, es que te permite “virtualizar” sin depender de un hipervisor y con un overhead mínimo en comparación a la virtualización tradicional.

Instalación

Como todo en Linux es muy fácil de instalar y ya viene preparado en la mayoría de distribuciones. En el caso de CentOS hay que habilitar el repositorio EPEL editando el fichero de configuración del repositorio y poniendo la variable enabled a 1:

[root@centos1 ~]# vi /etc/yum.repos.d/epel.repo

[epel]
name=Extra Packages for Enterprise Linux 6 – $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
A continuación ya podemos instalar docker con yum. Como veremos, una de las dependencias es LXC:
[root@centos1 ~]# yum install docker-io
Dependencies Resolved

================================================================================
 Package            Arch            Version                 Repository     Size
================================================================================
Installing:
 docker-io          x86_64          1.0.0-3.el6             epel          4.5 M
Installing for dependencies:
 lxc                x86_64          0.9.0-2.el6             epel           78 k
 lxc-libs           x86_64          0.9.0-2.el6             epel          116 k

Transaction Summary
================================================================================
Install       3 Package(s)

Total download size: 4.7 M
Installed size: 24 M
Is this ok [y/N]: y

Así de sencillo es instalarlo. Y como vemos, la versión es la primera estable que se ha publicado recientemente:
[root@centos1 ~]# docker -v
Docker version 1.0.0, build 63fe64c/1.0.0
Para empezar a utilizarlo se debe iniciar el servicio y configurarlo para que arranque en el runlevel predeterminado:
[root@centos1 ~]# service docker start
Starting cgconfig service:                                 [  OK  ]
Starting docker:                                                [  OK  ]
[root@centos1 ~]# chkconfig docker on

Imágenes y contenedores

Con el servicio ya en marcha podemos descargar las imágenes que docker mantiene, así como imágenes que la comunidad ha creado y ha subido. Por ejemplo descargaremos las últimas para centos y para ubuntu:

[root@centos1 ~]# docker pull centos:latest
Pulling repository centos
0c752394b855: Download complete
511136ea3c5a: Download complete
34e94e67e63a: Download complete

[root@centos1 ~]# docker pull ubuntu:latest
Pulling repository ubuntu
e54ca5efa2e9: Download complete
511136ea3c5a: Download complete
d7ac5e4f1812: Download complete
2f4b4d6a4a06: Download complete
83ff768040a0: Download complete
6c37f792ddac: Download complete
Para ver las imágenes que tenemos descargadas y disponibles para utilizar bastará con ejecutar el subcomando “images”:
[root@centos1 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              latest              e54ca5efa2e9        41 hours ago        276.1 MB
centos              latest              0c752394b855        10 days ago         124.1 MB
Pasando el parámetro -a podemos ver el historial de versiones de cada imagen:
[root@centos1 ~]# docker images -a
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              latest              e54ca5efa2e9        41 hours ago        276.1 MB
                            6c37f792ddac        41 hours ago        276.1 MB
                            83ff768040a0        41 hours ago        192.7 MB
                            2f4b4d6a4a06        41 hours ago        192.7 MB
                            d7ac5e4f1812        41 hours ago        192.5 MB
centos              latest              0c752394b855        10 days ago         124.1 MB
                            34e94e67e63a        2 weeks ago         0 B
                            511136ea3c5a        12 months ago       0 B
Podremos arrancar instancias o contenedores con las imágenes que queramos de la siguiente manera:
[root@centos1 ~]# docker run -i -t centos /bin/bash
bash-4.1# more /etc/centos-release
CentOS release 6.5 (Final)
bash-4.1# hostname
3ce460cbb9d8

[root@centos1 ~]# docker run -i -t ubuntu /bin/bash
root@60d6e0455be0:/# more /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION=”Ubuntu 14.04 LTS”
root@60d6e0455be0:/# hostname
60d6e0455be
Al pasar el parámetro -i al comando run se ejecutará el contenedor de forma interactiva, de forma que, en cuanto termine el comando que pasamos como parámetro la ejecución del contenedor terminará.
Mientras estemos ejecutando la shell, veremos que el contenedor está ejecutándose:
[root@centos1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
49087a343e7f        centos:latest       /bin/bash           12 seconds ago      Up 11 seconds                           dreamy_curie   
Si quisiesemos ver un historial de las instancias ejecutadas pasaríamos el parámetro -a:
 [root@centos1 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
15dc7c59189c        centos:latest       /bin/bash           27 seconds ago      Up 26 seconds                                   compassionate_fermi  
49087a343e7f        centos:latest       /bin/bash           12 minutes ago      Exited (0) 17 seconds ago                       dreamy_curie         
9e69f5b64254        ubuntu:latest       uname -r            15 minutes ago      Exited (0) 15 minutes ago                       high_engelbart       
f5aa352a5ce9        centos:latest       uname -r            15 minutes ago      Exited (0) 15 minutes ago                       jovial_meitner       
60d6e0455be0        ubuntu:latest       /bin/bash           17 minutes ago      Exited (0) 16 minutes ago                       cocky_leakey         
961b10b9bbbf        ubuntu:latest       hostname            17 minutes ago      Exited (0) 17 minutes ago                       insane_mayer         
3ce460cbb9d8        centos:latest       /bin/bash           19 minutes ago      Exited (0) 17 minutes ago                       loving_yonath  
Si por contra, quisiesemos ejecutar un contenedor en background o demonizado, como sucede en Solaris con las zonas, al comando run le pasaríamos el parámetro -d. En el siguiente ejemplo arrancaríamos una instancia de la imagen ubuntu y dos instancias de la imagen de centos y finalmente veríamos que se están ejecutando las tres:
[root@centos1 ~]# docker run -d -t ubuntu  /bin/bash
abc254ab2e8eb392ce80938c8f2b8fa8cb1603ab6935b2121b7cb0cddbdd64c3
[root@centos1 ~]# docker run -d -t centos  /bin/bash
59adfe1998cc678cf2c9db964f1b57e60a301ffa2139c7a4635ebe315db2b718
[root@centos1 ~]# docker run -d -t centos  /bin/bash
6714217732adadec19f47399fe5f7252823787869a96e8fed72457cd5106589c
[root@centos1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6714217732ad        centos:latest       /bin/bash           3 seconds ago       Up 2 seconds                            romantic_shockley 
59adfe1998cc        centos:latest       /bin/bash           7 seconds ago       Up 6 seconds                            thirsty_bartik    
abc254ab2e8e        ubuntu:latest       /bin/bash           14 seconds ago      Up 13 seconds                           naughty_yonath 
Al arrancar cada contenedor nos devuelve un número muy largo. Este número es el container_id que mas adelante vemos en la primera columna del comando ps. La última columna es un nombre que se asigna automáticamente y servirá para identificar las instancias de una forma mas amigable. Para parar las zonas que están corriendo podríamos pasar como identificador tanto el container_id como el nombre:

[root@centos1 ~]# docker stop romantic_shockley
romantic_shockley
[root@centos1 ~]# docker stop thirsty_bartik
thirsty_bartik
[root@centos1 ~]# docker stop naughty_yonath
naughty_yonath
[root@centos1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 

Como vemos, el kernel que se está ejecutando es el del host:

[root@centos1 ~]# uname -r
2.6.32-431.el6.x86_64
[root@centos1 ~]# docker run -i -t centos uname -r
2.6.32-431.el6.x86_64
[root@centos1 ~]# docker run -i -t ubuntu uname -r
2.6.32-431.el6.x86_64

Otra forma de arrancar un contenedor es con el comando start y pasando como parámetro el id del contenedor o el nombre que docker le asigno en su momento (lo podemos encontrar con docker ps -a)
 [root@centos1 ~]# docker start romantic_shockley
romantic_shockley
[root@centos1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6714217732ad        centos:latest       /bin/bash           15 minutes ago      Up 3 seconds                            romantic_shockley
Para acceder a la consola del contenedor ejecutaríamos el comando attach:
 [root@centos1 ~]# docker attach romantic_shockley

Obtener información

Existe una serie de comandos que nos servirán para obtener información, tanto de docker, como de las imagenes o contenedores que tenemos creados. El comando info nos devolverá información general de la instalación actual de docker:
[root@centos1 ~]# docker info
Containers: 6
Images: 8
Storage Driver: devicemapper
 Pool Name: docker-8:1-132310-pool
 Data file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata
 Data Space Used: 784.9 Mb
 Data Space Total: 102400.0 Mb
 Metadata Space Used: 1.4 Mb
 Metadata Space Total: 2048.0 Mb
Execution Driver: native-0.2
Kernel Version: 2.6.32-431.el6.x86_64
Con el comando history veremos el historial de versiones de la imagen que le hayamos especificado:
[root@centos1 ~]# docker history centos
IMAGE               CREATED             CREATED BY                                      SIZE
0c752394b855        10 days ago         /bin/sh -c #(nop) ADD file:ce8fdb737386beb5fd   124.1 MB
34e94e67e63a        2 weeks ago         /bin/sh -c #(nop) MAINTAINER The CentOS Proje   0 B
511136ea3c5a        12 months ago                                                       0 B
También tendremos el comando inspect, que nos devolverá un objeto JSON con información detallada de la imagen. Tambien sirve para obetner información de un contenedor.

[root@centos1 ~]# docker inspect centos
[{
    “Architecture”: “amd64”,
    “Author”: “The CentOS Project \u003ccloud-ops@centos.org\u003e – ami_creator”,
    “Comment”: “”,
    “Config”: {
        “AttachStderr”: false,
        “AttachStdin”: false,
        “AttachStdout”: false,
        “Cmd”: null,
        “CpuShares”: 0,
        “Cpuset”: “”,
        “Domainname”: “”,
        “Entrypoint”: null,
        “Env”: [
            “HOME=/”,
            “PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”
        ],
        “ExposedPorts”: null,
        “Hostname”: “b2d0f1281acd”,
        “Image”: “34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a”,
        “Memory”: 0,
        “MemorySwap”: 0,
        “NetworkDisabled”: false,
        “OnBuild”: [],
        “OpenStdin”: false,
        “PortSpecs”: null,
        “StdinOnce”: false,
        “Tty”: false,
        “User”: “”,
        “Volumes”: null,
        “WorkingDir”: “”
    },
    “Container”: “b2d0f1281acd040292b36f6623feca10a89df1637c8d86e54079d473da4d05e3”,
    “ContainerConfig”: {
        “AttachStderr”: false,
        “AttachStdin”: false,
        “AttachStdout”: false,
        “Cmd”: [
            “/bin/sh”,
            “-c”,
            “#(nop) ADD file:ce8fdb737386beb5fd9aff7c9bbe9e6c9e60db290809dd6407c61b377e444b59 in /”
        ],
        “CpuShares”: 0,
        “Cpuset”: “”,
        “Domainname”: “”,
        “Entrypoint”: null,
        “Env”: [
            “HOME=/”,
            “PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”
        ],
        “ExposedPorts”: null,
        “Hostname”: “b2d0f1281acd”,
        “Image”: “34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a”,
        “Memory”: 0,
        “MemorySwap”: 0,
        “NetworkDisabled”: false,
        “OnBuild”: [],
        “OpenStdin”: false,
        “PortSpecs”: null,
        “StdinOnce”: false,
        “Tty”: false,
        “User”: “”,
        “Volumes”: null,
        “WorkingDir”: “”
    },
    “Created”: “2014-06-09T21:38:41.281490617Z”,
    “DockerVersion”: “0.10.0”,
    “Id”: “0c752394b855e8f15d2dc1fba6f10f4386ff6c0ab6fc6a253285bcfbfdd214f5”,
    “Os”: “linux”,
    “Parent”: “34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a”,
    “Size”: 124078508
}

Para obtener informacion específica de un contenedor especificaremos al comando inspect la clave que queremos que nos devuelva, como por ejemplo el hostname o la dirección IP:
[root@centos1 ~]# docker run -d -t centos  /bin/bash
d7e7938ab7e98ff8e2413179d5222201de6a0c66716b99aafb35a0805fbf279e
[root@centos1 ~]# docker  ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
d7e7938ab7e9        centos:latest       /bin/bash           11 seconds ago      Up 11 seconds                           nostalgic_newton   

[root@centos1 ~]# docker inspect -f ‘{{ .Config.Hostname }}’ nostalgic_newton
d7e7938ab7e9
[root@centos1 ~]# docker inspect -f ‘{{ .NetworkSettings.IPAddress }}’ nostalgic_newton
172.17.0.22

Borrado de contenedores

Para norrar contenedores utilizaremos el comando rm. Le podremos pasar un único identificador de contenedor o varios en el mismo comando:
[root@centos1 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                       PORTS               NAMES
abc254ab2e8e        ubuntu:latest       /bin/bash           22 minutes ago      Exited (0) 18 minutes ago                        naughty_yonath      
90ae553f4384        centos:latest       /bin/bash           23 minutes ago      Exited (-1) 22 minutes ago                       ecstatic_mcclintock

[root@centos1 ~]# docker rm ecstatic_mcclintock naughty_yonath
ecstatic_mcclintock
naughty_yonath

Creación de módulos para puppet

Una vez puesto en marcha un servidor de Puppet es importante tener bien organizado la estructura de directorios para que no se convierta en un caos. Hay tres directorios importantes, el manifests, el modules y el files. Mi estructura actual es la siguiente:

[root@puppet puppet]# tree /etc/puppet/
/etc/puppet/
├── auth.conf
├── files
│   ├── limits.conf
│   ├── motd
│   ├── nicstat-linux
│   ├── nicstat-solarisx86
│   ├── ntp.conf
│   └── sysctl.conf
├── fileserver.conf
├── manifests
│   ├── nodes.pp
│   ├── site.pp
├── modules
│   ├── ftp
│   │   └── manifests
│   │   └── init.pp
│   ├── nicstat
│   │   └── manifests
│   │   └── init.pp
│   ├── ntp
│   │   └── manifests
│   │   └── init.pp
│   ├── sysconf
│   │   └── manifests
│   │   └── init.pp
│   └── users
│   └── manifests
│   └── init.pp
└── puppet.conf
En el manifests se ubican los principales scripts. Yo lo organizo en un site.pp que incluye el fichero nodes.pp que es donde defino las configuraciones específicas para cada nodo. En el directorio modules habrá un subdirectorio por cada módulo y dentro de este otro subdirectorio manifests y un fichero init.pp donde esta la propia definición del módulo. El último directorio importante es el files que utilizo para almacenar los ficheros de configuración estandarizados o binarios que quiero desplegar en los nodos.
Voy a analizar algunos de los ficheros comentados:
site.pp:
La idea de este fichero es que esté lo mas limpio posible para que de un vistazo sea intuitivo ver que scripts se están aplicando. En mi caso únicamente importo el nodes.pp.
[root@puppet manifests]# more site.pp
import ‘nodes.pp’
En el nodes.pp defino los nodos, filtrando por el nombre (se podría filtrar por algún otro parámetro). En cada definición de nodo incluyo los módulos que les quiero aplicar.
[root@puppet manifests]# more nodes.pp
node puppet {
    include ntp
    include nicstat
    include users
}
node /linux[1-3].enterprise.com/ {
    include ntp
    include nicstat
    include sysconf
    include users
    notice(“I am running on node ${fqdn}”)
}
node ‘solaris[1-2].enterprise.com‘ {
    include ftp
    include nicstat
    include users
    notice(“I am running on node ${fqdn}”)
}
Modulos
Para crear un módulo hay que crear una subcarpeta con el nombre del módulo. Dentro de este nuevo subdirectorio puede haber una estructura similar a la general en /etc/puppet. Como requisito fundamental es la existencia del fichero init.pp. En dicho fichero deberá existir una definición de clase (class) que será la que se importa en el nodes.pp.
He creado varios módulos para configurar determinadas funcionalidades, por ejemplo:
FTP
me aseguro que este parado por temas de seguridad.
[root@puppet manifests]# more /etc/puppet/modules/ftp/manifests/init.pp
class ftp {
    service { ‘ftp’:
        ensure => stopped,
    }
}
NTP
Existe en Puppet Forge algún módulo mas completo para el ntp, sin embargo para lo que yo busco este me es suficiente. Me aseguro de que el paquete esté instalado, el servicio arrancado y que el fichero de configuración es el mismo en todos los servidores.
[root@puppet manifests]# more /etc/puppet/modules/ntp/manifests/init.pp
class ntp {
    package { ‘ntp’:
        ensure => installed,
    }
    service { ‘ntpd’:
        ensure => running,
        require => Package[‘ntp’],
    }
    file { ‘/etc/ntp.conf’:
        notify => Service[“ntpd”],
        source => “puppet:///files/ntp.conf”,
        require => Package[‘ntp’],
    }
}
NICSTAT
Se trata de un binario para obtener estadísticas avanzadas de red. Me interesa desplegarlo en todos los nodos y ademas hay que tener en cuenta que el binario es diferente para Solaris y Linux:
[root@puppet manifests]# more /etc/puppet/modules/nicstat/manifests/init.pp
class nicstat{
    if $::osfamily == ‘Solaris’ {
        file { ‘/opt/utils/’:
            ensure => directory,
        }
        file { ‘/opt/utils/nicstat’:
            source => “puppet:///files/nicstat-solarisx86”,
        }
    } elsif $::osfamily == ‘RedHat’ {
        file { ‘/opt/utils/’:
            ensure => directory,
        }
        file { ‘/opt/utils/nicstat’:
        source => “puppet:///files/nicstat-linux”,
        }
    }
}
USERS
Con este módulo pretendo estandarizar la creación de usuarios. Podríamos crear todos los usuarios de los administradores por ejemplo o asegurarnos de que no exista determinado usuario.
[root@puppet puppet]# more /etc/puppet/modules/users/manifests/init.pp
class users{
    user { ‘jsotoca’:
        ensure => present,
        comment => ‘Julian Garcia-Sotoca’,
        home => $operatingsystem ?{
            Solaris => ‘/export/home/jsotoca’,
            default => ‘/home/jsotoca’,
        },
        managehome => true,
    }

    user { ‘baduser’:
        ensure => absent,
    }

Instalación de Puppet en Solaris 10

Para instalar el agente de puppet en Solaris 10 lo mas facil es recurrir a OpenCSW. De esta forma podemos descargar el paquete y sus correspondientes dependencias (a partir de Solaris 11.2 ya viene incluido en los repositorios oficiales). 

Lo mas útil es crear un paquete que contenga el propio paquete de puppet y sus dependencias, de forma que podamos redistribuir dicho paquete en todos los servidores donde lo queramos instalar y no será necesario que todos los servidores tengan conexión a Internet. Para ello ejecutaremos:

root@solaris01 # /opt/csw/bin/pkgutil –stream –target=i386:5.10 –output /tmp/puppet.pkg –yes –download puppet
=> Fetching new catalog and descriptions (http://mirror.opencsw.org/opencsw/testing/i386/5.10) if available …
==> 3707 packages loaded from /var/opt/csw/pkgutil/catalog.mirror.opencsw.org_opencsw_testing_i386_5.10
Solving needed dependencies …
Solving dependency order …
Package list:
       CSWalternatives-1.2,REV=2013.10.15 (opencsw/testing)
       CSWaugeas-0.10.0,REV=2012.01.04 (opencsw/testing)
       CSWcas-initsmf-1.49,REV=2013.03.13 (opencsw/testing)
       CSWcas-usergroup-1.44,REV=2011.05.02 (opencsw/testing)
       CSWcommon-1.5,REV=2010.12.11 (opencsw/testing)
       CSWfacter-1.7.1,REV=2013.05.22 (opencsw/testing)
       CSWlibgcc-s1-4.8.2,REV=2013.11.08 (opencsw/testing)
       CSWlibgdbm4-1.9,REV=2011.10.24 (opencsw/testing)
       CSWlibgnugetopt0-1.3,REV=2011.07.06 (opencsw/testing)
       CSWlibiconv2-1.14,REV=2011.08.07 (opencsw/testing)
       CSWliblzma5-5.0.5,REV=2013.07.05 (opencsw/testing)
       CSWlibncurses5-5.9,REV=2011.11.21 (opencsw/testing)
       CSWlibreadline6-6.2,REV=2011.07.02 (opencsw/testing)
       CSWlibruby18-1-1.8.7p357,REV=2014.03.06 (opencsw/testing)
       CSWlibssl1-0-0-1.0.1g,REV=2014.04.08 (opencsw/testing)
       CSWlibxml2-2-2.9.1,REV=2013.08.16 (opencsw/testing)
       CSWlibz1-1.2.8,REV=2013.09.23 (opencsw/testing)
       CSWpuppet-2.7.23,REV=2013.08.15 (opencsw/testing)
       CSWruby18-1.8.7p357,REV=2014.03.06 (opencsw/testing)
       CSWrubyaugeas-0.4.1,REV=2012.03.25 (opencsw/testing)
       CSWterminfo-5.9,REV=2011.11.21 (opencsw/testing)
Total size: 9.3 MB
A local copy of CSWcommon-1.5,REV=2010.12.11 exists and is of matching size.
=> Fetching CSWlibz1-1.2.8,REV=2013.09.23 (2/21) …
A local copy of CSWlibiconv2-1.14,REV=2011.08.07 exists and is of matching size.
=> Fetching CSWliblzma5-5.0.5,REV=2013.07.05 (4/21) …
=> Fetching CSWlibxml2-2-2.9.1,REV=2013.08.16 (5/21) …
=> Fetching CSWlibgcc-s1-4.8.2,REV=2013.11.08 (6/21) …
A local copy of CSWlibgnugetopt0-1.3,REV=2011.07.06 exists and is of matching size.
A local copy of CSWterminfo-5.9,REV=2011.11.21 exists and is of matching size.
=> Fetching CSWlibruby18-1-1.8.7p357,REV=2014.03.06 (9/21) …
=> Fetching CSWlibssl1-0-0-1.0.1g,REV=2014.04.08 (10/21) …
=> Fetching CSWlibgdbm4-1.9,REV=2011.10.24 (11/21) …
=> Fetching CSWalternatives-1.2,REV=2013.10.15 (12/21) …
A local copy of CSWcas-usergroup-1.44,REV=2011.05.02 exists and is of matching size.
A local copy of CSWcas-initsmf-1.49,REV=2013.03.13 exists and is of matching size.
A local copy of CSWlibncurses5-5.9,REV=2011.11.21 exists and is of matching size.
A local copy of CSWlibreadline6-6.2,REV=2011.07.02 exists and is of matching size.
A local copy of CSWaugeas-0.10.0,REV=2012.01.04 exists and is of matching size.
=> Fetching CSWruby18-1.8.7p357,REV=2014.03.06 (18/21) …
A local copy of CSWrubyaugeas-0.4.1,REV=2012.03.25 exists and is of matching size.
=> Fetching CSWfacter-1.7.1,REV=2013.05.22 (20/21) …
=> Fetching CSWpuppet-2.7.23,REV=2013.08.15 (21/21) …
Transforming CSWcommon …
Transforming CSWlibz1 …
Transforming CSWlibiconv2 …
Transforming CSWliblzma5 …
Transforming CSWlibxml2-2 …
Transforming CSWlibgcc-s1 …
Transforming CSWlibgnugetopt0 …
Transforming CSWterminfo …
Transforming CSWlibruby18-1 …
Transforming CSWlibssl1-0-0 …
Transforming CSWlibgdbm4 …
Transforming CSWalternatives …
Transforming CSWcas-usergroup …
Transforming CSWcas-initsmf …
Transforming CSWlibncurses5 …
Transforming CSWlibreadline6 …
Transforming CSWaugeas …
Transforming CSWruby18 …
Transforming CSWrubyaugeas …
Transforming CSWfacter …
Transforming CSWpuppet …
Transforming packages into stream (/tmp/puppet.pkg) …

Install commands in dependency safe order:

pkgadd -G -d /tmp/puppet.pkg CSWcommon
pkgadd -G -d /tmp/puppet.pkg CSWlibz1
pkgadd -G -d /tmp/puppet.pkg CSWlibiconv2
pkgadd -G -d /tmp/puppet.pkg CSWliblzma5
pkgadd -G -d /tmp/puppet.pkg CSWlibxml2-2
pkgadd -G -d /tmp/puppet.pkg CSWlibgcc-s1
pkgadd -G -d /tmp/puppet.pkg CSWlibgnugetopt0
pkgadd -G -d /tmp/puppet.pkg CSWterminfo
pkgadd -G -d /tmp/puppet.pkg CSWlibruby18-1
pkgadd -G -d /tmp/puppet.pkg CSWlibssl1-0-0
pkgadd -G -d /tmp/puppet.pkg CSWlibgdbm4
pkgadd -G -d /tmp/puppet.pkg CSWalternatives
pkgadd -G -d /tmp/puppet.pkg CSWcas-usergroup
pkgadd -G -d /tmp/puppet.pkg CSWcas-initsmf
pkgadd -G -d /tmp/puppet.pkg CSWlibncurses5
pkgadd -G -d /tmp/puppet.pkg CSWlibreadline6
pkgadd -G -d /tmp/puppet.pkg CSWaugeas
pkgadd -G -d /tmp/puppet.pkg CSWruby18
pkgadd -G -d /tmp/puppet.pkg CSWrubyaugeas
pkgadd -G -d /tmp/puppet.pkg CSWfacter
pkgadd -G -d /tmp/puppet.pkg CSWpuppet
Como vemos, al final del proceso nos muestra el paso a paso de como instalarlo correctamente. Dichos comandos se pueden poner en un script de forma que la instalación consista en copiar el software y ejecutar el instalador:
root@solaris01 # ls -l | grep puppet
-rwxr-xr-x   1 root     root         883 Apr 29 16:58 install_puppet.sh
-rw-r–r–   1 root     root     32153600 Apr 29 16:56 puppet.pkg
root@solaris01 # ./install_puppet.sh

Una vez instalado podemos verificar el archivo de configuración y verificamos que en el hosts aparezca el servidor de puppet:
root@solaris01 # grep puppet /etc/hosts
X.X.X.X puppet

root@solaris01 # vi /opt/csw/etc/puppet/puppet.conf
# puppet.conf
#
# points puppet at OpenCSW default paths

[main]
   confdir = /etc/opt/csw/puppet
   config = $confdir/puppet.conf
   vardir = /var/opt/csw/puppet
   ssldir = $vardir/ssl

[agent]
   # The file in which puppetd stores a list of the classes
   # associated with the retrieved configuratiion.  Can be loaded in
   # the separate “puppet“ executable using the “–loadclasses“
   # option.
   # The default value is ‘$confdir/classes.txt’.
   classfile = $vardir/classes.txt

   # Where puppetd caches the local configuration.  An
   # extension indicating the cache format is added automatically.
   # The default value is ‘$confdir/localconfig’.
   localconfig = $vardir/localconfig
   report = true
~

En este momento ya podemos realizar un test y firmar el certificado en la parte del servidor. A continuación habilitaríamos el servicio:
root@solaris01 #  /opt/csw/bin/puppet agent –test
root@solaris01 #  svcadm enable cswpuppetd

Para parar el agente hay que deshabilitar el servicio:
 
root@solaris01 #  svcadm disable cswpuppetd
He creado algunos manifiestos específicos para solaris o que realizan una determinada acción en función del sistema operativo:

Despliegue de un fichero

root@solaris01 #cat modules/nicstat/manifests/init.pp
class nicstat{
    if $::osfamily == ‘Solaris’ {
        file { ‘/opt/utils/’:
            ensure => directory,
        }
        file { ‘/opt/utils/nicstat’:
            source => “puppet:///files/nicstat-solarisx86”,
        }
       
       
    } elsif $::osfamily == ‘RedHat’ {
        file { ‘/opt/utils/’:
            ensure => directory,
        }
        file { ‘/opt/utils/nicstat’:
            source => “puppet:///files/nicstat-linux”,
        }   
    }
}

Customizar el MOTD:

node ‘solaris’’ {
   include ftp
   include nicstat
   file { “/etc/motd”:
           content => “Welcome
\tServer IP address: ${ipaddress}.
\tHostname: ${fqdn}
\tOperating System: ${operatingsystem}\tRelease: ${operatingsystemrelease}
\tOS family: ${osfamily}
\tKernel: ${kernel} ${kernelversion}
\tPuppet ${puppetversion}
\tCPU: ${physicalprocessorcount}\t\t\tCores: ${processorcount}
\tMemory: ${memorysize}\tSwap: ${swapsize}
\tTimeZone: ${timezone}
\tphyisical/virtual: ${virtual}\tType: ${type}
\tManufacturer: ${manufacturer}\tModel: ${productname}
\tSerial Number: ${serialnumber}
\n”
       }
       notice(“I am running on node ${fqdn}”)
}