Package: playlabs
Playlabs: the obscene ansible distribution~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Playlabs combines simple ansible patterns with packaged roles to create adocker orchestrated paas to prototype products for development to production.Playlabs does not deal with HA, for HA you will need to do the ansible pluginsyourself, or use kubernetes ... but Playlabs will do everything else, evenconfigure your own sentry or kubernetes servers !DISCLAMER: maybe it even works for you, but that's far from garanteed so far.Quick start===========Init your ssh user with your key and secure sshd and passwordless sudo::playlabs init root@1.2.3.4# all options are ansible options are proxiedplaylabs init @somehost --ask-become-passNow your user can install roles::playlabs install ssh,docker,firewall,nginx @somehostAnd deploy a project, examples::playlabs @somehost deploy image=betagouv/mrs:masterplaylabs @somehost deployimage=betagouv/mrs:masterplugins=postgres,django,uwsgibackup_password=fooprefix=ybsinstance=hackenv.SECRET_KEY=itsnotasecretplaylabs @somehost deployprefix=testenvinstance=$CI_BRANCHimage=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHAIf you have that work, creating an inventory is the way to move on, wether youwant to version configuration, add a deploy user for your CI, configure asecret backup password, add ssh-keys ...:playlabs scaffold ./your-inventoryInstall playlabs================Install with::pip3 install --user -e git+https://yourlabs.io/oss/playlabs#egg=playlabsRun the ansible-playbook wrapper command without argument to see the quickgetting started commands::~/.local/bin/playlabsRead the following for more gory details.0. Init=======Initializing means going from a naked system to a system with your own user,ssh key, dotfiles, sudo access, secure sshd, and all necessary dependencies toexecute ansible, such as python3. It will also install your friend account ifyou have an ansible inventory repository where you store your friend list inyml.You might need to pass extra options to ansible in some cases, for example ifyour install provides a passworded sudo, add ``--ask-sudo-pass`` or put thepassword in the CLI, since initializing will remove ::playlabs init @somehostplaylabs init user:pass@somehostplaylabs init user@somehost --ask-sudo-passplaylabs init root@somehost1. Roles========If you want to deploy your project, then you need to install the paas whichconsists of three roles: docker, firewall, and nginx. The nginx role sets uptwo containers, nginx-proxy that watches the docker socket and introspectsdocker container environment variables, such as VIRTUAL_HOST, to reconfigureitself, it even supports uWSGI. The other container is nginx-letsencrypt, thatshares a cert volume with the nginx-proxy container, and watches the dockersocket for containers and introspect variables such as LETSENCRYPT_EMAIL, toconfigure the certificates.Remember the architecture:- nginx-proxy container recieves requests,- nginx-letsencrypt container generates certificates,- other docker containers have environment variables necessary for the aboveThe CLI itself is pretty straightforward::playlabs install docker,firewall,nginx @somehost # the paas for the project roleplaybabs install sendmail,netdata,mailcatcher,gitlab @stagingplaybabs install sendmail,netdata,sentry user@productionThe difference between traditionnal roles and playlabs roles, is that inplaylabs they strive to have stuff running inside docker to leverage thearchitecture of the nginx proxy.Playlabs can configure sendmail of course, but also has roles providingfull-featured docker based mailservers or mailcatcher instances for your dev,training or staging environments for example.This approach comes from migrating away from "building in production" to"building immutable tested chroots", away from "pet" to "cattle".But if you're already an ansible hacker you're better off with ansible to do a**lot** more than than what docker-compose has to offer, such as managing usersand roles, on your SDN as in your apps.In fact, you will see role that consist of a single docker ansible module call,but the thing is that you can spawn it in one command and have it integratedwith the rest of your server, and even rely on ansible to provisionfine-grained RBAC in your own apps.2. Project: deployments=======================The `project` role is made to be generic and cover infrastructure needs todevelop a project, from development to production. Spawn an environment, herewith an example image this repo is tested against::playlabs @yourhost deploy betagouv/mrs:master '{"env":{"SECRET_KEY" :"itsnotasecret"}}'It will use the IP address by default if ansible finds it, set the dns with thedns option ``dns=yourdns.com``, or set it in ``project_staging_dns`` yamlvariable of `your-inventory/group_vars/all/project.yml`.This is because the default prefix is ``project`` and the default instance is``staging``. Let's learn a new way of specifiying variables, add to yourvariables::yourproject_production_image: yourimage:productionyourproject_production_env:SECRET_KEY: itsnotsecret# the above value could be encrypted with ansible-vault s_encryptThen you can deploy as such::playlabs @yourhost deploy prefix=yourproject instance=productionIf you configure yourhost in your inventory, in group "yourproject-production",then you don't have to specify the host anymore::playlabs @yourhost project prefix=$CI_PROJECT instance=$CI_BRANCH3. Project: plugins===================PostgreSQL or Django or uWSGI support are provided through project plugins,which you may activate as such:- specify ``-p postgres,uwsgi,django``- configure ``yourprefix_yourinstance_plugins=[postgres, uwsgi, django]``- add to Dockerfile ``ENV PLAYLABS_PLUGINS postgres,uwsgi,django``The order of plugins matters, having postgres first ensures postgres is startedbefore the project image.Plugins are directories located at the root of playlabs repo, but at some pointwe can imagine loading them from the image itself.Plugins contain the following:- vars.yml: variables that are auto-loaded- deploy.pre.yml: tasks to execute before deploy of the project image- deploy.post.yml: tasks to execute after deploy of the project image- backup.pre.sh: included in backup.sh template before the backup- backup.post.sh: included in backup.sh template before the backup- restore.pre.sh: included in restore.sh template before the restore- restore.post.sh: included in restore.sh template before the restore5. Inventory (git versioning of cfg)====================================Most roles require an inventory to be really fun. Initiate an empty repositorywhere you will store your data that the roles should use::playlabs scaffold your-inventoryIn inventory.yml you can define your machines as well as the roles they shouldbe included by default in when playing a role without a specific target::all:hosts:yourhost.com:otherhost:fqdn: yourdomain.tldansible_ssh_port: 22ansible_ssh_host: 123.12.12.23children:netdata:hosts:yourhostIn the above you have created a netdata group with a host yourhost. Executingthe netdata role without explicit @ target will automacitally install netdataon yourhost thanks to that.Given how free ansible limit syntax lets us, we can use rich notations such asthis one to add two hosts to two roles at once::children:netdata-mailcatcher:hosts: [yourhost.com, otherhost]You can add as much metadata as you want in group_vars, for now let's add someusers to ``your-inventory/group_vars/all/users.yml``::---users:- name: jlfirst_name: John  # used by django role for exampleemail: aoeu@example.comkey: 'ssh-...'roles:ssh: sudok8s: cluster-adminsentry: superuserBe carefull that roles for a user are a 2d matrix: each key or value maycorrespond to an ansible role name, the other is the level of user within thatrole, that's why roles is a key value pair.Every time you init a machine from a directory that is an inventory, itwill install all users.Options=======Ansible-------Some of the variables you can like ::-e key=value                    # set variable "key" to "value"-e '{"key":"value"}'            # same in json-i path/to/inventory_script.ext # load any numbers of inventory variables-i 1.2.4.4,                     # add a host by ip to this play--limit 1.2.4.4,                # limit play execution to these hosts--user your-other-user          # specify a particular username--noroot                        # don't try becoming root automaticallyGlobal variables----------------Variables that are used by convention accross roles::letsencrypt_uri=https...letsencrypt_email=your@...Role variables--------------Base variable are defined in `playlabs/roles/rolename/vars/main.yml` and startwith the `rolename_`, they can be overridden in your inventory's`group_vars/all/rolename.yml`.The base variable will default to the same variable without the `rolename_`prefix::# Set project_image project role variable from the command lineimage=your/image:tagRole structure--------------Default roles live in playlabs/roles and share the `standard directorystructure with ansible roles<https://docs.ansible.com/ansible/2.5/user_guide/playbooks_reuse_roles.html>`_,that you can scaffold with the ansible-galaxy tool.Playlabs use roles as alternatives as docker-compose when possible, rather thanpolluting the host with many services.Project variables-----------------The project role base variables calculate to be overridable by prefix/instance::# project_{image,*} base value references project_staging_{image,*} from inventoryinstance=staging# project_{image,*} base value references mrs_production_{image,*} from inventoryinstance=production prefix=mrsProject plugins variable------------------------The project role has a special plugins variable that can be overridden in theusual way, but it will also try to find it by introspecting the docker imagefor the `PLAYLABS_PLUGINS` env var ie::ENV PLAYLABS_PLUGINS postgres,django,uwsgi,sentryPlugin variables----------------Plugin variables are loaded by the project role for each plugin that it loadsif any.Base plugin variables start with `project_pluginname_` and the special`project_pluginname_env` variable should be a dict, they will be all merged toadd environment variables to the project container, project_env will be a mergeof all them plugin envs.Plugin env vars should preferably use overridable variables.Plugin structure----------------Default plugins live in playlabs/plugins and have the following files:- `backup.pre.sh` take files out of containers and add them to the $backup`variable- `backup.post.sh` clean up files you have taken out after the backup has been`done- `restore.pre.sh` clear the place where you want to extract data from the`restic backup repository- `restore.post.sh` load new data and clean after the project was restarted in`the snapshot version,- `deploy.pre.yml` ansible tasks to execute before project deployment, ie. spawn`postgres- `deploy.post.yml` ansible tasks to execute after project deployment, ie.`create users from inventory- `vars.yml` plugin variables declarationOperations==========By default, it happens in /home/yourprefix-yourinstance. Contents depend on theactivated plugins.In the /home/ directory of the role or project there are scripts:- `docker-run.sh` standalone command to start the project container, feel free`to have on that one- `backup.sh` cause a secure backup, upload with lftp if inventory defines dsn- `restore.sh` recovers the secure backup repository`with lftp if inventory desfines dsn. Without argument` list snapshots. With a`snapshot argument` proceed to a restore of that snapshot including project`image version and plugin data- `prune.sh` removes un-needed old backup snapshots- `log` logs that playlabs rotates for you, just fill in log files, it will doa copy truncate though, but works until you need prometheus or somethingFor backups to enable, you need to set backup_password, either with -e, eitherthrough yourpefix_yourinstance_backup_password.The restic repository is encrypted, if you set the lftp_dsn oryourprefix_yourinstance_lftp_dsn then it will use lftp to mirror them. If youtrash the local restic repository, and run restore.sh, then it will fetch therepository with lftp.