Integrating Network Policy with Helm for Enhanced Kubernetes Security
Learn how to enhance your Kubernetes cluster security by implementing Network Policies through Helm charts, including best practices and real-world examples.
Understanding Network Policies in Kubernetes
Network Policies are Kubernetes resources that control the flow of network traffic between pods, namespaces, and external endpoints. They act as a firewall, allowing you to:
- Isolate workloads
- Enforce zero-trust networking
- Implement microsegmentation
- Control ingress and egress traffic
- Define allowed communication paths
Why Use Helm for Network Policies?
Helm provides several advantages when managing Network Policies:
- Templating capabilities for dynamic policy generation
- Version control and rollback support
- Consistent policy deployment across environments
- Easy updates and modifications
- Reusable policy templates
Prerequisites
Before implementing Network Policies with Helm, ensure:
- Your cluster supports Network Policies (e.g., using Calico, Cilium, or other CNI with NetworkPolicy support)
- Helm 3.x is installed
- Proper RBAC permissions are configured
Basic Network Policy Template
Here’s a basic example of a Network Policy template in a Helm chart:
# templates/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Release.Name }}-policy
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.appName }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: {{ .Values.allowedNamespace }}
- podSelector:
matchLabels:
role: {{ .Values.allowedRole }}
ports:
- protocol: TCP
port: {{ .Values.servicePort }}
egress:
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: UDP
port: 53 # DNS
Implementing Common Security Patterns
1. Default Deny All Traffic
# templates/default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Release.Name }}-default-deny
namespace: {{ .Release.Namespace }}
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
2. Allow Specific Microservices Communication
# templates/microservice-policy.yaml
{{- range .Values.microservices }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ $.Release.Name }}-{{ .name }}-policy
spec:
podSelector:
matchLabels:
app: {{ .name }}
ingress:
{{- range .allowedServices }}
- from:
- podSelector:
matchLabels:
app: {{ . }}
{{- end }}
{{- end }}
3. Monitoring System Access
# templates/monitoring-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Release.Name }}-monitoring
spec:
podSelector:
matchLabels:
app: {{ .Values.appName }}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- port: {{ .Values.metricsPort }}
protocol: TCP
Values File Configuration
# values.yaml
appName: myapp
servicePort: 8080
metricsPort: 9090
allowedNamespace: frontend
allowedRole: api
microservices:
- name: frontend
allowedServices:
- backend
- cache
- name: backend
allowedServices:
- database
- cache
- name: database
allowedServices: []
Best Practices
1. Layer Your Policies
Create multiple policies that build upon each other:
# templates/layered-policy.yaml
{{- if .Values.security.layers.basic }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Release.Name }}-basic
spec:
podSelector: {}
policyTypes:
- Ingress
---
{{- end }}
{{- if .Values.security.layers.advanced }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Release.Name }}-advanced
spec:
# Additional restrictions
{{- end }}
2. Use Conditional Policies
# templates/conditional-policy.yaml
{{- if .Values.environment.production }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Release.Name }}-strict-policy
spec:
# Stricter rules for production
{{- else }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Release.Name }}-dev-policy
spec:
# More permissive rules for development
{{- end }}
3. Template Helper Functions
# templates/_helpers.tpl
{{- define "networkpolicy.common.labels" -}}
app: {{ .Values.appName }}
environment: {{ .Values.environment.name }}
managed-by: {{ .Release.Service }}
{{- end }}
Testing and Validation
- Dry Run Installation:
helm install --dry-run --debug my-policies ./network-policies
- Policy Validation:
kubectl auth can-i create networkpolicy
kubectl auth can-i update networkpolicy
- Testing Connectivity:
# Test pod connectivity
kubectl run test-pod --image=busybox -n test-namespace -- wget -O- http://service-name:port
Troubleshooting
Common issues and solutions:
Policy Not Applied
- Check CNI plugin supports Network Policies
- Verify label selectors match pods
- Check policy is in correct namespace
Unexpected Blocking
- Review egress rules for DNS access
- Check namespace labels
- Verify port specifications
Policy Conflicts
- Network Policies are additive
- More specific policies take precedence
- Review all policies in namespace
Monitoring and Logging
Enable policy monitoring:
# templates/policy-metrics.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
annotations:
metrics-enabled: "true"
policy-log-level: "info"
Conclusion
Integrating Network Policies with Helm provides a powerful way to manage and enforce network security in Kubernetes clusters. Key takeaways:
- Use templates for consistent policy deployment
- Layer policies for defense in depth
- Implement environment-specific policies
- Regular testing and validation
- Monitor policy effectiveness
Remember to:
- Start with restrictive policies
- Test thoroughly before production
- Document policy intentions
- Monitor policy impacts
- Regularly review and update policies
For more information, refer to the Kubernetes Network Policy documentation and Helm documentation.