Bob's Deep Dive into Kubernetes Pod Security
Join Bob as he dives deep into securing Kubernetes pods with Alex's guidance. Learn about Pod Security Policies, RoleBindings, and Service Accounts, and discover how to lock down your pods with best practices for a robust and secure Kubernetes environment.
With his Kubernetes cluster up and running, Bob was ready to delve deeper into securing his deployments. As he prepared to take the next step, Josie reminded him, "Securing your pods isn’t just about following a checklist—it’s about building a fortress for your applications. To get this right, why not chat with Alex from the platform team? He’s the pod security expert."
Bob nodded, appreciating Josie’s continued guidance, and headed off to meet Alex.
Bob headed over to Alex's desk, eager to learn more.
📂 Code Repository: Explore the complete code and configurations for this article on GitHub.
Pod Security Policies (PSPs) or Pod Security Admission
Alex, a seasoned platform engineer, welcomed Bob with a friendly smile. "So, you're looking to lock down your pods, I hear?" he said.
Bob nodded. "Josie mentioned something called Pod Security Policies, or Pod Security Admission. I'm not too familiar with them."
Alex leaned back in his chair. "Think of PSPs or Pod Security Admission as the building codes for your Kubernetes apartments," he explained. "They dictate the safety standards each apartment must meet."
Bob's eyes lit up. "That makes sense!"
Alex continued, "They're incredibly powerful tools for controlling various aspects of pod security."
"Here’s how Pod Security Policies (or Admission) integrate with other Kubernetes components to secure your pods at every step:"
Together, they explored the capabilities of PSPs or Pod Security Admission:
- Resource Usage: Limiting the amount of CPU and memory a pod can consume
- Privilege Escalation: Preventing containers from running with root privileges or escalating their permissions
- Network Access: Restricting the network traffic allowed to and from the pod.
- Security Contexts: Defining security settings for the pod and its containers, such as user IDs, group IDs, and file system permissions
"By the way, Bob," Alex said, "you should know that Pod Security Policies are being replaced with Pod Security Admission in newer Kubernetes versions. While they work similarly, Pod Security Admission simplifies enforcement by focusing on predefined security levels. It’s worth exploring if you’re running a newer cluster."
Crafting a Pod Security Policy
Alex then guided Bob through creating a sample Pod Security Policy.
"Let's create a policy that prevents containers from running as root and restricts privilege escalation," Alex suggested.
They crafted the following YAML definition:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: no-root-psp
spec:
runAsUser:
rule: MustRunAsNonRoot
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
"This policy ensures that all containers within a pod must run as a non-root user," Alex explained. "It's a fundamental security practice in Kubernetes."
Bob nodded, appreciating the hands-on example.
Linking Policies to Service Accounts
Next, Alex showed Bob how to assign the Pod Security Policy to a service account.
"We'll need to create a role and bind it to a service account, granting it permission to use the policy," Alex explained.
They created the following YAML definitions:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: my-namespace
name: no-root-psp-role
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames: ['no-root-psp']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: my-namespace
name: no-root-psp-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: no-root-psp-role
subjects:
- kind: ServiceAccount
name: my-service-account
namespace: my-namespace
"Now, any pod deployed using this service account will be subject to the no-root-psp
policy," Alex explained.
Bob was impressed by the level of control and security that PSPs provided.
Connecting Security Policies to Deployments
Finally, Alex showed Bob how to integrate the service account into his deployment configuration.
Services in Kubernetes rely on Endpoints to route traffic only to Pods that are marked as ready. Endpoints are dynamically updated based on Pod readiness, ensuring traffic is directed only to healthy Pods. This complements the security policies we've implemented.
"You'll need to specify the service account in your deployment YAML," Alex said.
They updated Bob's deployment.yaml
file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
# ... other deployment configurations
template:
spec:
serviceAccountName: my-service-account
# ... other pod configurations
"Now, your deployment will use the service account, and the pod will automatically adhere to the Pod Security Policy," Alex concluded.
Bob thanked Alex for the detailed explanation and the practical examples. He felt much more confident in securing his Kubernetes pods, but he also knew this was just one piece of the puzzle.
- Enforce Non-Root Policies: Always run pods as non-root and prevent privilege escalation to minimise risks
- Use Network Policies: Restrict pod communication to authorised traffic only
- Adopt Pod Security Admission: Transition from PSPs to simplify security enforcement in newer Kubernetes versions
- Secure Deployments: Link service accounts to policies and use secure container images with proper secrets management
- Layered Security is Key: Combine multiple measures for a comprehensive defence strategy
Back at Bob's Desk
"Back at his desk, Bob reflected on what he’d learned. 'PSPs are like building codes for Kubernetes deployments,' he told Josie. She smiled, 'Exactly, but remember to layer those policies with secure images, secrets, and network controls.' Bob nodded, ready to implement his newfound knowledge."
Bob nodded, pulling up his deployment.yaml
file. "I'm ready to put all of this into practice."
He started by adding the serviceAccountName
that Alex had helped him configure:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
template:
spec:
serviceAccountName: my-service-account
# ... other pod configurations
"That ensures my pod will adhere to the 'no-root-psp' policy," he thought, nodding in satisfaction.
Next, he recalled the importance of using a secure container image. He made sure his deployment.yaml
referenced an image that followed the best practices he'd learned earlier:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
template:
spec:
serviceAccountName: my-service-account
containers:
- name: my-app
image: my-registry/my-secure-image:latest # Use a secure image from a trusted registry
# ... other container configurations
"Minimal base image, vulnerability scanning, and image signing – check, check, check," Bob muttered to himself, ticking off the security checklist in his mind.
He then turned his attention to secrets management. He knew he couldn't store sensitive information directly in his deployment YAML. Instead, he created a Kubernetes Secret to hold his API key:
apiVersion: v1
kind: Secret
metadata:
name: my-api-key
type: Opaque
data:
api-key: <BASE64_ENCODED_API_KEY>
He then mounted this Secret as an environment variable in his pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
template:
spec:
serviceAccountName: my-service-account
containers:
- name: my-app
image: my-registry/my-secure-image:latest
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: my-api-key
key: api-key
# ... other container configurations
"Now my application can access the API key securely," Bob thought, pleased with his progress.
Finally, Alex explained how Network Policies help control traffic between pods and services. "Let’s create a policy to allow only specific traffic," Alex suggested, pulling up an example:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-ingress
spec:
podSelector:
matchLabels:
app: my-app
ingress:
- from:
- podSelector:
matchLabels:
app: trusted-app
ports:
- protocol: TCP
port: 8080
"This ensures that only pods with the label app: trusted-app
can communicate with my-app
on port 8080," Alex explained. "It’s like locking the doors and giving access only to those with the right keys."
He reviewed his deployment.yaml
file one last time, satisfied with the security measures he had implemented. He had successfully combined Pod Security Policies, secure container images, secrets management, and network policies to create a robust security posture for his application.
Bob leaned back, satisfied with his progress. As he reviewed his deployment configurations, Josie popped by to check in. "Great work, Bob. Now let’s ensure your applications handle configurations and sensitive data securely. Managing ConfigMaps and Secrets is key to keeping everything under control."
Josie’s next challenge made Bob pause. How could he securely handle configurations and sensitive data like API keys without compromising his applications? He grinned—this was going to be exciting.