Chapter 5 — Cloud and container security: design alternatives
Lesson map
Lesson 05 published. Map, example, EX021.
flowchart TD
N0["Learning outcomes"]
N1["5.1 Alternatives"]
N2["5.2 Central versus local"]
N3["5.3 Default level"]
N4["5.4 Failure modes"]
N5["5.5 Exceptions"]
N6["5.6 Choice"]
N7["5.7 Rollout"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX021"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["5.1 Alternatives"]
N2["5.2 Central versus local"]
N3["5.3 Default level"]
N4["5.4 Failure modes"]
N5["5.5 Exceptions"]
N6["5.6 Choice"]
N7["5.7 Rollout"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX021"]
[Learning outcomes]
|
v
[5.1 Alternatives]
|
v
[5.2 Central versus local]
|
v
[5.3 Default level]
|
v
[5.4 Failure modes]
|
v
[5.5 Exceptions]
|
v
[5.6 Choice]
|
v
[5.7 Rollout]
|
v
[Worked example] --> [Exercise EX021]
Learning outcomes
You will (1) compare designs for enforcing workload security across clusters; (2) evaluate central versus per-cluster policy; (3) consider failure modes; (4) choose a design.
5.1 Alternatives
Design 1: Pod Security admission labels set by each team. Design 2: labels set centrally by GitOps, with a cluster-wide default of Restricted for unlabelled namespaces. Design 3: Design 2 plus a policy engine for extra rules, its policies distributed from one repository. Each design answers the audit finding in a different way. Design 1 keeps the current approach, which relies on teams remembering labels. Design 2 makes the safe setting the default, so a forgotten label leaves a namespace protected rather than exposed. Design 3 adds the policy engine from option B, so registry and signature rules are enforced from the same central repository.
5.2 Central versus local
Local control lets teams move quickly but recreates the original gap: labels forgotten. Central defaults make the safe choice automatic. The audit finding came from exactly this: labels set locally were lost during an upgrade. With central defaults, a new or forgotten namespace starts at Restricted, and teams ask for exceptions when they need less. The quotes team at first preferred local control, but agreed once Inês showed exceptions could be granted within a day. Inês records the quotes team's objection and her answer in the design document.
5.3 Default level
Kubernetes allows configuring cluster-wide defaults for the admission controller. Setting the default to Restricted means a new namespace is protected unless an exception is approved. With a Restricted default, the upgrade gap that caused the audit finding would have left namespaces protected rather than unenforced. Teams that need a weaker profile, such as monitoring, request an exception, which is recorded with its reason. The default is set in the cluster configuration managed by GitOps, so it cannot be changed without review.
5.4 Failure modes
If the policy engine fails, Design 3 can fail closed for production namespaces; built-in admission runs inside the API server and has no separate availability risk. Failing closed means that if the policy engine is unavailable, production deployments wait rather than running unchecked. This protects customer data but could delay urgent fixes, so the incident runbook includes a break-glass path. Built-in admission keeps working even if the engine fails, so Pod Security profiles still apply. Inês documents both behaviours, so engineers know what to expect during an outage.
5.5 Exceptions
Monitoring and node agents need Privileged; they get their own namespace with an exception record. Node agents need access to the host to collect data, which Restricted and Baseline do not allow. Placing them in their own namespace keeps the Privileged label away from workloads that do not need it. The exception record names the agents, the reason and the owner, and it is reviewed with the other exceptions. Any new agent must go into the same namespace or justify a separate exception.
5.6 Choice
Design 3, with built-in admission as the foundation and the engine for registry and signature rules. Design 3 combines the protection of central defaults with the extra checks option B was chosen for. Built-in admission handles Pod Security profiles without a separate service to fail, while the policy engine adds rules the profiles cannot express. Inês records the choice with the alternatives and the reasons in the design document, which the platform team and quotes team both review. The platform team confirms it can operate the engine within the funded engineer's year.
5.7 Rollout
Audit and warn modes first, then enforce. Audit mode logs workloads that would break the policy without stopping them, and warn mode tells the deploying engineer. These steps let teams find and fix problems before enforcement begins. Each cluster moves to enforce only when its audit logs show no unexplained violations. Inês tracks each cluster's mode in the plan, so the working group can see progress and spot clusters that stall. Inês sets a minimum of two weeks in warn mode for each cluster, so teams see warnings on their normal deployment cycle before anything is blocked.
Testing the design on paper
Before building, Inês walks through three scenarios against Design 3: a new team creates a namespace, a cluster is upgraded, and the policy engine is unavailable. In each case she writes what happens and who notices. The upgrade scenario is the most important, since it reproduces the original gap; under Design 3 the central default and GitOps labels survive the upgrade.
Design note
The final design note records the rejected alternatives and why, so that a future team revisiting the choice understands the trade-offs instead of reopening settled questions.
Worked example
The quotes team asks to keep Design 1 for flexibility. Inês shows that under Design 3 they can still request exceptions within a day, while the default prevents the next upgrade gap. They agree.
Synthetic case. Designs are synthetic.
Errors and limits
Central control can become a bottleneck; staff the exception process.
Exercises
- EX021 — Three designs. Describe the three designs. Rubric: 3 = team labels; central GitOps with default; plus engine; 2 = two; 1 = one; 0 = none.
- EX022 — Default benefit. Why set a cluster-wide Restricted default? Rubric: 3 = new namespaces protected automatically; 2 = partial; 1 = vague; 0 = none.
- EX023 — Built-in availability. Why does built-in admission add no separate availability risk? Rubric: 3 = runs inside API server; 2 = partial; 1 = vague; 0 = none.
- EX024 — Chosen design. Which design was chosen? Rubric: 3 = Design 3; 2 = partial; 1 = vague; 0 = none.
- EX025 — Quotes objection. How was the quotes team persuaded? Rubric: 3 = exceptions within a day; prevents gap; 2 = partial; 1 = vague; 0 = none.
Synthesis
Make the safe choice the default and keep exceptions workable.
Continue studying — chapter 05 of 12
← Chapter 04 (draft) · Course chapter index · Chapter 06 (draft) →