Containerization, microservices and distributed architectures in practice
Now that we have delivered a project applying techniques we developed as part of our internal R&D project, we are going to share our key takeaways on using containerization, microservices, and distributed architectures in the development of robotics software. Specifically, we are going to discuss the utilization of ROS2 (framework used for robotics software development) in combination with Docker (platform used for containerization) as we discuss why containerization, microservices, and distributed architectures are needed and what the advantages are.
When working with ROS2 projects, every so often it feels like a puzzle. A fully functioning robotics software system involves simultaneously running components doing their tasks while communicating with each other. This is a precise process, where there is no room for miscommunication and therefore, operational systems require many different parts to be aligned in a specific way in order to work. A simple system is simple to implement and maintain. Real world systems are often not simple though, and with complexity we approach a point when things get challenging. This is when containerized architectures will start to shine.
We have used Docker as our containerization platform. Docker containers simplify the development, deployment, and management of software by encapsulating the application and its dependencies. In the context of ROS2, Docker can significantly simplify handling complex systems. A fully functioning robotics software system can be defined and stored with the help of containerization practices. Wrapped with good documentation, it will be ready for utilization “out of the box”.
Applications for Docker within the context of ROS2 don’t stop here; we can apply it on the system architecture level too. Instead of stuffing the whole ROS2 system into a single container, we can implement a distributed system architecture with microservices to divide a complex system into more manageable components. This allows us to achieve a more flexible and maintainable system where each container is responsible for a certain dedicated task. As an example, container A could handle sensors that observe the surroundings and container B could be responsible for the movement that allows navigation in this environment. Now the same system works as previously, yet in a more manageable way.
ROS2 ecosystem
Robotics software systems are complex and they involve many different components working in harmony. With the development capabilities offered by ROS2, the process becomes more manageable and efficient:
Package architecture: ROS2 provides a framework for building the system in packages, where each package encapsulates a specific part of a system’s functionality. This encourages a modular system design.
I nterfaces: The packages, or nodes, communicate with each other via interfaces and communication methods (topics, services, actions). ROS2 provides predefined interfaces for commonly used robotics functionality and allows developers to easily define custom interfaces for more specific use cases. This relieves developers from having to worry about the implementation details of the underlying DDS middleware used for communication and focus on the application logic instead.
Dependency management: ROS2 allows declaring a package’s dependencies in the package.xml file. As a result the correct dependencies can be automatically installed with the rosdep tool. This ensures that correct versions of dependencies are installed in a managed way, without the need for custom install scripts.
While ROS2 offers solutions for various aspects of robotics software development, fully integrating the system remains challenging. As an example, each ROS2 distribution requires the installation of a specific operating system as a prerequisite. Further steps include installing dependencies as well as configuring and building the packages. If the system is distributed to multiple pieces of hardware, the steps need to be repeated for each device, and if you want to try a different ROS2 version, you need to start all over again. This can become very frustrating when dealing with larger systems.
Luckily, containers can ease this path by encapsulating the process, enhancing development capabilities, and simplifying the integration of the system. Given that ROS2 packages and nodes establish a foundation for modular systems, and with Docker's prominence in distributed systems, the integration of ROS2 with Docker appears to be the ideal choice for developing such robotic systems.
The figure above illustrates an example of a containerized system. The system showcases a robot equipped with a camera unit, in combination with a unit processing data from the camera. If the system is implemented without containerization, all installations, dependencies, and configurations would be done manually on the host OS. With containerization, there is no need touch the host OS and both setup as well as deployment of the system can be automated with Docker.
A containerized approach gives flexibility in the deployment architecture of the system. For instance, if the image processing in the above example is a computationally intensive task, we can simply deploy the image processing container on another host, relieving the robot’s limited hardware resources. Communication still flows through ROS2’s DDS transport and the system functionality stays the same. This way, we can utilize the distributed microservice architecture to optimize system’s performance, and containers make this process much more practical.
In a system utilizing a distributed microservice architecture, each container can be modified individually and deployed quickly, while the runtime environment is not affected. This is a significant improvement compared to traditional methods. The development and prototyping process becomes much more flexible when the system is distributed and containerized, and it also integrates well with CI/CD pipelines, as we discussed in our previous blog post.
Conclusion
The integration of Docker with ROS2 introduces a practical solution to manage a scalable robotics system. When we applied the methods discussed in this blog post, we were able to effectively manage the complexities of expanding robotic systems, ensuring streamlined development and deployment. Docker's ability to modularize and isolate system components did not only enhance the efficiency of robotics software deployment but it also improved the development workflow. This harmonious blend of ROS2's modular architecture and Docker's containerization technology has made it possible for us to develop more robust, scalable, and manageable robotics systems while also emphasizing how our R&D efforts create tangible value, not only advancing our own expertise but also delivering practical, impactful solutions for our customers.
FAQ
During our consultancy work within this domain, we have encountered certain reocurring questions. We see that these questions represent common concerns among professionals working in the field. As our readers might share these same concerns, we made a list of these frequently asked questions to be addressed:
Is it hard to learn Docker and apply containerization?
Docker has a moderate, yet straightforward learning process, and with a variety of tutorials and community support, it is very accessible to those with technical a background. Understanding the core concepts of Dockerfiles, images, and containers is the key to effective use. Knowing your way around Linux helps too. In a nutshell, a Dockerfile outlines the blueprint for an image, which encapsulates the program and its dependencies, and this image can then be run as a container, providing an operational version of the program within its own isolated environment.
How does containerization affect the performance and resource use of the system?
Containerization introduces a small overhead compared to running applications directly on the host OS, but is more than often outweighed by the benefits of better resource management and isolation. Containers ensure that applications use only the resources they need, avoiding waste.
What about the security aspect of containers?
Containers, when implemented correctly, offer a secure environment. It is important to use trusted images and control what access containers have to the host OS. Regular security and dependency scanning as well as updates can also be done to mitigate risks. If your application needs to communicate directly with hardware, you should be aware of the risks of using privileged mode.
How about graphical applications in containers?
You can run graphical applications inside containers too, by mounting the host’s X-server into the container or with VNC. Docker can even take advantage of GPU acceleration with the --gpus=all option. However, performance might not be as smooth as in native applications.