Docker: Mapear usuarios dentro del contenedor

En ocasiones que trabajamos con Docker necesitamos generar ficheros. Los ficheros que se generan en el contenedor por defecto pertenecen a root. Vamos a ver una forma para mapear usuarios del sistema dentro del contenedor. En concreto nos interesa mapear nuestro propio usuario deforma que el propietario de un fichero sea el mismo dentro y fuera del contenedor.

Tenemos al usuario foo que tiene una entrada en /etc/passwd como esta:

foo:x:1001:1001::/home/foo:/bin/bash

Empecemos por preparar un directorio de trabajo para foo dentro del contenedor.

$ mkdir ~/docker_home
$ cp /etc/skel/{.bash_logout,.bashrc,.profile} ~/docker_home

Ahora cuando vayamos a lanzar el contenedor, debemos mapear el usuario:

$ docker run -ti \
 -v /etc/passwd:/etc/passwd \
 -v /etc/group:/etc/group \
 -v /etc/shadow:/etc/shadow \
 -v /home/foo/docker_home:/home/foo ubuntu:16.04

La entrada al contenedor seguirá siendo con el usuario root pero ahora podemos hacer:

su - foo

Para trabajar con nuestro usuario.

Si queremos entrar directamente con nuestro usuario hacemos así:

$ docker run -ti \
 -v /etc/passwd:/etc/passwd \
 -v /etc/group:/etc/group \
 -v /etc/shadow:/etc/shadow \
 -v /home/foo/docker_home:/home/foo ubuntu:16.04 \
 su -s /bin/bash -c "/bin/bash" foo

Por último si queremos que el contenedor sea más caja negra debemos tener en cuenta que hay que modificar el Dockerfile a la hora de construir la imagen.

Owncloud con almacenamiento en S3 (con replicación de zona) y Let’s Encrypt

Una entrada completita para antes de irnos de vacaciones

Contendores y Proxy Pass

Comenzamos creando una instancia en OpenStack a la que provisionamos con un volumen para la persistencia de datos. El volumen lo podemos montar en /mnt y será nuestro directorio de trabajo.

En el directorio de trabajo creamos la siguiente estructura de directorios:

.
├── docker-compose
├── mysql
└── owncloud

En el directorio de docker-compose creamos el fichero yaml con el estado deseado de los contendedores:

---
version: '2'
services:
  owncloud:
    image: owncloud
    ports:
      - 8080:80
    volumes:
      - /mnt/volumen/owncloud:/var/www/html
  mysql:
    image: mariadb
    volumes:
      - /mnt/volumen/mysql/db:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: s3cr3t

Por no liar con los grupos de seguridad de OpenStack solo permito acceso al puerto 80/tcp así que vamos a levantar un Nginx delante de los contenedores.

# apt install nginx
# vim /etc/nginx/sites-enable/default
## Añadir este contenido ##
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name owncloud.example.com;

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_pass http://localhost:8080;
    }
}
## Reiniciar el servidor ##
# systemctl restart nginx

Podemos acceder a la url con el navegador y configuramos el usuario y la password para Owncloud. La conexión a la base de datos que podemos acceder por el host mysql con la contraseña que hemos elegido previamente.

Una vez dentro de Owncloud instalamos la App External storage support y lo dejamos aquí de momento.

Configuración de S3

Entramos en la consola de AWS y creamos un usuario, necesitaremos el AccessKeyID y el SecretAccessKey, este usuario podrá acceder a los buckets. A continuacion creamos dos buckets S3. Como vamos a replicarlos entre zonas tenemos que actuvar Versioning. En la pestaña de permisos eliminamos al owner ya que usaremos Policy. Con el recurso creado vamos la pestaña Permissions -> Bucket Policy y añadimos las siguente politica:

{
            "Sid": "AllowAccess",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::ACCOUNT:user/USER"
            },
            "Action": [
                "s3:DeleteObject",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::BUCKET_NAME/*"
        },
        {
            "Sid": "AllowList",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::ACCOUNT:user/USER"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::BUCKET_NAME"
        },
         {
            "Sid": "IPAllow",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::BUCKER_NAME/*",
            "Condition": {
            "IpAddress": {"aws:SourceIp": "IP de OWNCLOUD"}
         } 
       } 
    ]
}

Nos movemos ahora a la pestaña de Properties y activamos Cross-region replication completamos el formulario que nos aparece. En source el bucket de origen, en Destination ponemos la zona y el segundo bucket que hemos creado. en Destination storage class establecemos con Same as source object y en Select role ponemos Create new.

En el segundo bucket establecemos la política de acceso cambiando el nombre del bucket

Configurar Owncloud

Volvemos a nuestro Owncloud y entramos a la pestaña de configuración donde configuramos la cadena de conexión al bucket es decir, le ponemos el S3 access key el S3 secret key y el nombre del bucket. Si todo está correcto un punto verde debería aparecer a la izquierda del cuadro de diálogo. También podéis probar a subir y borrar archivos también para comprobar que replican a la otra zona de disponibilidad.

Let’s Encrypt

Vamos a instalar certbot para gestionar automáticamente los certificados digitales. Para ello seguimos estos pasos:

# Instalamos:
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install certbot 
# Generamos los certificados
$ certbot certonly --webroot -w /mnt/volumen/owncloud -d owncloud.example.com
# Este comando crea un fichero en la raiz del servidor para verificar que somos propietarios del dominio.
# A continuación generará el certificado en
# /etc/letsencrypt/archive/owncloud.example.com/fullchain1.pem

Ya con el certificado configuramos Nginx:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name owncloud.example.com;

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    listen 443 ssl;
    server_name owncloud.example.com;

        root /var/www/html;

    ssl_certificate     /etc/letsencrypt/archive/owncloud.example.com/fullchain1.pem;
    ssl_certificate_key /etc/letsencrypt/keys/0000_key-certbot.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;

    location / {
        proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_pass http://localhost:8080;
    }
}

Reiniciar Nginx

# systemctl restart nginx

Habilitar docker-compose para que arranque con el sistema

Ahora configuramos para que si se tiene que reiniciar la máquina por algún motivo los contenedores arranquen automáticamente. Para ello añadimos un nuevo servicio a systemd

# vim /etc/systemd/system/docker-compose.service
## Añadimos este contenido:
[Unit]
Description=Owncloud on Docker Compose
Requires=docker.service
After=network.target docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/mnt/volumen/docker-compose
ExecStart=/usr/local/bin/docker-compose -f /mnt/volumen/docker-compose/docker-compose.yaml start 
ExecStop=/usr/local/bin/docker-compose -f /mnt/volumen/docker-compose/docker-compose.yaml stop

[Install]
WantedBy=multi-user.target
## Y recargamos la configuración
# systemctl daemon-reload

Y listo.

OpenStack & Kubernetes: LBaaS y Self Service Provisioning

Ya que tenemos desplegado Kubernetes en OpenStack vamos a aprovechar las capacidades de este para desplegar nuestras aplicaciones.

Configurar Kubernetes para utilizar OpenStack

El primer paso que tenemos que dar es configurar nuestras credenciales de OpenStack en Kubernetes. Para ello editamos el fichero /etc/kubernetes/cloud_config y añadimos las siguientes líneas:

[Global]
auth-url=http://AUTH_URL:5000/v3
username=demo
password=s3cr3t
region=RegionOne
tenant-id=d245f207e6fc4e56b5a1d23e0716ad70
domain-name=Default

De esta forma el API de Kubernetes puede comunicar con el API de OpenStack y configurar los servicios.

El campo domain-name solo es necesario si usamos API v3 de OpenStack, como indica la AUTH_URL.

Ahora debemos cambiar añadir lo siguiente:

KUBE_API_ARGS=[...] --cloud-provider=openstack --cloud-config=/etc/kubernetes/cloud_config

al arranque de nuestro Kubernetes apiserver.

Igualmente en /etc/kubernetes/manifests/kube-controller-manager.yaml:

- [...]
- --cloud_config=/etc/sysconfig/kube_openstack_config
- --cloud_provider=openstack

Aquí la cosa se complica y depende de tu instalación. Si tienes el binario en el sistema solo tienes que ajustar en /etc/kubernetes/* pero si estás usando contenedores, deberás volver a construir los contenedores y añadir estos parámetros.

Utilizar el LBaaS de OpenStack en Kubernetes

Para habilitar el balanceador debemos añadir los siguientes datos en nuestro fichero de cloud_config:

  1. La subred donde se va a construir el balanceador.
  2. Debemos indicar que maneje los security groups.
  3. El security group que se debe aplicar al puerto del balanceador. Es el vip_port_id anterior.
  4. Y por último la id de la red de la que tomará la IP flotante.

Deberiamos tener algo así:

[LoadBalancer]
lb-version=v2
subnet-id=82f277d7-1b29-49b3-94ee-40424c4e36d9
manage-security-groups=true
node-security-group=b063453a-41fb-47e5-ac3e-fbe270fc2232
floating-network-id=ccee1f8b-c813-4a69-a072-ee1e10aba677

¿Qué tiene que pasar? Ahora, cuando en el service pongamos LoadBalancer Kubernetes utilizará las credenciales que le hemos proporcionado y construirá un balanceador completo para la aplicación. De la red que le hemos proporcionado cogerá un IP flotante libre. Esta es la IP a la que debemos atacar cuando queramos utilizar el servicio recién publicado.

Self Service Provisioning

Para que nuestras aplicaciones conserven los datos que generen en su tiempo de vida es necesario proporcionarles volúmenes de persistencia. Para ello comenzamos creando un nuevo objeto de Kubernetes llamado StorageClass donde vamos a definir como debe pedir el volumen a OpenStack y como vamos a llamarlo desde nuestra aplicación. Podemos definir tantos como sistemas de aprovisionamiento tengamos. El StorageClass tiene esta pinta:

kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
  name: gold #-> este es el nombre con el que nos referiremos a el cuando hagamos el claim
provisioner: kubernetes.io/cinder
parameters:
  type: kube-storage #-> Esto hay que definirlo en openstack
  availability: nova

Como vemos los dos valores que tenemos que definir son name y type. Entonces, cuando queramos que nuestra aplicación haga uso de esta persistencia dinámica usaremos algo como esto:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: claim1
  annotations:
    volume.beta.kubernetes.io/storage-class: gold #-> Este es el nombre que le hemos dado
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 30Gi

Antes había que hacer uso de PersistentVolume pero está siendo reemplazado por este nuevo objeto que creará el volumen dinámicamente.

Referencias

OpenStack: LoadBalancer as a Service v2

Vamos a ver como instalar y configurar LBaaSv2 en OpenStack Newton. Está montado sobre Ubuntu 16.04

Instalación

Toda la operación se desarrolla en el nodo controlador de OpenStack o donde esté configurada la red de Neutron

Puede parecer obvio, pero la documentación oficial no te dice que hay que instalar primero el plugin, para esto hacemos:

apt-get install neutron-lbaasv2-agent

Dependiendo de tu entorno instalará estas dependencias

python-pyasn1-modules:amd64 (0.0.7-0.1, automatic), haproxy:amd64 (1.6.3-1ubuntu0.1, automatic), liblua5.3-0:amd64 (5.3.1-1ubuntu2, automatic), python-neutron-lbaas:amd64 (2:9.0.0-0ubuntu1~cloud0, automatic), neutron-lbaasv2-agent:amd64 (2:9.0.0-0ubuntu1~cloud0), neutron-lbaas-common:amd64

Configuración

Vamos a editar los archivos de configuración:

En /etc/neutron/neutron.conf añadimos el plugin a la lista de plugins que haya.

service_plugins = [existing service plugins],neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2

En /etc/neutron/neutron_lbaas.conf añadimos una linea en la sección [service_providers]. Si ya tenemos otros proveedores de servicios como FWaaS o VPNaaS añadimos una linea nueva, Esta directiva de configuración permite repetición.

service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default

En /etc/neutron/lbaas_agent.ini añadimos el driver que maneja la interfaces virtuales:

interface_driver = INTERFACE_DRIVER

Yo uso linuxbridge, luego la línea quedaría así:

interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver

Finalizamos con el migrate de la base de datos.

neutron-db-manage --subproject neutron-lbaas upgrade head

Reiniciamos neutron

systemctl neutron-server restart

Reiniciamos el agente

systemctl restart Neutron-lbaasv2-agent

Y con esto termina la configuración.

Crear un LoadBalancer

Tenemos dos servidores web corriendo en nuestro Tenant y queremos balancear la carga. Los dos servidores son:

webserver-1 172.31.1.25
webserver-2 172.31.1.16

Deben estar incluidos en alguna regla que permita el trafico HTTP hacia ellos, en caso contrario podemos crearlo:

# Cargar en openrc
. openrc
# Crear el security group
neutron security-group-create http
# Crear la regla
neutron security-group-rule-create --direction ingress --protocol tcp --port-range-min 80 --port-range-max 80 --remote-ip-prefix 0.0.0.0/0 http

Vamos a crear el balanceador

neutron lbaas-loadbalancer-create --name test-lb private-subnet

private-subnet es una subred privada. Podemos consultar las redes disponibles haciendo:

openstack network list

El balanceador se crea en unos segundos, podemos verlo así:

neutron lbaas-loadbalancer-show test-lb

Que mostrará algo como esto:

+---------------------+------------------------------------------------+
| Field               | Value                                          |
+---------------------+------------------------------------------------+
| admin_state_up      | True                                           |
| description         |                                                |
| id                  | 12826d46-9854-4123-9193-37b8c2511729           |
| listeners           | {"id": "75d5218b-948e-482b-b7a9-d831d0feb476"} |
| name                | test-lb                                        |
| operating_status    | ONLINE                                         |
| pools               | {"id": "860726ba-1997-453f-9e32-7879254e3306"} |
| provider            | haproxy                                        |
| provisioning_status | ACTIVE                                         |
| tenant_id           | d245f207e6fc4e56b5a1d23e0716ad70               |
| vip_address         | 172.31.1.23                                    |
| vip_port_id         | 1e090071-2800-4468-8ab7-0493d0881e10           |
| vip_subnet_id       | a03252b6-e67e-48d9-89fc-edc3872d83ae           |
+---------------------+------------------------------------------------+

Apuntar el valor de vip_port_id porque lo necesitaremos más adelante.

Vamos a crear los grupos de seguridad necesarios para dirigir tráfico al balanceador:

$ neutron security-group-create lbaas
$ neutron security-group-rule-create \
  --direction ingress \
  --protocol tcp \
  --port-range-min 80 \
  --port-range-max 80 \
  --remote-ip-prefix 0.0.0.0/0 \
  lbaas
$ neutron security-group-rule-create \
  --direction ingress \
  --protocol tcp \
  --port-range-min 443 \
  --port-range-max 443 \
  --remote-ip-prefix 0.0.0.0/0 \
  lbaas
$ neutron security-group-rule-create \
  --direction ingress \
  --protocol icmp \
  lbaas

Hemos permitido trafico HTTP, HTTPS y el ping. Ahora aplicamos las reglas al puerto del balanceador. El vip_port_id que apuntamos antes.

$ neutron port-update \
  --security-group lbaas \
  1e090071-2800-4468-8ab7-0493d0881e10

Podemos comprobar que está activo al hacer ping.

ping -c3 172.31.1.23
PING 172.31.1.23 (172.31.1.23) 56(84) bytes of data.
64 bytes from 172.31.1.23: icmp_seq=1 ttl=62 time=19.2 ms
64 bytes from 172.31.1.23: icmp_seq=2 ttl=62 time=0.491 ms
64 bytes from 172.31.1.23: icmp_seq=3 ttl=62 time=0.312 ms

--- 172.31.1.23 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.312/6.678/19.232/8.877 ms

Creamos los listeners para el balanceador:

$ neutron lbaas-listener-create \
  --name test-lb-http \
  --loadbalancer test-lb \
  --protocol HTTP \
  --protocol-port 80

Y por último el pool de servidores a los que se balancea:

$ neutron lbaas-pool-create \
  --name test-lb-pool-http \
  --lb-algorithm ROUND_ROBIN \
  --listener test-lb-http \
  --protocol HTTP
$ neutron lbaas-member-create \
  --subnet private-subnet \
  --address 172.31.1.16 \
  --protocol-port 80 \
  test-lb-pool-http
$ neutron lbaas-member-create \
  --subnet private-subnet \
  --address 172.31.1.25  \
  --protocol-port 80 \
  test-lb-pool-http

Ya sólo nos queda comprobar que funciona:

$ for i in $(seq 1 4); do curl 172.31.1.23; done
webserver-1
webserver-2
webserver-1
webserver-2

Empaquetando Aplicaciones para Kubernetes

En la entrada anterior hemos visto como utilizar las herramientas que nos proporciona Kubernetes para construir nuestra aplicación. Ahora vamos a ver lo fácil que es construir un paquete con toda la información que va a necesitar nuestra aplicación para funcionar.

El gestor de paquetes de Kubernetes

El gestor de paquete de Kubernetes se llama Helm. También es el nombre del comando.

Para instalar Helm simplemente nos descargamos el binario y lo colocamos en el PATH.

$ wget http://storage.googleapis.com/kubernetes-helm/helm-v2.1.3-linux-amd64.tar.gz
$ mv linux-amd64/helm /usr/local/bin/helm

Podemos ver que está instalado con:

$ helm version
Client: &version.Version{SemVer:"v2.1.2", GitCommit:"58e545f47002e36ca71ac5d1f7a987b56e1937b3", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.1.2", GitCommit:"58e545f47002e36ca71ac5d1f7a987b56e1937b3", GitTreeState:"clean"}

Helm cuenta con otro componente que se llama Tiller, es un pod que actua como un agente dentro de Kubernetes. La forma más rápida de desplegar el agente es así:

$ helm init

Esto tomará los valores por defecto para conectar con el clúster y desplegar el agente. Vemos el agente desplegado como pod

$ kubectl --namespace=kube-system get pods --selector='name=tiller'
NAME                             READY     STATUS    RESTARTS   AGE
tiller-deploy-3161388333-0lqd4   1/1       Running   8          6d

Estructura de un paquete para Kubernetes/Helm

Al igual que otros paquetes como los deb de Debian los paquetes de Helm se llaman Charts y tienen la siguiente estructura:

wordpress/
  Chart.yaml          # A YAML file containing information about the chart
  LICENSE             # OPTIONAL: A plain text file containing the license for the chart
  README.md           # OPTIONAL: A human-readable README file
  values.yaml         # The default configuration values for this chart
  charts/             # OPTIONAL: A directory containing any charts upon which this chart depends.
  templates/          # OPTIONAL: A directory of templates that, when combined with values,
                      # will generate valid Kubernetes manifest files.
  templates/NOTES.txt # OPTIONAL: A plain text file containing short usage notes

Todos nos interesan ahora mismo excepto el de charts/ porque nuestro Chart (de wordpress) no depende de ningún otro. Vamos a ir viendo cada uno al tiempo que vemos como lo hemos adaptado a nuestros yaml para wordpress

Nuestro Chart de WordPress

Chart.yaml

name: wp-helm
description: An example of Helm and WordPress
version: 0.1.0
keywords:
  - http
  - wordpress
  - www
  - web
  - cms
home: "https://www.wordpress.org"
sources:
  - "https://github.com/nordri/helm-wordpress"
maintainers:
  - name: nordri
    email: nordri@gmail.com
engine: gotpl

No hay mucho que contar, está bastante claro. La opción engine hace referencia al parseador que usaremos para las plantillas, la opción por defecto si no se indica es gotpl que es el que usa Golang, como Jinja2 para Python.

LICENSE

Es el texto de la Licencia Apache 2

README.md

La información relativa a nuestro Chart, como funciona y demás

Un ejemplo de WordPress con Helm y Kubernetes.........

values.yaml

Este fichero contiene los datos de nuestra instalación. Como por ejemplo el nombre del sitio. Puertos a usar, usuarios y contraseñas.

image: wordpress
db_server: 192.168.1.43
root_db_password: root01
nfs_path: srvnfs
nfs_server: 192.168.1.43
pv_size: 20Gi
pvc_size: 2Gi
hostname: wordpress
resources:
  requests:
    memory: 128Mi
    cpu: 500m

Para este ejemplo hemos introducido dos nuevos parámetros que van a controlar el uso de los recursos por parte de nuestra aplicación. La memoria que hemos establecido a 128Mi y la cpu a 500m (500 milicores)

charts

Si usáramos dependencias de otros charts los incluiríamos en este directorio. Seguiría la misma estructura de directorios del padre, por ejemplo si nuestro chart depende del chart Apache y MySQL sería:

wordpress:
  Chart.yaml
  requirements.yaml
  # ...
  charts/
    apache/
      Chart.yaml
      # ...
    mysql/
      Chart.yaml
      # ...

templates

Aquí es donde vamos a definir cada uno de los componentes que conforman nuestra aplicación. Cada fichero yaml que utilizamos en la entrada anterior aparece aquí parametrizado para que coja los valores del fichero de values.yaml. Por no alargar mucho la entrada vamos a ver los detalles más significativos:

Hay dos ficheros clave que son _helpers.tpl y NOTES.txt. El primero es donde definimos funciones que serán ejecutadas por el parseador y el segundo es el mensaje que presentaremos cuando la aplicación se instale, como la URL de acceso.

Una vez tenemos las funciones definidas podemos hacer uso de ellas dentro de nuestras plantillas. En nuestro caso usamos la función template con el parámetro “fullname” para obtener el nombre de la instalación. Esto es porque, al igual que con Docker, cada instalación recibe un nombre aleatorio dentro del clúster, así podemos definir por ejemplo para nuestro servicio la siguiente línea:

name: {{template "fullname" .}}-svc

Ese será el nombre del servicio y lo usaremos para relacionar cada componente de la aplicación dentro del cluster.

Lo siguiente será sacar valores del fichero values.yaml y usaríamos la siguiente sintaxis:

# Obtener el nombre del host que le pasaremos a ingress
- host: {{ .Values.hostname }}

También podemos tener en la plantilla un nombre por defecto en caso que no se rellene ese valor en values.yaml

- host: {{ default "localhost" .Values.hostname }}

Los valores pueden hacer uso de pipelines al estilo Bash por ejemplo para cifrar una password y entrecomillarla. Lo vemos en el fichero de mysql-secrets.yaml.

mysql-root-password: {{.Values.root_db_password | b64enc | quote}}

Vemos que la contraseña está en plano en el fichero de values, la tomamos, la pasamos a base64 y la ponemos entre comillas.

Si queremos incluir trozos de values sin tener que referenciarlos uno a uno podemos hacer uso de toYaml que es una función para llamar a plantillas, tenemos que definir una plantilla dentro de values, nosotros hemos llamado resources y luego pasarla por la función de indentado, así si queremos incluir los resources que puede hacer uso el pod hacemos así:

{{ toYaml .Values.resources | indent 10 }}

Y tomará de values el trozo de plantilla que corresponda con resources y lo indentará 10 posiciones.

También se usa una lista de variables ya definidas que podemos consultar aquí

Instalando el paquete

Una vez tenemos todo instalamos el paquete. Si vemos la ayuda de Helm tenemos varias formas de instalar el paquete:

[...]
1. By chart reference: helm install stable/mariadb
2. By path to a packaged chart: helm install ./nginx-1.2.3.tgz
3. By path to an unpacked chart directory: helm install ./nginx
4. By absolute URL: helm install https://example.com/charts/nginx-1.2.3.tgz
[...]

Si lo instalamos usando la opción 3 veremos algo parecido a esto:

NAME:   winsome-tortoise
LAST DEPLOYED: Thu Dec 29 12:19:26 2016
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Secret
NAME                                TYPE      DATA      AGE
winsome-tortoise-wordpress-secret   Opaque    1         1s

==> v1/PersistentVolume
NAME                            CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                                    REASON    AGE
winsome-tortoise-wordpress-pv   20Gi       RWX           Retain          Bound     default/winsome-tortoise-wordpress-pvc             1s

==> v1/Service
NAME                             CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
winsome-tortoise-wordpress-svc   10.111.214.123          80:32590/TCP   1s

==> extensions/Deployment
NAME                         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
winsome-tortoise-wordpress   1         1         1            0           1s

==> extensions/Ingress
NAME                             HOSTS       ADDRESS   PORTS     AGE
winsome-tortoise-wordpress-ing   wordpress             80        1s

==> v1/PersistentVolumeClaim
NAME                             STATUS    VOLUME                          CAPACITY   ACCESSMODES   AGE
winsome-tortoise-wordpress-pvc   Bound     winsome-tortoise-wordpress-pv   20Gi       RWX           1s


NOTES:
Los datos de acceso son los siguientes:

Host: wordpress

Donde vemos un resumen de los componentes que han sido lanzados y la información que nos da el fichero NOTES.txt. Vemos las aplicaciones instaladas a través de helm, asi

$ helm list
NAME               REVISION    UPDATED                     STATUS      CHART        
winsome-tortoise    1           Thu Dec 29 12:19:26 2016    DEPLOYED    wp-helm-0.1.0

Si quisiéramos eliminar la aplicación hariamos:

$ helm delete winsome-tortoise

Repositorio

Aquí el repositorio en GitHub: aquí