The Mixology Playbook: Kubernetes And Serverless
Technology is constantly transitioning, and in this state of continuous ‘in-between’, hybrid is king.
From manual to automated, physical to virtual, on-prem to the cloud, and now monolith to microservices and serverless.
Serverless today is a fresh and blooming ecosystem, yet when it comes to making the transition to serverless (or microservices) the future promises many aspects of growth and progress, but also a substantial amount of uncertainty. Will everything become pure serverless with zero orchestration, in just a few years time? Will we see a combination of serverless with microservices, and even with the classic monolithic apps? When contemplating these questions – One thing is certain: hybrid systems are a key aspect of technology and they are here to stay. Which is why we better pay them some attention.
A look at the players
Change is imminent. There’s tension in the air, and from the cutting-edge perspective, just like in the classic western, we have the good, the bad, and the ugly.
- The ‘good’ is pure serverless: no complex orchestration, no servers, no complicated maintenance, etc. Serverless gives you the ability to run clean code and focus on achieving goals with your software.
- The ‘ugly’ is Kubernetes and microservices: messy and full of orchestration. There just seem to be too many things you must write, too many servers and containers you must maintain. However, there are quite a few tricks up its sleeve, and it has quite a few advantages that can give serverless a good run for its money.
- The ‘bad’, from this point of view, is the monolithic app. It’s been with us for years. Right from the start, and it’s not going anywhere. And with its own bag of heavy-duty tricks, it plans to stick with us to the very end.
Each of these players come with its advantages and disadvantages, and each of them currently has a position on the field.
Change brings challenges
Considering a move to new technology, like serverless or microservices, may create strong tensions within a company. The resistance to the new may express itself on several levels:
- Systems: the existing applications, the current orchestration, and the existing services.
- People: devs may resist the move since they are used to working with specific apps and services on a single server and on a certain scale. Their old projects have their own disciplines. Plus, resource allocation may also generate tensions.
- Cultures: together, systems and people create the culture which becomes fundamental to the company’s activities. It includes, for example, specific methods of managing and maintaining the code, the deployment process, and code review. All these are also subject to friction and change when moving to new technology.
It’s very tempting to fall into the utopian vision of a pure world. To think that it’s possible, for instance, to only run your project in serverless or only in microservices. This mindset might work for the short term, but it ignores the existing reality and its complexities. The tensions and frictions mentioned earlier will meet you in the next round and quickly pile up into technical and cultural debt. “Suddenly,” you’ll find yourself juggling both the maintenance of the old systems and the integration of the new elements that are still being baked in.
Starting a new project: things to consider
There are many parameters that can affect the long-term success of your new project in this hybrid world. The following is a list of common key examples:
Language: This is one of the first things we need to choose when starting a new project. Will it be Go or Python? Would we rather use the language we’ve previously used, or should we choose one that seems to be the best match for the environment? The latter option is often considered to be best practice. In reality, however, it leaves the rest of the environment behind and ignores all other elements and frameworks, the handling of web requests, connecting the file system, etc.
Framework: The problem with existing solutions is that they are different for each environment. Each framework is often completely new and we will need to figure out how to adopt and implement it in practice. For example, if you worked with Flask or Django in Python in your monolith or microservice, moving to serverless you’ll have to go with something like Zappa on top of Flask, or Chalice.
Building and deploying: In serverless, we don’t need to pass through the complexities of the CI/CD pipeline since we can simply upload the Zip to Lambda. However, we should consider where this leaves us in relation to the existing code deployment flows- as we run a risk of losing our controls and policies for deployments.
Design patterns: With monoliths, developers are often used to working with monolith design patterns, for example, “Shared Process Memory”. It’s very convenient since all the work is in the same process, accessing the same memory. This changes with the move to serverless: everything is on the network and you have to use solutions like SQS or Kafka to synchronize your code components.
Monitoring: While there are classic monitoring products, such as Datadog, serverless offers up a whole new world with tools like Epsagon, IOpipe, Honeycomb, etc. This plethora of new solutions brings the challenge of picking the right offering for your needs, and more importantly, balancing the offering with the existing tools.
Debugging: the classic monolith allows you to attach a debugger and simply pause and observe. This isn’t an option in serverless since there is no server to run and nothing to attach to. You can try SAM Local, and ironically enough, set up a server for debugging serverless.
What can developers do?
So, how can we overcome these challenges? How can we, as devs, DevOps, and SREs create the best configurations for hybrid systems and build the most efficient solutions to face these inherent challenges?
Embrace the hybrid future. Accept the fact that sometime in the not-so-distant future, your project will be a part of a hybrid environment and consider how you can develop it now, so when the time comes, it integrates and grows better.
Explore and innovate. Yes, there’s a variety of options and tools out there, but we still don’t have all the answers. Organizations and devs need to allocate time to experiment and gradually outline the best practices. The more we deal with these questions, the sooner we’ll find answers as a community. By allocating a small amount of time now, you’ll be saving your future self bucket loads of time and pain.
Use these 3 key concepts to create and measure up good hybrid solutions:
- Connect: In a good hybrid solution, the new connects to the old, with interfaces and shared data.
- Maintain: In a good hybrid solution the new is easily maintained with the old; allowing developers to understand it with ease as it connects to the whole system.
- Consolidate: In a good hybrid solution the new consolidates with the old. It aspires to become a single system and not some detached side project; which people fail to be aware of and adopt.
What can the industry do?
As part of an industry, we need to consider standardization and how we provide developers with a unified way to work with different elements. New vendor solutions should uphold 3 key parameters:
- Augment: Solutions should aim to improve and add value to existing elements. As opposed to trying to replace them altogether, or trying to enter into specific sections within existing processes. Consolidation is becoming a frequent occurrence, and as vendors, we need to think about promoting the process. We should aim at providing value to the hybrid world and accelerate its evolution.
- Interconnect: The solution needs to be able to connect to other solutions while sharing information and usage patterns. The APIs we build should have a clear and consistent interface. They should also work in a similar way across platforms, thus saving devs the trouble of having to learn everything from scratch. We should also consider investing in data pipelines and allow for the effortless transfer of data between solutions.
- Interchange: The ability to be interchangeable is the hardest point for vendors to accept. An inability to replace a vendor produces a negative dissonance in the long term. On the other hand, enabling different tools to connect to your solution is best for the ecosystem as a whole.
Hybrid solutions done right: the takeaway
Create symbiosis: Instead of building a closed system, consider forming a symbiosis between the various parts of the solution. If you’re writing a function in serverless, ask yourself: Will the existing microservices benefit from it when you’re done? Would it be easier for them to work?
Leave room to mutate and evolve: When things only work separately and cannot connect to other elements, they eventually get stuck and stop generating value. But if you allow room for flexibility, a place to insert or change the code and connect to other platforms, everybody wins.
Provide transparency and observability: A solution with code that cannot be observed and understood is bound to eventually fail and lose its users and maintainers. Aspiring for your solution to be accessible and understandable by others is key to wider adoption and allowing it to stand the test of time.
Support Interchangeability: As mentioned earlier, a good solution should be interchangeable with others.
Make it feel seamless: Developers who work with the solution should feel it integrates seamlessly with other solutions used by their company. No special effort should be made on their part to learn how to use your solution.
These are values we set into Rookout’s foundation from day one. Aspiring to be as complementary as we can to our ecosystem, our goal is to connect to as many platforms and solutions as possible. We want to create a better world where developers can work with the various tools in a smooth and seamless way. And as you can see in the demo below, with Rookout, it doesn’t matter which cloud you are using or if you’re using Rookout on a monolith, microservice, or serverless function. It all works the same: by simply clicking a button.