Last night I heard Axel Fontaine (author of Flyway and CEO of BoxFuse) talk to a group of us in Belfast about Cloud Infrastructure, and ask if our software architectures are ready for it. (Thank you to Axel for coming out to see us if you see this post!)
I think his talk made a statement and asked a question – designing an architecture for the cloud is not the same as designing for an on-premise solution – and if you want to do this right, do you know what you have to start doing differently?
I don’t want to try to repeat all of his insights here – I’d encourage you to go and listen to him if he’s coming to your area. But I found it interesting and thought provoking, and I’ll mention some of the things I took away from the talk.
Design your infrastructure to be optimised for cost
The old way of doing things is to buy a server, and scale up/out as your demand increases. So if you have a spike in usage once a month and you invest to cope with this, then you’ll have an estate of servers which are not being used economically for most of the month. Cloud services like AWS or Azure give you a control panel where you can scale based on CPU usage, queue length, or regular spikes.
There’s a few challenges with spinning up machines on demand:
- Service discovery – an elastic load balancer with a stable entry point is a nice way to handle this.
- Logging – if you’re outputting your logs to text files, then theses logs are going to be scattered, and therefore less useful. Instead send your logs in real time to a logging servers, like Kibana or Seq. (Obviously there’s always a need to make sure you’re not logging sensitive data).
Invest in a good lock
You could make it just as simple as lifting your on premise server, virtualise it and put it in “The Cloud” – that’s possible of course…but not hugely efficient. And there are pretty good reasons to not do it that way – maybe you have a nice big firewall around your hosting provider’s estate, but what’s going on inside there?
- Do you have a nosy administrator who’s able to access your data? Do you really trust your cloud provider with that data?
- Or is your data being replicated to a place you don’t expect? (Which could be bad if you’re legally bound to keep it on European or US shores).
Consider the three states of data when you’re designing your solution:
Data at rest:
You might need to secure data at rest by encrypting your database – even encrypting personally identifiable data at a column level like names, or dates of birth. You could use your app to manage your encryption keys – but it might be better to use a key management server, or even a Trusted Platform Module in hardware.
Data in use:
This one’s more tricky – how do you actually use data which is always encrypted? Most of us know how to deal with encrypted passwords, but what about when it’s a name, or a date of birth? Well, one way you can query is by non-encrypted data (e.g. search by a non-semantic Id field), but also remember that some ORMs will allow you to encrypt and decrypt data in motion (e.g. http://stackoverflow.com/questions/22870515/storing-column-data-securely-with-ef6-and-identity-provider).
Data in motion
Move artefacts between environments, and make your servers disposable
This is the old “treat your servers as cattle, not pets” rule – which translates to abandoning the old idea of CRUD for servers. Instead, just use CRD – create, read and delete them, and don’t update. Instead of provisioning machines during your first deployment, and applying incremental patch updates, deploy fully baked virtualised containers, with your configuration baked in too. You can use an algorithm to determine what config should be used (e.g. based on your machine names which are different in each environment). This way your full container is tested the whole way from development to production, leading to fewer surprises when you deploy to production.
(Microsoft have addressed some of these configuration ideas in MVC6).
Deploying to the cloud presents a lot of opportunities like cost saving and improved performance, and deploying containers rather than updating libraries allows you to test your code on the environment it’ll actually be deployed on. But remember to consider security from the outset – how far you go obviously depends on what your needs are, but it’s easier to bake the right level in from the start than it is to try to add it in later.