In this 3-part blog series I’ll be discussing
- Tigera Secure design decisions
- Federating policy across fault domains
- Creating a unified policy domain between legacy and cloud-native environments
This first blog in the series will provide an insider’s view into Tigera Secure and our design decisions in implementing the technology.
Enforcing policy that governs network security and connectivity for legacy and cloud-native apps is core to what we do here at Tigera – so much so that we sometimes take for granted the design decisions that created a framework that protects millions of workloads daily. In this series of posts, I am going to pull back the curtain and share with you a deeper look into the core design decisions that went into Tigera Secure that have enabled network security and connectivity to be applied reliably in so many contexts.
Before diving in, I wanted to share a quick insight.
I have always found it intriguing how others perceive the world around them and learn new things – having four young children at home, and I am granted a front row seat to this discovery daily. Likewise, coming to a new programming language or paradigm, we are forced to quickly learn what to focus on immediately and what to save for later, after we have absorbed and learned by experience. I have also taught several Kubernetes and related courses over the last two years which have given me the opportunity to learn from students about their initial perception of this new ecosystem.
Many of the students come from a traditional software development environment where delivering software into production is a very tedious and hands-on process. When asking the students to share what they enjoy most about this new distributed computing paradigm compared to what they are forced to do in their current systems, I often hear how they like describing the desired outcome rather than managing the operations and logic that it would take to achieve a result. The reality is distributed computing is hard and deploying software that is assembled with microservices in the traditional world is non-scalable. However, Kubernetes has lowered the barrier of entry into this new way of deploying and managing software by hiding its complexity behind a declarative API. A declarative configuration enables less work for the practitioner and yet yields a more reliable result.
Another feature students rave about is labels. Labels provide flexibility for selecting and targeting platform primitives when applying behavior to them or when using them for derivative configurations. This simple primitive makes it easy to target and describe the configuration of multiple concerns within a system.
These are just two of the traits that ease the adoption of network policy in Tigera Secure. In this post, I will discuss why we took a declarative approach to policies.
As beginning computer programmers, we learn the difference between imperative and declarative programming. Imperative programming is a style of programming where a set of statements sequentially change the state of something until a goal is reached. In this style, we tell the computer how to accomplish a task. Declarative programming, on the other hand, is a style of programming where the elements of a computation or the goal of what must be accomplished are described. Instead of describing how to accomplish a task, we describe what we would like accomplished.
Large cloud-native and distributed computing platforms have a lot of moving parts, which consequently means lots of changing states. An imperative approach to any configuration, including policy, would require the end user to understand the ins and outs of the state machines that govern these systems. That level of knowledge is impractical and would eliminate any gains from abstracting away policy implementation. This is the primary reason configuration is declarative within Tigera Secure. The onus is placed on Tigera Secure userbase to understand the interaction between the policy engine and the other moving parts of the distributed system.
Another requirement for a policy engine is well-understood behavior. Imperative statements are a point in time action and therefore, they are dependent on the current state and time at which they are executed. Looking at an imperative statement without all of the environment/state/time context makes it impossible to understand what it does. Since a declarative approach describes outcomes and not methods, this can be easily digested by a reviewer with little working knowledge of the underlying moving parts.
Finally, as organizations continue to decompose their monoliths into microservices, it becomes increasingly important to also decompose policies into micropolicies (see my recent blog on micropolicies for more information). A declarative policy can be more easily traversed and composed because the intermixing and order of the rules is handled by the policy engine, not imperative instructions from the end user.
So, by keeping policies declarative, we keep the onus on the Tigera team for getting state management right, ease the learning curve and enable both policy creators and auditors to quickly comprehend the intent of a policy, and enable composition and precedence of policy without worrying about implementation side effects.
In the next blog, I will peel the onion further on our design decisions. In the meantime, I invite you to learn more about Tigera’s Secure is here.