Upload
giacomos
View
897
Download
0
Embed Size (px)
Citation preview
dallo sviluppo alla produzione
Livin' with Docker
abstract per DockerOps 2016 [giacomo.spettoli, simone.deponti]@abstract.it/
Indice (Spoiler alert!)
● Introduzione del caso di studio
● Perchè proprio docker?
● Lo sviluppo
● CI / CB / CD
● Deploy
● Produzione
Obiettivi del progetto
● Migrazione portale del cliente verso
una soluzione basata sul cms Plone
● Fornire una soluzione gestionale su
misura con Odoo (aka OpenERP)
Pecularità● vari strati software da configurare e
far interagire (nginx, elasticsearch,
postgres, haproxy.)
● gruppo di lavoro distribuito e
variabile per numero e componenti
Possibili soluzioni...
● configurazione a mano! (“I’m on a
highway to Hell ♫”)
● sistema di provisioning (chef, puppet,
ansible, #younameit)
● sistema di virtualizzazione (vagrant +
virtualbox, vmware, hyperv, ...)
...docker!
● più leggero e modulare di una VM
● più stabile e scalabile di un sistema
di provisioning
● essendo un cambio di paradigma
bisogna trovare il modo giusto di
usarlo (per il contesto specifico)
la fase di sviluppo
Makefile + Ansible per il bootstrap
(download pacchetti, bower & grunt)
Docker-compose per l’orchestration dei
containers
il testing e le build: Jenkins
1. scarica il codice
2. fa il build delle immagini
3. esegue i test
4. fa il push sul nostro registry
Bonus: Jenkins dentro ad un container
docker che si connette al docker padre
il testing e le build: Jenkins
1. scarica il codice
2. fa il build delle immagini
3. esegue i test
4. fa il push sul nostro registry
Bonus: Jenkins dentro ad un container
docker che si connette al docker padre
il testing e le build: Jenkins
1. scarica il codice
2. fa il build delle immagini
3. esegue i test
4. fa il push sul nostro registry
Bonus: Jenkins dentro ad un container
docker che si connette al docker padre
il testing e le build: Jenkins
1. scarica il codice
2. fa il build delle immagini
3. esegue i test
4. fa il push sul nostro registry
Bonus: Jenkins dentro ad un container
docker che si connette al docker padre
il testing e le build: Jenkins
1. scarica il codice
2. fa il build delle immagini
3. esegue i test
4. fa il push sul nostro registry
Bonus: Jenkins dentro ad un container
docker che si connette al docker padre
l’hosting: CoreOS
● droplet CoreOS su DO
● containers orchestrati con systemd
● config via cloudinit
il deploy: ansible e cloudinit
1. ansible fa il push della config
cloudinit
2. viene eseguito il setup cloudinit
3. vengono riavviati i container
il deploy: ansible e cloudinitname: copy cloud-init
copy:
src: "cloudinit/{{inventory_hostname}}.yml"
dest: /etc/custom-cloud-init
owner: root
sudo: yes
il deploy: ansible e cloudinit
1. ansible fa il push della config
cloudinit
2. viene eseguito il setup cloudinit
3. vengono riavviati i container
il deploy: ansible e cloudinit
name: run cloudinit
shell: coreos-cloudinit -from-file=/etc/custom-cloud-
init
sudo: yes
il deploy: ansible e cloudinit#cloud-configwrite_files:
- path: /home/core/.docker/config.json owner: core:core permissions: 0644 content: | { "auths": { "https://registry.abstract.it": { "auth": "bWFjaGlu… ", "email": "[email protected]" } } }
il deploy: ansible e cloudinitcoreos: … units: - name: "pullimages.service" content: | [Unit] Description=Pulls all required images After=docker.service Requires=docker.service
[Service] User=core Type=oneshot ExecStart=/usr/bin/docker pull busybox:latest ExecStart=/usr/bin/docker pull postgres:9.4 …
il deploy: ansible e cloudinit - name: "ploneanon02.service"
command: "start" content: | [Unit] Description=Plone (Anonymous) After=blobdata.service mysql.service postgresplone.service … Requires=blobdata.service pullimages.service
[Service] User=core TimeoutStartSec=0 Restart=on-failure ExecStartPre=-/usr/bin/docker kill ploneanon02 ExecStartPre=-/usr/bin/docker rm -v ploneanon02 ExecStart=/usr/bin/docker run --name=ploneanon02 --volumes-from=blobdata -e … registry.abstract.it/teatroit/plone:latest ExecStop=/usr/bin/docker stop ploneanon02
il deploy: ansible e cloudinit- name: "backup.service"
content: |
…
[Service]
Type=oneshot
ExecStart=/usr/bin/docker run --rm -v /tmp:/tmp -e ...
--entrypoint=/usr/bin/pg_dump postgres:9.4 -f /tmp/postgresqlusers.dump -F c
…
ExecStart=/usr/bin/curl -XPUT http://localhost:9200/_snapshot/total -d
'{"type":"fs","settings":{"compress":"true","location":"/srv/webapp/var/
elastic/"}}'
ExecStart=/usr/bin/bash -c "/usr/bin/curl -XPUT
http://localhost:9200/_snapshot/total/$(date +%Y%m%d%H%M%S)?
wait_for_completion=true"
ExecStart=/usr/bin/docker run --rm -v ... --volumes-from=... -e …
jerob/docker-duplicity:latest bash /duplicity
il deploy: ansible e cloudinit
1. ansible fa il push della config
cloudinit
2. viene eseguito il setup cloudinit
3. vengono riavviati i container
il deploy: ansible e cloudinit - name: stop services service: name: "{{item}}.service" state: stopped with_items: - nginx - varnish … sudo: yes - name: start services service: name: "{{item}}.service" state: started with_items: - pullimages - postgresusers …
Conclusioni
● siamo volutamente partiti “bassi” (niente scheduling)
● entrare mentalmente nel “concetto” di container (stateless)
● certe cose sono difficili da mettere in un container (RDBMS)
Questions?
Thanks!
Giacomo [email protected]
Simone [email protected]