Funny insects/keda exercise refactor#878
Conversation
- checkout-service: HTTP server with POST /checkout -> Redis RPUSH - order-processor: BLPOP consumer with configurable delay + CPU loop - Multi-stage Dockerfiles using golang:1.26-alpine -> alpine:3.23 with SHA pinning - Both images build successfully (checkout-service:local, order-processor:local) Related to T1.0 in Spec 01
- Kustomize base: namespace, redis-secret, redis, checkout-service, order-processor, keda-trigger-auth - Local overlay patches imagePullPolicy: Never for k3d compatibility - Redis upgraded to 8.6-alpine with SHA pinning - HPA omitted from base — left for students to write in Exercise 3 Related to T2.0 in Spec 01
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a new chapter (9.6) KEDA exercise with docs/specs, two Go example services and Dockerfiles, Kustomize manifests and overlay, Taskfile automation, k6 load script, and renumbers subsequent chapter files and sidebar/README entries. ChangesKEDA Exercise and Chapter Reorganization
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 15
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/9-kubernetes-container-orchestration/9.9-controllers.md (1)
43-43:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate chapter reference from 9.6 to 9.7.
After the chapter renumbering, the Webhooks chapter moved from 9.6 to 9.7, but this cross-reference was not updated.
🔗 Proposed fix
-If you've been working through the bootcamp, you've already been exposed to both CRDs and custom controllers. In the first exercise of chapter 9.6, Webhooks, you were tasked with setting up a basic admission webhook, which required installing cert-manager. `cert-manager` is a powerful tool that combines a set of custom resource definitions (CRDs) with a custom controller to automate the issuance, renewal, and management of TLS certificates that webhooks require to securely interact with the Kubernetes API server. By leveraging CRDs like Certificate, Issuer, and ClusterIssuer, cert-manager enables you to declare and manage certificates directly within Kubernetes, removing the need for manual intervention in obtaining and maintaining certificates. This automation is not only convenient but essential in high-scale environments where TLS certificates need frequent renewal to ensure secure connections across applications and services. +If you've been working through the bootcamp, you've already been exposed to both CRDs and custom controllers. In the first exercise of chapter 9.7, Webhooks, you were tasked with setting up a basic admission webhook, which required installing cert-manager. `cert-manager` is a powerful tool that combines a set of custom resource definitions (CRDs) with a custom controller to automate the issuance, renewal, and management of TLS certificates that webhooks require to securely interact with the Kubernetes API server. By leveraging CRDs like Certificate, Issuer, and ClusterIssuer, cert-manager enables you to declare and manage certificates directly within Kubernetes, removing the need for manual intervention in obtaining and maintaining certificates. This automation is not only convenient but essential in high-scale environments where TLS certificates need frequent renewal to ensure secure connections across applications and services.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/9-kubernetes-container-orchestration/9.9-controllers.md` at line 43, Update the cross-reference string "chapter 9.6, Webhooks" to "chapter 9.7, Webhooks" in the text so the Webhooks chapter number matches the renumbered chapters; search for the literal phrase "chapter 9.6, Webhooks" in the docs (e.g., within the paragraph mentioning cert-manager and webhooks) and replace it with "chapter 9.7, Webhooks".
♻️ Duplicate comments (1)
docs/specs/01-spec-keda-exercise/01-tasks-keda-exercise.md (1)
86-86:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winResolve HPA manifest inclusion decision.
Task 2.6 states
hpa.yamlis "intentionally omitted — left for students to write as part of Exercise 3," but Task 4.6 (line 141) instructs students to "applyk8s/base/hpa.yamlwithkubectl apply -f."If the file is omitted from the repository, students cannot apply it from that path. This is the same inconsistency flagged in
01-spec-keda-exercise.mdline 68.Recommended resolution: Provide
hpa.yamlink8s/base/as a reference implementation (students apply it in Exercise 3), but keep theScaledObjectas student-written (Exercise 5). This maintains the learning objective of writing KEDA resources while reducing friction in the HPA comparison exercise.Also applies to: 141-141
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/specs/01-spec-keda-exercise/01-tasks-keda-exercise.md` at line 86, Task 2.6 claims hpa.yaml is intentionally omitted but later steps ask students to apply k8s/base/hpa.yaml; add a reference HPA manifest so exercises are consistent: create k8s/base/hpa.yaml containing a HorizontalPodAutoscaler named order-processor-hpa in namespace keda-demo targeting the order-processor Deployment with minReplicas: 1, maxReplicas: 10 and a Resource metric cpu targetUtilizationPercentage: 50, while leaving the KEDA ScaledObject for students to author in the later exercise.
🧹 Nitpick comments (1)
examples/ch9/keda/k8s/base/redis-secret.yaml (1)
7-7: ⚡ Quick winDecouple Redis address from hardcoded namespace.
Using
redis.keda-demo.svc.cluster.local:6379couples this secret to a single namespace. Preferredis:6379(same-namespace service DNS) to keep overlays portable.Proposed fix
stringData: - REDIS_ADDR: redis.keda-demo.svc.cluster.local:6379 + REDIS_ADDR: redis:6379🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/ch9/keda/k8s/base/redis-secret.yaml` at line 7, The REDIS_ADDR secret value is hardcoded to a namespace-specific FQDN; update the REDIS_ADDR entry in redis-secret.yaml (the REDIS_ADDR key) to use the same-namespace service DNS (e.g., "redis:6379") so the secret is portable across overlays and not tied to the keda-demo namespace.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.cspell.json:
- Line 102: Replace the misspelled dictionary entry "observabity" with the
correct word "observability" in the cspell word list; locate the literal string
"observabity" in the .cspell.json word array and update it to "observability" so
the spellchecker accepts the correct term going forward.
In `@docs/9-kubernetes-container-orchestration/9.6-keda.md`:
- Line 95: The sentence that currently reads "Before installing KEDA, you must
remove the HPA you created in Exercise 3." is referencing the wrong exercise;
update the text to reference "Exercise 2" instead of "Exercise 3" so it
correctly points to where the HPA was created (locate the paragraph that begins
"Before installing KEDA..." in the KEDA exercise content and replace "Exercise
3" with "Exercise 2").
- Line 91: Replace the Markdown image syntax referencing
"img9/dank-hpa-meme.jpg" with an HTML <img> tag that points to the image placed
in the root img/ folder (e.g., src="img/dank-hpa-meme.jpg") and preserve the alt
text ("dank hpa meme") and centering class (e.g., class="img-center"); move the
file from img9/ into img/ and update the image reference in the document
accordingly.
- Line 65: Replace the Markdown image syntax referencing
"img9/producer-consumer.jpg" with an HTML <img> tag that points to the root img
folder (e.g., src="/img/producer-consumer.jpg"), preserve the class "img-center"
and the alt text "producer consumer image", and remove the old markdown line so
the content uses the HTML <img> element instead of the Markdown image reference.
In `@docs/specs/01-spec-keda-exercise/01-proofs/01-task-02-proofs.md`:
- Line 115: The proof uses image "redis:8.6-alpine@sha256:..." while the spec
and task docs reference "redis:7-alpine"; pick one source of truth and make them
consistent: either update the spec and task documents
("01-spec-keda-exercise.md" and "01-tasks-keda-exercise.md") to reference
"redis:8.6-alpine" (and remove or update SHA pins where appropriate), or change
the proof artifact in "01-task-02-proofs.md" to use "redis:7-alpine" (and if you
keep a SHA, pin the correct digest for v7); ensure all three files use the exact
same image string.
In `@docs/specs/01-spec-keda-exercise/01-spec-keda-exercise.md`:
- Line 68: The spec text contradicts Task 2.6 about whether k8s/base/hpa.yaml is
provided or left for students: reconcile the documents by choosing A or B and
update both files accordingly; if you decide A (provide it) change the sentence
in docs/specs/01-spec-keda-exercise/01-spec-keda-exercise.md to explicitly state
that k8s/base/hpa.yaml is included and ensure Task 2.6 in
01-tasks-keda-exercise.md no longer says it is omitted, or if you decide B
(students write it) change the spec sentence to state that k8s/base/hpa.yaml is
intentionally omitted and ensure Task 2.6 continues to reflect that; update any
references and examples in both files so they consistently reference
k8s/base/hpa.yaml and Task 2.6.
In `@examples/ch9/keda/checkout-service/Dockerfile`:
- Around line 8-11: The runtime Dockerfile currently runs the container as root;
to fix, modify the final stage (the Dockerfile containing COPY --from=builder
/checkout-service /checkout-service, EXPOSE 8080, ENTRYPOINT
["/checkout-service"]) to create or use a non-root user, chown the
/checkout-service binary to that user, and add a USER <nonroot> directive before
the ENTRYPOINT so the process runs unprivileged; ensure the created user has
permission to execute the binary and any required runtime directories.
In `@examples/ch9/keda/checkout-service/main.go`:
- Line 44: Replace the use of context.Background() in the Redis enqueue call so
the operation respects request cancellation/timeouts: create a request-scoped
context with a deadline (e.g., using context.WithTimeout on the handler's ctx),
defer the cancel, and pass that context into rdb.RPush(ctx, "orders:queue",
payload). Update the call site where rdb.RPush is invoked (replace the
context.Background() argument) so stalls or client cancellations will cancel the
Redis operation.
- Around line 69-71: The server is started with http.ListenAndServe(nil) and no
timeouts, which risks slow clients; replace the ListenAndServe call by creating
an http.Server struct (set Addr to ":"+port, Handler to http.DefaultServeMux or
the mux used for checkoutHandler) and configure ReadTimeout, ReadHeaderTimeout,
WriteTimeout and IdleTimeout with sensible values, then call
server.ListenAndServe() (or ListenAndServeTLS if needed); update references
around checkoutHandler and the existing println/log.Fatal to use the new server
variable.
In `@examples/ch9/keda/k8s/base/checkout-service.yaml`:
- Around line 15-31: Add explicit pod and container security contexts for the
checkout-service: under the pod spec add a podSecurityContext with
seccompProfile.type set to "RuntimeDefault"; under the container entry for name:
checkout-service add a securityContext with runAsNonRoot: true,
allowPrivilegeEscalation: false, capabilities.drop: ["ALL"], and
readOnlyRootFilesystem: true (apply to the container named checkout-service in
the existing spec). Ensure the fields are placed alongside the existing
resources/env to harden the workload without changing other settings.
In `@examples/ch9/keda/k8s/base/order-processor.yaml`:
- Around line 15-31: Add explicit pod and container security contexts to harden
the order-processor pod: in the Pod spec add a podSecurityContext (e.g.,
runAsNonRoot: true, runAsUser: 1000, fsGroup: 2000) and inside the container
named "order-processor" add a securityContext that enforces least privilege
(runAsNonRoot: true, runAsUser: 1000 if not inherited, allowPrivilegeEscalation:
false, readOnlyRootFilesystem: true, capabilities: drop: ["ALL"], and
seccompProfile: { type: "RuntimeDefault" }). Update the "order-processor"
container block and the surrounding spec to include these fields so the pod and
container both enforce non-root execution and restricted capabilities.
In `@examples/ch9/keda/k8s/base/redis.yaml`:
- Around line 15-25: Add a pod- and container-level securityContext to the Redis
Pod spec to harden the container: under the Pod spec add securityContext with
seccompProfile.type: RuntimeDefault, and under the container entry for name:
redis add securityContext with allowPrivilegeEscalation: false,
capabilities.drop: ["ALL"], and runAsNonRoot: true; update the existing
container block (container name "redis") rather than creating a new container
and ensure these fields are applied alongside the current image/args/ports
entries.
In `@examples/ch9/keda/order-processor/Dockerfile`:
- Around line 8-10: The final stage of the Dockerfile currently runs as root
(ENTRYPOINT ["/order-processor"]); create and switch to an unprivileged user in
the runtime image and ensure the binary is owned/executable by that user.
Specifically, in the final stage (the stage that copies /order-processor from
the builder and sets ENTRYPOINT) add a non-root user (e.g., create user
"appuser"), chown the /order-processor binary to that user, and add a USER
appuser instruction before ENTRYPOINT so the container runs the binary as a
non-root principal.
In `@examples/ch9/keda/Taskfile.yml`:
- Line 67: The task description string starting with "desc: Run k6 load test
(defaults — CHECKOUT_URL=http://localhost:8080, VUS=50, DURATION=60s)" is
inconsistent with the actual default VUS value (VUS=10) defined elsewhere;
update that desc text to reflect the real default (VUS=10) so the description
matches the default variable, i.e., edit the desc line to show VUS=10 (or
alternatively change the default VUS variable to 50 if you intend that to be the
true default) — look for the "desc: Run k6 load test..." string and the VUS
default declaration to make them consistent.
- Around line 66-73: The load:run target defaults CHECKOUT_URL to
http://localhost:8080 which is unreachable from the host because the stack only
creates in-cluster resources; update the default CHECKOUT_URL in the load:run
Taskfile target to a cluster-accessible address (for example the service DNS
like http://checkout-service.<namespace>.svc.cluster.local:8080) or
document/offer an alternative env var (e.g., CHECKOUT_URL=https://<host>:<port>
with port-forwarding) so load/flash-sale.js can reach the checkout service
without manual port-forwarding.
---
Outside diff comments:
In `@docs/9-kubernetes-container-orchestration/9.9-controllers.md`:
- Line 43: Update the cross-reference string "chapter 9.6, Webhooks" to "chapter
9.7, Webhooks" in the text so the Webhooks chapter number matches the renumbered
chapters; search for the literal phrase "chapter 9.6, Webhooks" in the docs
(e.g., within the paragraph mentioning cert-manager and webhooks) and replace it
with "chapter 9.7, Webhooks".
---
Duplicate comments:
In `@docs/specs/01-spec-keda-exercise/01-tasks-keda-exercise.md`:
- Line 86: Task 2.6 claims hpa.yaml is intentionally omitted but later steps ask
students to apply k8s/base/hpa.yaml; add a reference HPA manifest so exercises
are consistent: create k8s/base/hpa.yaml containing a HorizontalPodAutoscaler
named order-processor-hpa in namespace keda-demo targeting the order-processor
Deployment with minReplicas: 1, maxReplicas: 10 and a Resource metric cpu
targetUtilizationPercentage: 50, while leaving the KEDA ScaledObject for
students to author in the later exercise.
---
Nitpick comments:
In `@examples/ch9/keda/k8s/base/redis-secret.yaml`:
- Line 7: The REDIS_ADDR secret value is hardcoded to a namespace-specific FQDN;
update the REDIS_ADDR entry in redis-secret.yaml (the REDIS_ADDR key) to use the
same-namespace service DNS (e.g., "redis:6379") so the secret is portable across
overlays and not tied to the keda-demo namespace.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1e21a29c-2fa3-4109-8f35-c3b368426967
⛔ Files ignored due to path filters (4)
docs/9-kubernetes-container-orchestration/img9/dank-hpa-meme.jpgis excluded by!**/*.jpgdocs/9-kubernetes-container-orchestration/img9/producer-consumer.jpgis excluded by!**/*.jpgexamples/ch9/keda/checkout-service/go.sumis excluded by!**/*.sumexamples/ch9/keda/order-processor/go.sumis excluded by!**/*.sum
📒 Files selected for processing (36)
.cspell.jsondocs/9-kubernetes-container-orchestration/9.6-keda.mddocs/9-kubernetes-container-orchestration/9.7-webhooks.mddocs/9-kubernetes-container-orchestration/9.7.1-validating-admission-policy.mddocs/9-kubernetes-container-orchestration/9.8-declarative-configuration.mddocs/9-kubernetes-container-orchestration/9.8.1-kustomize.mddocs/9-kubernetes-container-orchestration/9.8.2-helm.mddocs/9-kubernetes-container-orchestration/9.9-controllers.mddocs/README.mddocs/_sidebar.mddocs/specs/01-spec-keda-exercise/01-proofs/01-task-01-proofs.mddocs/specs/01-spec-keda-exercise/01-proofs/01-task-02-proofs.mddocs/specs/01-spec-keda-exercise/01-proofs/01-task-03-proofs.mddocs/specs/01-spec-keda-exercise/01-questions-1-keda-exercise.mddocs/specs/01-spec-keda-exercise/01-spec-keda-exercise.mddocs/specs/01-spec-keda-exercise/01-tasks-keda-exercise.mdexamples/ch9/keda/Taskfile.ymlexamples/ch9/keda/checkout-service/Dockerfileexamples/ch9/keda/checkout-service/go.modexamples/ch9/keda/checkout-service/main.goexamples/ch9/keda/k8s/base/checkout-service.yamlexamples/ch9/keda/k8s/base/kustomization.yamlexamples/ch9/keda/k8s/base/namespace.yamlexamples/ch9/keda/k8s/base/order-processor.yamlexamples/ch9/keda/k8s/base/redis-secret.yamlexamples/ch9/keda/k8s/base/redis.yamlexamples/ch9/keda/k8s/overlays/local/image-pull-policy-patch.yamlexamples/ch9/keda/k8s/overlays/local/kustomization.yamlexamples/ch9/keda/load/flash-sale.jsexamples/ch9/keda/order-processor/Dockerfileexamples/ch9/keda/order-processor/go.modexamples/ch9/keda/order-processor/main.goexamples/ch9/keda/order-processor/order-processorsrc/quizzes/chapter-9/9.7.1/validatingadmissionpolicy-quiz.jssrc/quizzes/chapter-9/9.8.1/kustomize-quiz.jssrc/quizzes/chapter-9/9.8.2/helm-quiz.js
| spec: | ||
| containers: | ||
| - name: order-processor | ||
| image: order-processor:local | ||
| env: | ||
| - name: REDIS_ADDR | ||
| valueFrom: | ||
| secretKeyRef: | ||
| name: redis-secret | ||
| key: REDIS_ADDR | ||
| - name: PROCESS_DELAY_MS | ||
| value: "500" | ||
| resources: | ||
| requests: | ||
| cpu: 100m | ||
| limits: | ||
| cpu: 500m |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd -t f "order-processor.yaml" examples/Repository: liatrio/engineering-bootcamp
Length of output: 120
🏁 Script executed:
cat -n examples/ch9/keda/k8s/base/order-processor.yamlRepository: liatrio/engineering-bootcamp
Length of output: 974
🌐 Web query:
Kubernetes security context best practices pod level container level securityContext
💡 Result:
In Kubernetes, a security context defines privilege and access control settings for a Pod or Container [1][2]. Implementing these settings is essential for enforcing the principle of least privilege and hardening your workloads [3][4]. Key Best Practices 1. Understand Hierarchy and Overrides: Security settings can be defined at both the Pod level (applying to all containers in the Pod) and the Container level (applying only to that specific container) [1][2]. Container-level settings override Pod-level settings when there is overlap [1][3][4]. Use Pod-level settings for baseline configurations that apply to all containers, and use Container-level settings for granular, workload-specific requirements [3][4]. 2. Enforce Least Privilege: - Run as Non-Root: Always set runAsNonRoot: true and specify a non-zero runAsUser [5]. This prevents processes from running with root privileges, which is a primary target for attackers [5]. - Disable Privilege Escalation: Set allowPrivilegeEscalation: false to prevent child processes from gaining more privileges than their parent [5]. - Drop Unnecessary Capabilities: Use the capabilities field to drop all default Linux capabilities (drop: ["ALL"]) and explicitly add back only those strictly required by the application [1][5][2]. - Use Read-Only Filesystems: Set readOnlyRootFilesystem: true whenever possible to prevent unauthorized modifications to the container's filesystem [5][4]. 3. Leverage Pod Security Standards (PSS): PSS provides a standardized way to enforce security policies at the namespace level [6][7]. - Restricted Policy: This is the recommended profile for production environments [8]. It enforces current pod hardening best practices, such as requiring non-root users and blocking privilege escalation [6][8]. - Baseline Policy: Use this for development or less sensitive workloads; it prevents known privilege escalations while remaining broadly compatible [6][8]. - Avoid Privileged: The Privileged policy is unrestricted and should be avoided unless absolutely necessary for system-level workloads [8][7]. 4. Use Modern Security Profiles: - Seccomp: Explicitly set the seccompProfile to RuntimeDefault to restrict the system calls a container can make [2][6]. - AppArmor: Use the appArmorProfile field to apply pre-configured security profiles on the node [1][2]. 5. Implementation Strategy: - Gradual Adoption: When implementing PSS, use the audit and warn enforcement modes first to identify potential violations without breaking existing workloads [7][9]. - Strategic Namespacing: Organize namespaces based on the required PSS profile (e.g., separate namespaces for Restricted and Baseline workloads) [9]. - Regular Audits: Combine security contexts with other Kubernetes security features like RBAC and Network Policies to ensure a defense-in-depth posture [8][10].
Citations:
- 1: https://kubernetes.io/docs/concepts/policy/security-context/
- 2: http://k8s.io/docs/concepts/workloads/pods/advanced-pod-config/
- 3: https://wiz.io/academy/kubernetes-security-context-best-practices
- 4: https://www.wiz.io/academy/container-security/kubernetes-security-context-best-practices
- 5: https://www.dynatrace.com/news/blog/kubernetes-security-best-practices-security-context/
- 6: https://kubernetes.io/docs/concepts/security/pod-security-standards/
- 7: https://reintech.io/blog/kubernetes-security-best-practices-pod-security-standards-2026
- 8: https://k8s-security.guru/kubernetes-security/best-practices/cluster-setup-and-hardening/pod-security/pod-security-standards/
- 9: https://www.groundcover.com/learn/security/pod-security-standards
- 10: https://www.sysdig.com/learn-cloud-native/kubernetes-security-101
Harden order-processor runtime permissions.
The pod spec (line 15) and container definition (line 17) currently lack explicit security context configuration, allowing default privilege behavior. Add pod-level and container-level security context to enforce least privilege principles.
Suggested patch
template:
metadata:
labels:
app: order-processor
spec:
+ securityContext:
+ seccompProfile:
+ type: RuntimeDefault
containers:
- name: order-processor
image: order-processor:local
+ securityContext:
+ allowPrivilegeEscalation: false
+ readOnlyRootFilesystem: true
+ capabilities:
+ drop: ["ALL"]
+ runAsNonRoot: true
env:
- name: REDIS_ADDR📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| spec: | |
| containers: | |
| - name: order-processor | |
| image: order-processor:local | |
| env: | |
| - name: REDIS_ADDR | |
| valueFrom: | |
| secretKeyRef: | |
| name: redis-secret | |
| key: REDIS_ADDR | |
| - name: PROCESS_DELAY_MS | |
| value: "500" | |
| resources: | |
| requests: | |
| cpu: 100m | |
| limits: | |
| cpu: 500m | |
| spec: | |
| securityContext: | |
| seccompProfile: | |
| type: RuntimeDefault | |
| containers: | |
| - name: order-processor | |
| image: order-processor:local | |
| securityContext: | |
| allowPrivilegeEscalation: false | |
| readOnlyRootFilesystem: true | |
| capabilities: | |
| drop: ["ALL"] | |
| runAsNonRoot: true | |
| env: | |
| - name: REDIS_ADDR | |
| valueFrom: | |
| secretKeyRef: | |
| name: redis-secret | |
| key: REDIS_ADDR | |
| - name: PROCESS_DELAY_MS | |
| value: "500" | |
| resources: | |
| requests: | |
| cpu: 100m | |
| limits: | |
| cpu: 500m |
🧰 Tools
🪛 Checkov (3.2.528)
[medium] 1-31: Containers should not run with allowPrivilegeEscalation
(CKV_K8S_20)
[medium] 1-31: Minimize the admission of root containers
(CKV_K8S_23)
🪛 Trivy (0.69.3)
[error] 17-31: Root file system is not read-only
Container 'order-processor' of Deployment 'order-processor' should set 'securityContext.readOnlyRootFilesystem' to true
Rule: KSV-0014
(IaC/Kubernetes)
[error] 17-31: Default security context configured
container order-processor in keda-demo namespace is using the default security context
Rule: KSV-0118
(IaC/Kubernetes)
[error] 15-31: Default security context configured
deployment order-processor in keda-demo namespace is using the default security context, which allows root privileges
Rule: KSV-0118
(IaC/Kubernetes)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/ch9/keda/k8s/base/order-processor.yaml` around lines 15 - 31, Add
explicit pod and container security contexts to harden the order-processor pod:
in the Pod spec add a podSecurityContext (e.g., runAsNonRoot: true, runAsUser:
1000, fsGroup: 2000) and inside the container named "order-processor" add a
securityContext that enforces least privilege (runAsNonRoot: true, runAsUser:
1000 if not inherited, allowPrivilegeEscalation: false, readOnlyRootFilesystem:
true, capabilities: drop: ["ALL"], and seccompProfile: { type: "RuntimeDefault"
}). Update the "order-processor" container block and the surrounding spec to
include these fields so the pod and container both enforce non-root execution
and restricted capabilities.
| spec: | ||
| containers: | ||
| - name: redis | ||
| image: redis:8.6-alpine@sha256:d146f83b1e0f02fc27c26a50cee39338c736674c5959db84363e6ae3cd9e02d2 | ||
| args: | ||
| - --maxmemory | ||
| - 5mb | ||
| - --maxmemory-policy | ||
| - noeviction | ||
| ports: | ||
| - containerPort: 6379 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
git ls-files "examples/ch9/keda/k8s/base/redis.yaml"Repository: liatrio/engineering-bootcamp
Length of output: 110
🏁 Script executed:
cat -n examples/ch9/keda/k8s/base/redis.yamlRepository: liatrio/engineering-bootcamp
Length of output: 1027
🌐 Web query:
Redis 8.6 alpine runAsNonRoot securityContext compatibility
💡 Result:
The official Redis Docker image (including the Alpine variant) is designed to run as a non-root user by default [1][2]. Starting with Redis 8.0.2, the image automatically drops privileges by switching to the 'redis' user and removing unnecessary capabilities upon startup [1][2]. Because the image already defaults to a non-root user, it is inherently compatible with Kubernetes securityContext settings such as runAsNonRoot: true [3][1]. You generally do not need to perform complex workarounds to satisfy this requirement [3]. Key considerations for your deployment: 1. Default Behavior: The image handles the transition to the 'redis' user internally [1][2]. If you attempt to run the container with a specific securityContext, ensure that the user ID (UID) and group ID (GID) you specify have the necessary permissions to access the data directory (typically /data) [3][1]. 2. Privilege Dropping: This automatic privilege dropping can be bypassed if you explicitly set the --user option in Docker or use the SKIP_DROP_PRIVS=1 environment variable [1][2]. Using these overrides is not recommended as it reduces container security [1][2]. 3. Volume Permissions: If you are mounting volumes (e.g., for persistence), you may need to ensure the host directory is owned by the appropriate user or use fsGroup in your Kubernetes securityContext to allow the containerized process to read and write to the volume [3]. In summary, Redis 8.6 Alpine is fully compatible with runAsNonRoot: true out of the box, as it is engineered to drop root privileges automatically [1][2].
Citations:
- 1: https://github.com/docker-library/docs/blob/master/redis/content.md
- 2: https://hub.docker.com/_/redis
- 3: https://oneuptime.com/blog/post/2026-02-09-security-context-runasnonroot/view
🌐 Web query:
Kubernetes securityContext capabilities drop ALL redis container compatibility
💡 Result:
Yes, the Redis container is fully compatible with dropping all Linux capabilities in Kubernetes [1]. Standard Redis deployments do not require any special Linux capabilities to function [1]. Dropping all capabilities is a recommended security best practice that aligns with the principle of least privilege [1][2][3]. To implement this in your Kubernetes manifest, configure the securityContext for your Redis container as follows: spec: containers: - name: redis image: redis:latest securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL Key considerations for this configuration: 1. Compatibility: The standard Redis server process operates in user space and does not need kernel-level privileges (such as NET_BIND_SERVICE or SYS_RESOURCE) for normal operations [1]. 2. Security Best Practice: Dropping all capabilities (drop: ["ALL"]) removes potential attack vectors that could be exploited if the container process were compromised [1][3]. 3. Privilege Escalation: Setting allowPrivilegeEscalation to false is a critical companion setting [1][4]. It prevents the container process from gaining new privileges, which effectively reinforces the dropping of capabilities [4]. 4. Exceptions: Some specialized Redis distributions or enterprise configurations (such as Redis Enterprise) may optionally request capabilities like SYS_RESOURCE to automatically adjust system limits [5]. If you are using a standard Redis image, these are not required [1]. If you encounter issues with resource limits, it is recommended to configure those limits on the host or via Kubernetes resources rather than granting the container elevated capabilities [6][5]. By combining drop: ["ALL"] with allowPrivilegeEscalation: false and running as a non-root user, you achieve a hardened security posture for your Redis workload [1][3].
Citations:
- 1: https://www.systemshardening.com/articles/kubernetes/pod-security-context/
- 2: https://oneuptime.com/blog/post/2026-02-09-restrict-container-capabilities-security-context/view
- 3: https://oneuptime.com/blog/post/2026-02-09-capabilities-drop-all-add-specific/view
- 4: https://stackoverflow.com/questions/53328090/why-is-requiring-that-all-capabilities-be-dropped-in-a-kubernetes-podsecuritypol
- 5: https://redis.io/docs/latest/operate/kubernetes/security/allow-resource-adjustment/
- 6: https://dev.to/fivenineslab_30/can-pipe-buffer-limits-be-increased-from-inside-a-container-2kg4
🌐 Web query:
Kubernetes seccompProfile RuntimeDefault redis container
💡 Result:
In Kubernetes, the RuntimeDefault seccomp profile is a recommended security baseline that restricts a container's system calls to a sane, runtime-defined set, blocking dangerous operations while maintaining application compatibility [1][2][3]. By default, Kubernetes does not apply this profile, leaving containers in an Unconfined state unless explicitly configured otherwise [1][2][4]. To apply the RuntimeDefault profile to a Redis container, you have two primary options: 1. Per-Pod/Container Configuration: You can explicitly set the seccomp profile in the security context of your Redis deployment or pod manifest [5][4]. This is the most common approach for individual workloads [3][6]. apiVersion: v1 kind: Pod metadata: name: redis-secure spec: securityContext: seccompProfile: type: RuntimeDefault containers: - name: redis image: redis:latest 2. Cluster-Wide Defaulting: If you want all workloads in your cluster (including Redis) to use RuntimeDefault by default, you can enable the SeccompDefault feature gate [1][2][4]. This requires configuring the kubelet on each node with the --seccomp-default flag (or via the kubelet configuration file) [1][2][7]. When enabled, any pod that does not explicitly specify a seccomp profile will automatically use the RuntimeDefault profile instead of Unconfined [1][2][8]. Note that the specific system calls allowed or blocked by RuntimeDefault depend on the underlying container runtime (e.g., containerd or CRI-O) and the host's architecture [1][2][7]. For specialized Redis deployments, such as those requiring specific capabilities like SYS_RESOURCE for managing file descriptors, you may need to ensure your security context or SecurityContextConstraints (SCC) are configured to allow those specific requirements alongside the seccomp profile [9].
Citations:
- 1: https://v1-33.docs.kubernetes.io/docs/tutorials/security/seccomp
- 2: https://kubernetes.io/docs/tutorials/security/seccomp/
- 3: https://oneuptime.com/blog/post/2026-02-09-runtime-default-seccomp-baseline/view
- 4: https://medium.com/@mughal.asim/seccomp-in-kubernetes-a-quick-hands-on-tutorial-dd06d77934fd
- 5: https://kubernetes.io/docs/reference/node/seccomp/
- 6: https://oneuptime.com/blog/post/2026-02-09-custom-seccomp-profiles-kubernetes/view
- 7: https://kubernetes.io/blog/2021/08/25/seccomp-default
- 8: https://v1-31.docs.kubernetes.io/docs/tutorials/security/seccomp/
- 9: https://redis.io/docs/latest/embeds/k8s/openshift_scc
Add security context to harden the Redis container.
The pod and container specs lack security hardening. Redis 8.6-alpine is fully compatible with the following security settings which should be applied:
- Pod-level
securityContext.seccompProfile.type: RuntimeDefaultrestricts dangerous system calls - Container-level
securityContext.allowPrivilegeEscalation: falseprevents privilege escalation - Container-level
securityContext.capabilities.drop: ["ALL"]removes unused Linux capabilities (Redis requires none) - Container-level
securityContext.runAsNonRoot: trueenforces non-root execution (Redis 8.0.2+ switches to the redis user automatically)
Suggested patch
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
+ securityContext:
+ seccompProfile:
+ type: RuntimeDefault
containers:
- name: redis
image: redis:8.6-alpine@sha256:d146f83b1e0f02fc27c26a50cee39338c736674c5959db84363e6ae3cd9e02d2
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: ["ALL"]
+ runAsNonRoot: true
args:
- --maxmemory
- 5mb
- --maxmemory-policy
- noeviction🧰 Tools
🪛 Trivy (0.69.3)
[error] 17-25: Root file system is not read-only
Container 'redis' of Deployment 'redis' should set 'securityContext.readOnlyRootFilesystem' to true
Rule: KSV-0014
(IaC/Kubernetes)
[error] 17-25: Default security context configured
container redis in keda-demo namespace is using the default security context
Rule: KSV-0118
(IaC/Kubernetes)
[error] 15-25: Default security context configured
deployment redis in keda-demo namespace is using the default security context, which allows root privileges
Rule: KSV-0118
(IaC/Kubernetes)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/ch9/keda/k8s/base/redis.yaml` around lines 15 - 25, Add a pod- and
container-level securityContext to the Redis Pod spec to harden the container:
under the Pod spec add securityContext with seccompProfile.type: RuntimeDefault,
and under the container entry for name: redis add securityContext with
allowPrivilegeEscalation: false, capabilities.drop: ["ALL"], and runAsNonRoot:
true; update the existing container block (container name "redis") rather than
creating a new container and ensure these fields are applied alongside the
current image/args/ports entries.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
docs/9-kubernetes-container-orchestration/9.6-keda.md (1)
65-65:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse HTML
<img>tags from the rootimg/directory.Both images still use Markdown syntax and
img9/...paths. Please switch to HTML image tags and rootimg/paths.As per coding guidelines, "Use HTML
<img>tags for images and place all images in the rootimg/folder."Proposed fix
- +<img src="img/producer-consumer.jpg" class="img-center" alt="producer consumer image"> - +<img src="img/dank-hpa-meme.jpg" class="img-center" alt="dank hpa meme">Also applies to: 91-91
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/9-kubernetes-container-orchestration/9.6-keda.md` at line 65, Replace the Markdown image syntax using the relative img9/... path with an HTML <img> tag pointing to the root img/ directory and convert the attributes: change "" to an HTML <img> element using src="img/producer-consumer.jpg", class="img-center" and alt="producer consumer image"; apply the same transformation for the other occurrence referenced (line 91) so all images use HTML <img> tags and src paths under img/.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/9-kubernetes-container-orchestration/9.6-keda.md`:
- Line 54: Replace top-level exercise section headers that currently use '##'
with H3 headers '###' — specifically change "## Exercise 1 — Meet the System" to
"### Exercise 1 — Meet the System" and update the other exercise section
headings that use '##' (the other two exercise headers mentioned) to use '###'
instead so the doc follows the guideline of reserving H2 for navigation/TOC.
In `@docs/specs/01-spec-keda-exercise/01-tasks-keda-exercise.md`:
- Line 44: Change the page-level section headings that currently use "##" to
"###" so that only the navigation TOC uses H2; specifically update the "##
Tasks" heading (and the other occurrences using "##" on the same page) to "###
Tasks" (and likewise replace other "##" headings with "###") to follow the docs
convention described.
- Line 86: The task docs contain contradictory instructions about hpa.yaml: one
line says hpa.yaml is intentionally omitted for students to write an HPA and
another line requires adding hpa.yaml to the base kustomization.yaml; fix by
choosing one flow and making both lines consistent—either remove the requirement
to add hpa.yaml from kustomization.yaml (so students must create
HorizontalPodAutoscaler named order-processor-hpa in namespace keda-demo
targeting the order-processor Deployment with minReplicas: 1, maxReplicas: 10
and CPU utilization 50) or change the omission note to state that a template
hpa.yaml is provided in the base and update the omission line accordingly;
ensure references to hpa.yaml, kustomization.yaml, HorizontalPodAutoscaler,
order-processor-hpa, keda-demo, and order-processor are all aligned.
---
Duplicate comments:
In `@docs/9-kubernetes-container-orchestration/9.6-keda.md`:
- Line 65: Replace the Markdown image syntax using the relative img9/... path
with an HTML <img> tag pointing to the root img/ directory and convert the
attributes: change "" to an HTML <img> element
using src="img/producer-consumer.jpg", class="img-center" and alt="producer
consumer image"; apply the same transformation for the other occurrence
referenced (line 91) so all images use HTML <img> tags and src paths under img/.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6fa50f58-eef2-4695-8f3f-c9582a673bb5
📒 Files selected for processing (4)
.cspell.jsondocs/9-kubernetes-container-orchestration/9.6-keda.mddocs/specs/01-spec-keda-exercise/01-tasks-keda-exercise.mdexamples/ch9/keda/checkout-service/Dockerfile
✅ Files skipped from review due to trivial changes (1)
- .cspell.json
|
|
||
| --- | ||
|
|
||
| ## Tasks |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Align section header levels with docs convention.
This page uses ## as the default section level; please switch default content sections to ### and reserve ## for navigation TOC usage only.
As per coding guidelines, "Use H3 headers (###) as default within documentation pages, with H2 headers (##) reserved for navigation table of contents."
Also applies to: 68-68, 94-94, 123-123
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/specs/01-spec-keda-exercise/01-tasks-keda-exercise.md` at line 44,
Change the page-level section headings that currently use "##" to "###" so that
only the navigation TOC uses H2; specifically update the "## Tasks" heading (and
the other occurrences using "##" on the same page) to "### Tasks" (and likewise
replace other "##" headings with "###") to follow the docs convention described.
…load generator in Taskfile
Summary by CodeRabbit