Flex Hub
At this step, we assume that infrastructure has been setup and is ready to be consumed.
Virtual machines or metal servers are ready to be connected to and reachable from a network connectivity perpsective, featuring latest Linux Ubuntu LTS release.
Connectivity to Flex instances is out of the scope of this documentation.
Ansible requires SSH connectivity to reach out each individual instance and instrument the deployment. Whether you have a direct IP connection to the targeted servers or require a dedicated VPN to be setup is up to each operator but the machine running Ansible must be able to reach out the desired network.
Ansible requires SSH access with root/admin privilege. As to bootstrap deployment, it is then required that you have at least one local UNIX account that you can connect to through SSH, with sudo privileges.
How this account is initially provisonned and Whether one can connect through public key or password-based authentication is up to each operator.
It is recommended that all targeted instances have the same local user name or public key (or password) to ease deployment process. It is suggested to provision initial OS instances through a global pre-configured disk image.
Inventory Management
Ansible requires an inventory file as input to understand which machines are to be targeted by various operations and profiles.
On some cases (Cloud, AWS), inventory can be auto-discovered through various inventory plugins, provided the different resources are properly tagged.
On may cases however, inventory can be described in ansible/inventories/host.txt or ansible/inventories/host.{TAG}.txt, where TAG is something like 'stg' or 'prod' for example, as defined in META.yml file.
One can also set its own inventory filename, by setting the defaults.inventory variable accordingly in ansible/ansible.cfg configuration file.
Depending on your infrastructure provider and the Terraform modules you've used, this static inventory file can be auto-generated as well.
If yours starts with the following header:
###################################################################
# DO NOT EDIT: This file has been generated from Terraform output #
###################################################################
this should be self-explicit not to touch it ;-)
When on-premises, you probably have no other choice but to write your own.
Ansible's inventory file format is INI-formatted. It basically consists of sections for each group of machines, containing the list of associated instances.
Example:
[consul]
10.0.0.21 name=flex-stg-srv-1
10.0.0.22 name=flex-stg-srv-2
10.0.0.23 name=flex-stg-srv-3
In this example, consul is the group name. All instances from the group will be receptacles for the Consul software deployment. Each line represent a specific server instance. It starts with its IP address and is followed by one to many optional key=value parameters. The name parameter is mandatory and corresponds to the instance hostname.
Additional special parameters can be added to each and every instance description, to control how you connect to each of them, should there be any asymetry.
It is also possible to override global platform's variables (as defined in ansible/vars/variables.yml file) per-host, should you need a specific behavior.
Server instances can be part of multiple groups and they usually are, with Flex deployment. Dalet Flex comes with various pre-defined instance profiles (monitor, services, app, job ...) but exact workload placement is up to each and every operator (especially when running on-premises with bare metal servers).
How (and where) each micro-service will be deployed depends on the groups defined in inventory. Group names match available Flex services and any instance you put in a given group will feature an instance of the deployed service.
If not auto-generated, the exhaustive list of Flex inventory group can be determined from the following command:
cat ansible/collections/ansible_collections/dalet/flex/vars/services.yml | grep group | sed 's%.*group: \(.*\)%\1%' | grep -v dummy | uniq | sort
At the time of this writing, it consists of:
admin
adobepremierepanel
api
assettransfer
authentication
authorisation
bbcudrencrichment
blackpearl
collection
cut
daletai
dashboard
dataaggregation
divarchive
eventhandler
events
executionconfiguration
fastobject
fileaccess
fileprocessor
filereplication
filescan
fmp
fmpadmin
fmpreviewer
forms
globalheader
hotfolder
imageproxy
indexelastic
instream
job
jobasyncexecutor
jobengine
jobexecutionmanager
jobremoteengine
liveingest
login
manage
master
mediacortex
metadata
metadatadesigner
metadatamerge
mobile
nginx
operationsdashboard
outboundtransfer
panels
publish
publishindexer
registry
replicationgateway
reviewer
s3inventory
search
searchelastic
secrets
sequencemanifest
smokeresource
streamprocessor
subtitle
tableaupublisher
tag
taxonomy
thesaurus
transcoderesource
usage
usersettings
videoproxy
webtransfer
workflowdesigner
writeobject
xtendadobepanel
xtendamepanel
Do to some upstream limitation in Java Wildfly stack, instance hostnames have a mamximum length of 23 characters. It is VITAL that whatever naming convention you use, you stick to that limit.
Setting Platform Variables
You now need to provide quite a few essential platform-specific variables to instrument Ansible what to do next. Further from the exhaustive list of variables that can be set, some are mandatory.
If not already defined by templating and/or Terraform automation, variables are supposed to be set in ansible/vars/variables.yml file.
Mandatory ones are:
dalet_flex_release: x.y.z
where x.y.z is the very specific Flex release you intend to deploy. This variable will condition the whole deployment and the exact manifest of what type of micro-service (and associated version) must be deployed.
Next to that are a few other ones, related to platform identifier and private/public network domain and subnets to be used:
dalet_flex_platform_id: "flex-acme"
dalet_flex_platform_private_fqdn: "flex.acme.com"
dalet_flex_platform_public_fqdn: "flex.acme.local"
dalet_flex_platform_private_subnet_cidr: "10.0.0.1/25"
and container registry access:
dalet_flex_application_registry: registry.services.ooflex.net
dalet_flex_application_registry_user: ""
dalet_flex_application_registry_password: "{{ vault_dalet_flex_application_registry_password }}"
Pulling Code
In order to deploy Flex, you first need to locally retrieve the CasC codebase. The whole content is managed in an Ansible Collection, which location and version is described in the ansible/requirements.yml file.
Its content looks like:
collections:
- name: git@bitbucket.org:ooyalaflex/ansible-flex-collection
type: git
version: master
Retrieving the collection (and its dependancies) is as easy as:
$ opsctl update
which should provision the ansible/collections/ansible_collections/dalet/flex directory (amongst other collections).
Once Flex collection has been pulled, we can now pull additional required Ansible roles.
This can be done though:
$ opsctl deploy -p dalet.flex.init
which in turn will create the ansible/roles directory with required roles.
Pre/Post Tasks
While most of the generic Flex deployment tasks comes bundled with the associated Ansible collection, there might be use-cases where you need to add specific pre- or post- tasks.
Pre-tasks may be specific things like doing an automatic API call to your favorite monitoring system to call for maintenance before any change, installing a specific agent on the platform or adding/formatting/partionning specific data disks for example.
Post-tasks can be the very opposite: calling off maintenance after successful application deployment or notifying whoever needs be by specific means.
Pre-tasks are called before any generic Flex collection tasks. Post-tasks are called after that. Pre and post tasks are writing as simple YAML formatted Ansible rules and, are playbook-centric.
Their execution is bound to a specific playbook, and this playbook only (for instance, disk paritioning could make sense at infra playbook level, but not when running others).
Pre/post tasks are respectively defined in:
ansible/tasks/{PLAYBOOK_NAME}/{pre,post}.yml
where PLAYBOOK_NAME is the name of the playbook to be executed. (e.g. infra when running dalet.flex.infra playbook from Flex collection).
At this stage, you should have everything ready to start the initial application deployment.
Bootstrap
We can finally deploy ! Let's start with basic infrastructure setup and operating system configuration.
Start by running:
$ opsctl deploy -p dalet.flex.infra
which will essentially runs the Dalet BaseOS collection to ensure the operating system is fully configured. The playbook will take care of installaing various system application, tuning in kernel settings, when required and appropriate, setting up network mount points, if any, and installing observability agents.
Let's continue by ensuring that OS packages are up-to-date:
$ opsctl deploy -p dalet.flex.os
User Management
Dalet Flex allows you to create various UNIX admin user accounts on the different instances.
These are not application accounts.
They are DevOps system account meant to operate on the core system.
You can extend the following variables with a list of nominative user accounts to be created and paths to local directories where their respective public SSH keys are to be found, e.g.:
dalet_baseos_users_admin_accounts_enabled: ["jdoe", "ops", "it"]
dalet_baseos_users_admin_accounts_pubkey_dirs: ["files/ssh", "files/pubkeys"]
And rollout system users account creation:
$ opsctl deploy -p dalet.flex.users
Remote Network Storage
Should you be using remote network storage (e.g. NFS), your network share must have the following directories pre-created:
- /filestore
- /media
in order for Flex to mount them appropriately.
Let's Start !
From now on, all servers should be provisioned, bootstrapped, with latest OS updates, and feature proper user accounts for DevOps operators to access to.
If you feel like rebooting the different instances to ensure your run the latest Linux kernel version before deploying the Flex application, now is the good time ;-)
Note that these playbooks are generic and target every single instance (the all group) from your platform.