.. _Installation Guidelines:
============
Installation
============
Steps
-----
#. `Setup AWS Account`_
#. `Provision Required AWS Resources`_
#. `Provision Lambda Functions for Essentials`_
#. `Upload Essentials Configurations`_
#. `Create Scheduled Rules`_
Setup AWS Account
-----------------
``sosw`` implementation currently supports only AWS infrastructure. If you are running
production operations on AWS, we highly recommend setting up a standalone account for your
first experiments with ``sosw``. `AWS Organisations `_
now provide an easy way to set sub-accounts from the primary one.
To setup a completely isolated new account, follow the
`AWS Documentation `_
We shall require several services, but they are all supposed to fit in the
`AWS Free Tier. `_ As long as the resources are created using
CloudFormation, once you delete the stacks - the related resources will also be deleted
automatically to avoid unnecessary charges.
See :ref:`Cleanup` instructions in the :ref:`Tutorials` section.
Provision Required AWS Resources
--------------------------------
This document shall guide you through the setup process for ``sosw`` Essentials and different
resources required for them. All the resources are created using Infrastructure as Code
concept and can be easily cleaned up if no longer required.
.. warning::
The following Guide assumes that you are running these comands from some EC2 machine using
either Key or Role with permissions to control IAM, CloudFormation, Lambda, CloudWatch,
DynamoDB, S3 (and probably something else).
If you are running this in the test account - feel free to grant the IAM role of your EC2
instance the policy ``arn:aws:iam::aws:policy/AdministratorAccess``, but never do this in
Production.
If you plan to run tutorials after this, we recommend setting this up in ``us-west-2``
(Oregon) Region. Some scripts in the tutorials guidelines may have the region hardcoded.
Now we assume that you have created a fresh Amazon Linux 2 machine with some IAM Role having
permissions listed above. You may follow `this tutorial
`_
if feeling uncertain, just create a new IAM Role on Step 3 of the instance setup Wizard.
.. warning::
Do not run this in Production AWS Account unless you completely understand
what is going on!
The following commands are tested on a fresh EC2 instance of type ``t2.micro`` running
on default Amazon Linux 2 AMI 64-bit.
.. code-block:: bash
# Install required system packages for SAM, AWS CLI and Python.
sudo yum update -y
sudo yum install zlib-devel build-essential python3.7 python3-devel git docker -y
# Update pip and ensure you have required Python packages locally for the user.
# You might not need all of them at first, but if you would like to test `sosw`
# or play with it run tests
sudo pip3 install -U pip pipenv boto3
sudo mkdir /var/app
sudo chown ec2-user:ec2-user /var/app
cd /var/app
git clone https://github.com/sosw/sosw.git
cd sosw
# Need to configure your AWS CLI environment.
# Assuming you are using a new machine we shall just copy config with default region
# `us-west-2` to $HOME. The credentials you should not keep in the profile.
# The correct secure way is to use IAM roles if running from the AWS infrastructure.
# Feel free to change or skip this step if your environment is configured.
cp -nr .aws ~/
Now you are ready to start creating AWS resources. First let us provide some shared resources
that both ``sosw`` Essentials and ``sosw``-managed Lambdas will use.
.. code-block:: bash
# Get your AccountId from EC2 metadata. Assuming you run this on EC2.
ACCOUNT=`curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info/ | \
grep AccountId | awk -F "\"" '{print $4}'`
# Set your bucket name
BUCKETNAME=sosw-s3-$ACCOUNT
PREFIX=/var/app/sosw/examples/yaml/initial
# Create new CloudFormation stacks
for filename in `ls $PREFIX`; do
STACK=`echo $filename | sed s/.yaml//`
aws cloudformation package --template-file $PREFIX/$filename \
--output-template-file /tmp/deployment-output.yaml --s3-bucket $BUCKETNAME
aws cloudformation deploy --template-file /tmp/deployment-output.yaml \
--stack-name $STACK --capabilities CAPABILITY_NAMED_IAM
done
.. note::
Now take a break and wait for these resourced to be created. You may observe the changes
in the CloudFormation web-console (Services -> CloudFormation).
.. warning:: DO NOT continue until all stacks reach the CREATE_COMPLETE status.
If you later make any changes in these files (after the initial deployment), use the
following script and it will update CloudFormation stacks. No harm to run it extra time.
CloudFormation is smart enough not to take any action if there are no changes in templates.
.. hidden-code-block:: bash
:label: Show script
# Get your AccountId from EC2 metadata. Assuming you run this on EC2.
ACCOUNT=`curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info/ | \
grep AccountId | awk -F "\"" '{print $4}'`
# Set your bucket name
BUCKETNAME=sosw-s3-$ACCOUNT
PREFIX=/var/app/sosw/examples/yaml/initial
# Package and Deploy CloudFormation stacks
for filename in `ls $PREFIX`; do
stack=`echo $filename | sed s/.yaml//`
aws cloudformation package --template-file $PREFIX/$filename \
--output-template-file /tmp/deployment-output.yaml --s3-bucket $BUCKETNAME
aws cloudformation deploy --template-file /tmp/deployment-output.yaml \
--stack-name $stack --capabilities CAPABILITY_NAMED_IAM
done
Provision Lambda Functions for Essentials
-----------------------------------------
In this tutorial we were first going to use AWS SAM for provisioning Lambdas,
but eventually gave it up. Too many black magic is required and you eventually loose
control over the Lambda. The example of deploying Essentials uses raw bash/python scripts,
AWS CLI and CloudFormation templates. If you want to contribute providing examples
with SAM - welcome. Some sandbox can be found in `examples/sam/` in the repository.
.. code-block:: bash
# Get your AccountId from EC2 metadata. Assuming you run this on EC2.
ACCOUNT=`curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info/ | \
grep AccountId | awk -F "\"" '{print $4}'`
# Set your bucket name
BUCKETNAME=sosw-s3-$ACCOUNT
for name in `ls /var/app/sosw/examples/essentials`; do
echo "Deploying $name"
FUNCTION=$name
FUNCTIONDASHED=`echo $name | sed s/_/-/g`
cd /var/app/sosw/examples/essentials/$FUNCTION
# Install sosw package locally.
pip3 install -r requirements.txt --no-dependencies --target .
# Make a source package.
zip -qr /tmp/$FUNCTION.zip *
# Upload the file to S3, so that AWS Lambda will be able to easily take it from there.
aws s3 cp /tmp/$FUNCTION.zip s3://$BUCKETNAME/sosw/packages/
# Package and Deploy CloudFormation stack for the Function.
# It will create the Function and a custom IAM role for it with permissions
# to access required DynamoDB tables.
aws cloudformation package --template-file $FUNCTIONDASHED.yaml \
--output-template-file /tmp/deployment-output.yaml --s3-bucket $BUCKETNAME
aws cloudformation deploy --template-file /tmp/deployment-output.yaml \
--stack-name $FUNCTIONDASHED --capabilities CAPABILITY_NAMED_IAM
done
If you change anything in the code or simply want to redeploy the code use the following:
.. hidden-code-block:: bash
:label: Show script
# Get your AccountId from EC2 metadata. Assuming you run this on EC2.
ACCOUNT=`curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info/ | \
grep AccountId | awk -F "\"" '{print $4}'`
# Set your bucket name
BUCKETNAME=sosw-s3-$ACCOUNT
for name in `ls /var/app/sosw/examples/essentials`; do
echo "Deploying $name"
FUNCTIONDASHED=`echo $name | sed s/_/-/g`
cd /var/app/sosw/examples/essentials/$name
zip -qr /tmp/$name.zip *
aws lambda update-function-code --function-name $name --s3-bucket $BUCKETNAME \
--s3-key sosw/packages/$name.zip --publish
# Package and Deploy (if there are changes) CloudFormation stack for the Function.
aws cloudformation package --template-file $FUNCTIONDASHED.yaml \
--output-template-file /tmp/deployment-output.yaml --s3-bucket $BUCKETNAME
aws cloudformation deploy --template-file /tmp/deployment-output.yaml \
--stack-name $FUNCTIONDASHED --capabilities CAPABILITY_NAMED_IAM
done
Upload Essentials Configurations
--------------------------------
sosw-managed Lambdas (and Essentials themselves) will automatically try to read their
configuration from the DynamoDB table ``config``. Each Lambda looks for the document with
a range_key ``config_name = 'LAMBDA_NAME_config'`` (e.g. ``'sosw_orchestrator_config'``).
The ``config_value`` should contain a JSON that will be recursively merged to the
``DEFAULT_CONFIG`` of each Lambda.
We have provided some very basic examples of configuring Essentials.
The config files have some values that are dependant on your AWS Account ID,
so we shall substitute it and then upload these configs to DynamoDB.
It is much easier to do this in Python, so we shall call a python script for that. The
script uses some `sosw` features for working with DynamoDB, so we shall have to install sosw.
.. code-block:: bash
cd /var/app/sosw
pipenv run pip install sosw
cd /var/app/sosw/examples/
pipenv run python3 config_updater.py
### Or alternatively use old one:
# cd /var/app/sosw/examples/essentials/.config
# python3 config_uploader.py
# cd /var/app/sosw
Please take your time to read more about :ref:`Config Sourse` and find
advanced examples in the guidelines of :ref:`Orchestrator`, :ref:`Scavenger`
and :ref:`Scheduler`.
Create Scheduled Rules
----------------------
The usual implementation expects the ``Orchestrator`` and ``Scavenger`` to run every minute,
while ``Scheduler`` and ``WorkerAssistant`` are executed per request. ``Scheduler`` may have
any number of cronned Business Tasks with any desired periodicity of course.
The following script will create an AWS CloudWatch Events Scheduled Rule that will invoke
the ``Orchestrator`` and ``Scavenger`` every minute.
.. note::
Make sure not to leave this rule enabled after you finish your tutorial, because after
passing the free tier of AWS for Lambda functions it might cause unexpected charges.
.. code-block:: bash
# Set parameters:
BUCKETNAME=sosw-s3-$ACCOUNT
PREFIX=/var/app/sosw/examples/yaml
FILENAME=sosw-dev-scheduled-rules.yaml
STACK=sosw-dev-scheduled-rules
aws cloudformation package --template-file $PREFIX/$FILENAME \
--output-template-file /tmp/deployment-output.yaml --s3-bucket $BUCKETNAME
aws cloudformation deploy --template-file /tmp/deployment-output.yaml \
--stack-name $STACK --capabilities CAPABILITY_NAMED_IAM
.. hidden-code-block:: bash
:label: Manual creation of rules
############
# WARNING! #
############
# This is not recommended to run!
# Use CloudFormation.
ACCOUNT=`curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info/ | \
grep AccountId | awk -F "\"" '{print $4}'`
aws events put-rule --schedule-expression 'rate(1 minute)' --name SoswEssentials
aws events put-targets --rule SoswEssentials \
--targets \
"Id"="1","Arn"="arn:aws:lambda:us-west-2:$ACCOUNT:function:sosw_orchestrator" \
"Id"="2","Arn"="arn:aws:lambda:us-west-2:$ACCOUNT:function:sosw_scavenger"