Creació del llibre de cuina
Passos finals
Hi ha moltes maneres d'automatitzar el procés de configuració i configuració d'una caixa. Per qualsevol motiu, si tot el nostre sistema en aquest moment consta d'una sola caixa, configurar una infraestructura SCM (Gestió de la configuració de programari) completa és excessiva. Els scripts de Shell són una opció, però també podríem utilitzar una versió simplificada de SCM que està disponible en algunes de les eines que hi ha. Chef és una de les opcions populars i "chef-solo" és el mode de configuració autònom de Chef on no necessitem un node addicional per actuar com a "chef-server". Tot el que necessita és una URL o un camí cap a un paquet tarball que contingui llibres de cuina del xef. En comparació amb els scripts d'intèrpret d'ordres, aquest tipus d'enfocament és més declaratiu i eficaç des de la caixa i també és una bona introducció per començar amb els processos SCM o IaC (Infraestructura com a codi).
Alguns altres avantatges d'utilitzar chef-solo:
- Composabilitat: utilitzeu els llibres de cuina de la comunitat del supermercat del xef o d'altres llocs.
- Lliure i codi obert; amb llicència sota la permissiva llicència Apache 2.0.
- Accés a la resta de l'ecosistema del xef (InSpec, ChefSpec, Cookstyle, Foodcritic, chef-shell, etc.)
- Els llibres de cuina i les receptes es poden adaptar posteriorment a un mode client/servidor.
I alguns desavantatges:
- Alguns llibres de cuina comunitaris del supermercat Chef estan obsolets, trencats i no es mantenen.
- chef-solo no pot resoldre les dependències per si sol.
Les "receptes" dins d'un "llibre de cuina" del xef tenen un DSL basat en rubí que descriu que els "recursos" es troben en un estat particular en un node. Continuem amb una guia per familiaritzar-nos amb alguns conceptes de xef que també són aplicables al xef en solitari. El nostre objectiu és configurar un node Ubuntu que executi una aplicació web Python/Django mitjançant Gunicorn i NGINX.
Note: We do not necessarily require ChefDK to be installed on our "Chef workstation" (our machine), although with it, we can use 'chef generate' commands to start-off with a directory structure for creating cookbooks, recipes and more. In this article, we will assume ChefDK is installed on our workstation. Commands were run using the version 4.7.26-1 of ChefDK.
(Tot a partir d'aquest punt, tret que s'especifiqui el contrari, s'ha d'executar a la nostra màquina, també anomenada "estació de treball del xef").
Creació del llibre de cuina
Els llibres de cuina en xef són unitats reutilitzables que contenen tot el necessari per donar suport a un escenari de configuració. Els llibres de cuina poden contenir múltiples "receptes" i les "receptes" consisteixen principalment en patrons de recursos. default.rbés la recepta predeterminada que s'executarà quan es faci referència al llibre de cuina en una llista d'execució . Les diferents receptes permeten separar les preocupacions. Per a aquest tutorial, però, afegirem totes les declaracions de recursos en un fitxer de receptes principal, que és el fitxer default.rb.
Creeu una carpeta anomenada "my-chef-project" i creeu una carpeta dins d'ella anomenada "cookbooks". Des de ./my-chef-project/cookbooks/, executa:
$ chef generate cookbook my-cookbook
La nostra estructura de directoris serà ara així:
.
└── my-chef-project
└── cookbooks
└── my-cookbook
├── CHANGELOG.md
├── LICENSE
├── Policyfile.rb
├── README.md
├── chefignore
├── kitchen.yml
├── metadata.rb
├── recipes
│ └── default.rb
├── spec
│ ├── spec_helper.rb
│ └── unit
│ └── recipes
│ └── default_spec.rb
└── test
└── integration
└── default
└── default_test.rb
Afegint paquets
El primer pas per configurar el nostre node és identificar quins paquets requereix la nostra aplicació. El nostre node està seleccionat per ser Ubuntu, de manera que podem confiar en el gestor de paquets APT per recopilar les dependències. Instal·lar els paquets proporcionats per la distribució del sistema operatiu és, aleshores, fàcil:
apt_update
package 'python3'
package 'python3-pip'
package 'nginx'
package 'pkg-config'
package 'libcairo2-dev'
package 'libjpeg-dev'
package 'libgif-dev'
package 'libgirepository1.0-dev'
Això s'explica per si mateix. La primera línia actualitzarà el dipòsit d'apt i les línies següents instal·laran aquests paquets.
Note: The packages following 'nginx' are needed for compiling some of the python dependencies through pip. These may differ based on your python/django project dependencies specified in requirements.txt. You can use a trial and error method to determine these packages that you need to include in your cookbook. To do that, perform a manual sudo pip install -r requirements.txt (Note: This installs packages system wide!) on a freshly instantiated ubuntu machine to see if it runs successfully. If not, the stderr should give you hints on what packages are missing.
Creació d'usuaris de Linux
Un cop hem acabat d'afegir els paquets necessaris, hem de crear un usuari de Linux no privilegiat que serà el propietari del codi font de l'aplicació.
user 'bob' do
uid 1212
gid 'users'
home '/home/bob'
shell '/bin/bash'
password '$1$alilbito$C83FsODuq0A1pUMeFPeR10'
end
Tingueu en compte que la contrasenya és un format hash d'ombra utilitzat a Linux. Es pot derivar mitjançant OpenSSL:
$ openssl passwd -1 -salt alilbitof mypassword
Incloent la font de l'aplicació
Ara incloem el codi font de l'aplicació Django al nostre llibre de cuina. Col·loqueu el codi font dins ./my-chef-project/cookbooks/my-cookbook/files/default/myapp/
Creeu el ./my-chef-project/cookbooks/my-cookbook/files/defaultdirectori si no existeix.
Les instruccions per copiar aquests fitxers a una ubicació remota del nostre node es descriuen mitjançant el recurs remote_directory :
remote_directory '/home/bob/myapp' do
source 'myapp' # This is the name of the folder containing our source code that we kept in ./my-cookbook/files/default/
owner 'bob'
group 'users'
mode '0755'
action :create
end
Traient les dependències de Python
Per instal·lar els paquets Python a requirements.txt, podem utilitzar el recurs execute per executar una ordre arbitrària. En aquest cas, hem d'executar-hi l'ordre d'instal·lació pip:
execute 'install python dependencies' do
command 'pip3 install -r requirements.txt'
cwd '/home/bob/myapp'
end
Note: Bear in mind that this is going to execute as the root user and the python libraries will be installed system-wide. If our node is designated to exclusively run this one single python app, then it isn't much of a problem. Despite that, a better option to keep things clean and sane is to find and use a community cookbook that manages python installations or 'virtualenvs'. (or at the very least, write a series of execute blocks to replicate this). Using virtualenvs in python ensures that any python based system tools or other python projects will not be affected
Configuració de Gunicorn i NGINX
Ara és el moment de preparar el servidor HTTP Gunicorn WSGI amb NGINX com a servidor intermediari invers. Nginx també s'utilitza per gestionar tots els actius estàtics de Django.
Per connectar Gunicorn com a servei a Ubuntu, es pot utilitzar Systemd. El recurs systemd_unit s'inclou a Chef des de la versió 12.11.
systemd_unit 'gunicorn.service' do
content({
Unit: {
Description: 'Django on Gunicorn',
After: 'network.target',
},
Service: {
ExecStart: '/usr/local/bin/gunicorn --workers 3 --bind localhost:8080 myapp.wsgi:application',
User: 'bob',
Group: 'www-data',
WorkingDirectory: '/home/bob/myapp'
Restart: 'always',
},
Install: {
WantedBy: 'multi-user.target',
}
})
action [:create, :enable, :start]
end
Ara hem d'incloure una configuració de proxy NGINX estàndard a aquest servidor Gunicorn tal com es mostra a continuació. Aquest fragment pot entrar a ./my-cookbook/templates/nginx.conf.erb. Creeu el directori de plantilles si no existeix.
Note: Chef's templates support embedded ruby files that can contain variables, ruby expressions and statements. Although this file has the 'erb' extension, we did not use any of the ruby statements or expressions. Also, for the sake of simplicity, we only have a non HTTPS nginx config here (gentle reminder; please do not do this in production!)
server {
listen 80;
server_name http://example.com/;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/bob/myapp/myapp/static;
}
location / {
include proxy_params;
proxy_pass http://localhost:8080/;
}
}
Note: There is also an alternative and a better config, where, for instance the Gunicorn server is bound to a unix domain socket instead of a TCP loopback connection. It's worth exploring that for performance reasons.
Per copiar aquesta configuració a la carpeta habilitada per a llocs del node, utilitzeu el recurs de plantilla de Chef.
template '/etc/nginx/sites-available/example.com.conf' do
source 'nginx.conf.erb'
owner 'root'
group 'root'
mode '0744'
end
L'activació de les configuracions a nginx es fa normalment creant un enllaç simbòlic que apunta a la configuració a sites-availablela sites-enabledcarpeta de nginx . Els enllaços simbòlics es poden declarar als llibres de cuina del xef amb el recurs d' enllaç que es mostra a continuació:
link '/etc/nginx/sites-enabled/example.com.conf' do
to '/etc/nginx/sites-available/example.com.conf'
end
i per eliminar l'enllaç simbòlic de configuració predeterminat:
link '/etc/nginx/sites-enabled/default' do
action :delete
end
S'està iniciant NGINX
I, finalment, per activar el servei nginx:
service 'nginx' do
action :enable
action :start
end
Llistes d'execució
Les llistes d'execució del xef són una llista ordenada de rols o receptes en un llibre de cuina que s'executaran en seqüència al node. Tenim un llibre de cuina "el meu llibre de cuina" i la recepta "predeterminada" al seu interior que hem d'executar a la caixa d'Ubuntu, de manera que el runlist.json al directori del nostre projecte ( ./my-chef-project/runlist.json) hauria de ser així:
{
"run_list": [
"recipe[my-cookbook::default]"
]
}
Passos finals
El nostre llibre de cuina per a xef en solitari ja està a punt per ser servit. És hora de subministrar una màquina Ubuntu 18.04 i instal·lar-hi ChefDK:
$ ssh root@example.com 'apt-get update && yes | apt-get install curl && curl https://packages.chef.io/files/current/chefdk/4.7.45/ubuntu/18.04/chefdk_4.7.45-1_amd64.deb -o chefdk.deb && yes | dpkg -i chefdk.deb && rm chefdk.deb'
L'anar de nou a la nostra estació de treball de cuina , tot el que necessitem fer és posar els llibres de cuina carpeta dins d'un arxiu comprimit, la transferència d'aquest fitxer tar juntament amb el runlist.jsona el node remot ens aprovisionem dalt i executar la comanda xef en solitari:
(L'ordre següent s'ha d'executar dins del node o el "client del xef" i no de l'estació de treball del xef)
$ chef-solo --recipe-url $(pwd)/chef-solo.tar.gz -j $(pwd)/runlist.json --chef-license=accept
O aquí hi ha una línia única (que s'executarà des de ./my-chef-project/CWD a Chef Workstation):
tar zvcf chef-solo.tar.gz ./cookbooks &&\
scp chef-solo.tar.gz runlist.json root@example.com:~/ &&\
ssh root@example.com 'chef-solo --recipe-url $(pwd)/chef-solo.tar.gz -j $(pwd)/runlist.json --chef-license=accept'
Això és! Mireu que la sortida estàndard s'omple amb l'activitat del xef que intenta fer convergir el vostre node al que heu especificat als llibres de cuina. Chef-solo instal·larà totes les gemmes necessàries per a tots els llibres de cuina. Si l'ordre chef-solo té èxit, tindrem una aplicació Django que funciona darrere de nginx a la caixa d'Ubuntu. Navegueu al domini/IP per provar-lo.
Note: Remember that in django you may need to set this domain/ip in the ALLOWED_HOSTS list in settings.py.
Responent als canvis
Sempre que fem un canvi en el contingut del nostre directori del projecte (receptes, plantilles o el codi font de l'aplicació, etc.), només cal que executeu la línia anterior des del directori del projecte.
Tip: If the cookbook is version controlled with git (as it should), one good recommendation is to set git hooks to run this one-liner.
Allotjament del tarball (opcional)
Si mireu de prop l'última ordre del xef-solo, observeu que --recipe-urlestà pensat per prendre un URL. Això vol dir que podeu tenir un flux de treball on un CI crearà el vostre tarball de xef en solitari, el carregarà en algun lloc i configurarà el vostre node per treure'n periòdicament.
Tip: Use curl to pull the changed tarball periodically as a cronjob. curl -z $file will honor If-Modified-Since headers and will only download the tar ball if the remote file has been changed since the timestamp on the existing local $file.