NetworkPolicy
networking
Creating effective Kubernetes Network Policies involves defining rules that explicitly allow or deny traffic to and from your pods. Here are some example policies to help you understand how to set up both restrictive (deny) and permissive (allow) behaviors in your cluster.
1. Default Deny All Traffic to a Namespace
A common starting point in securing a namespace in Kubernetes is to deny all traffic to all pods within a namespace. This “default deny” policy doesn’t specify any allow
rules, making it effectively a deny-all policy.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
2. Allow Traffic from Specific Namespace
After setting a default deny, you might want to allow traffic from specific namespaces. This policy allows all ingress traffic from any pod in a specified namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-specific-namespace
namespace: default
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
policyTypes:
- Ingress
3. Allow Traffic Only on Specific Port
This policy allows traffic to specific ports, useful for services like web servers or databases that listen on well-known ports.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-specific-port
namespace: default
spec:
podSelector:
matchLabels:
app: myapp
ingress:
- ports:
- protocol: TCP
port: 80
policyTypes:
- Ingress
4. Allow Traffic from Certain Pods
This policy allows ingress traffic from pods with specific labels. It’s particularly useful when you want to restrict communication between services based on their roles or functions.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-certain-pods
namespace: default
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
5. Deny Traffic from Certain Pods
Conversely, you might want to explicitly deny traffic from certain pods while allowing others. This example shows a policy that denies ingress from any pod labeled as app: test
.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-from-certain-pods
namespace: default
spec:
podSelector:
matchLabels:
app: production
ingress:
- from:
- podSelector:
matchLabels:
app: test
policyTypes:
- Ingress
6. Combine Allow and Deny Rules
You can create complex policies that combine various allow and deny rules to finely control traffic flows:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: complex-network-policy
namespace: default
spec:
podSelector:
matchLabels:
app: complex-app
ingress:
- from:
- namespaceSelector:
matchLabels:
environment: trusted
- podSelector:
matchLabels:
app: trusted-peer
egress:
- to:
- ipBlock:
cidr: 192.168.0.0/16
except:
- 192.168.1.0/24
policyTypes:
- Ingress
- Egress
This complex policy allows ingress from any pod in a “trusted” namespace or labeled as trusted-peer
and restricts egress to a specific CIDR block, except for a specific subnet.
Applying Network Policies
To apply any of these network policies, save the YAML to a file and use kubectl
:
kubectl apply -f <filename>.yaml
Remember, network policies are additive, and they only apply to the pods in the namespaces that have them. Make sure your Kubernetes network plugin supports network policies, such as Calico, Weave, or Cilium.
In Kubernetes, applying a default deny policy for all traffic to a namespace is a common security practice. This ensures that no pods within the namespace can receive traffic unless explicitly allowed by additional NetworkPolicy resources. Here’s how to set up a default deny all traffic policy for a namespace and then allow traffic specifically for an nginx deployment within that namespace.
Step 1: Create a Namespace
First, let’s create a namespace where these policies will be applied. This isolates the resources and the network policies to a specific part of your Kubernetes cluster.
kubectl create namespace nginx-example
Step 2: Apply a Default Deny All Network Policy
Apply a default deny all ingress and egress traffic policy to the newly created namespace. This policy selects all pods in the namespace by not specifying any podSelector
.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: nginx-example
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
To apply this policy, save it to a file named default-deny-all.yaml
and run:
kubectl apply -f default-deny-all.yaml
Step 3: Deploy Nginx to the Namespace
Now deploy an nginx pod into the nginx-example
namespace. Here’s a simple deployment of nginx:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: nginx-example
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Save this to nginx-deployment.yaml
and apply it with:
kubectl apply -f nginx-deployment.yaml
Step 4: Allow Traffic to Nginx
To allow traffic to reach your nginx pod, create a NetworkPolicy that permits certain types of ingress traffic. For example, allow HTTP traffic on port 80:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-nginx
namespace: nginx-example
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from: []
ports:
- protocol: TCP
port: 80
Save this to allow-nginx.yaml
and apply it:
kubectl apply -f allow-nginx.yaml
Step 5: Verify the Configuration
After applying these configurations, the nginx pod should be accessible on port 80 from within the cluster, but all other traffic should be denied by default. You can test this by attempting to access the nginx service from another pod in the same namespace or a different namespace without corresponding egress rules.
This setup helps in maintaining strict control over the network traffic, ensuring that only explicitly allowed connections can be established to and from pods within the nginx-example
namespace.
To see the output after running the commands to set up your nginx deployment and NetworkPolicies in Kubernetes, you’ll need to perform a series of checks to confirm the correct application of the configurations and test the actual network functionality.
Step 1: Confirm the Network Policy and Deployment
First, verify that the NetworkPolicy and nginx deployment have been successfully created:
# List NetworkPolicies in the nginx-example namespace
kubectl get networkpolicy -n nginx-example
# List deployments in the nginx-example namespace to check nginx is deployed
kubectl get deployments -n nginx-example
# Check the status of the nginx pods to ensure they're running
kubectl get pods -n nginx-example
Expected Output
- NetworkPolicies:
NAME POD-SELECTOR AGE default-deny-all <none> 1m allow-nginx app=nginx 1m
- Deployments:
NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 1/1 1 1 1m
- Pods:
NAME READY STATUS RESTARTS AGE nginx-deployment-<random-string> 1/1 Running 0 1m
Step 2: Test Connectivity
To test if the nginx pod is correctly accessible according to the NetworkPolicy:
a. Inside the Same Namespace
Attempt to access the nginx service from another pod in the same namespace. This will demonstrate whether the ingress policy allows traffic:
- Run a temporary busybox pod and try to connect to nginx:
kubectl run -it --rm --namespace=nginx-example --image=busybox test-pod -- wget -qO- http://nginx-deployment
b. From a Different Namespace
Try accessing the nginx service from a pod in a different namespace to verify that the default deny policy across namespaces is effective:
- First, switch to or create a different namespace and try the same command:
kubectl create namespace test kubectl run -it --rm --namespace=test --image=busybox test-pod -- wget -qO- http://nginx-deployment.nginx-example
Expected Output
Inside the Same Namespace:
Connecting to nginx-deployment (10.244.1.10:80) <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </html>
This output indicates that the nginx server is accessible from within the same namespace, serving the default nginx page.
From a Different Namespace:
wget: can't connect to remote host (10.244.1.10): Connection timed out
This output shows that the default deny policy is effectively blocking traffic from outside the
nginx-example
namespace.
Step 3: Review Logs
Finally, you can check the logs from the nginx pod to see if it logs the access attempts, which can be useful for debugging:
kubectl logs -n nginx-example -l app=nginx
These steps provide a comprehensive check to ensure your deployments and network policies function as intended. If there’s any discrepancy in the expected behavior, you should revisit your configurations for any misconfigurations or typos.
To allow traffic from a specific namespace to your nginx deployment within the nginx-example
namespace, you’ll need to create a NetworkPolicy that explicitly allows this traffic. Here’s how to set up a NetworkPolicy to allow traffic from a designated namespace (e.g., trusted-namespace
) to the nginx pods in the nginx-example
namespace.
Step 1: Label the Trusted Namespace
First, ensure that the namespace from which you want to allow traffic to the nginx pods is labeled. This label will be used in the NetworkPolicy to identify the namespace.
kubectl label namespace trusted-namespace name=trusted-namespace
Step 2: Create a NetworkPolicy
Create a NetworkPolicy that allows traffic from the trusted-namespace
to the nginx pods in the nginx-example
namespace. Save the following YAML to a file, for example, allow-from-trusted-namespace.yaml
:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-trusted-namespace
namespace: nginx-example
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: trusted-namespace
ports:
- protocol: TCP
port: 80
This policy selects pods with the label app: nginx
in the nginx-example
namespace and allows incoming traffic on TCP port 80 from any pod in namespaces labeled with name: trusted-namespace
.
Step 3: Apply the NetworkPolicy
Apply this policy by running:
kubectl apply -f allow-from-trusted-namespace.yaml
Step 4: Test the Connectivity
To test if the policy works as intended, you can attempt to connect to the nginx service from a pod in the trusted-namespace
. First, run a temporary pod in the trusted-namespace
and try to access the nginx service:
kubectl run -it --rm --namespace=trusted-namespace --image=busybox test-pod -- wget -qO- http://nginx-deployment.nginx-example.svc.cluster.local:80
Expected Output
- Success Scenario: If the network policy is correctly configured and applied, you should see the default nginx HTML page output or a successful HTTP response.
- Failure Scenario: If there is no response, it could indicate that the network policy does not allow the traffic as expected, or there might be other restrictive policies or connectivity issues.
Monitoring and Adjustments
- Monitor Network Policies: Regularly check and monitor the logs and network traffic to ensure that the policies are working as expected.
- Adjust Policies: As your cluster evolves, you might need to update or refine your network policies to accommodate changes in deployments or namespace configurations.
This setup helps ensure that only the specified namespaces can access your resources, enhancing the security of your Kubernetes environment.
To configure a NetworkPolicy that specifically denies traffic from certain pods within your Kubernetes environment while allowing others, you can set up a policy that allows traffic from all sources except those specifically denied. This example demonstrates how to deny traffic from pods labeled as app: untrusted
while allowing others to access the nginx deployment in the nginx-example
namespace.
Step 1: Define the Deny Policy
First, we create a policy that explicitly denies traffic from pods with a specific label (app: untrusted
) to the nginx pods. Since Kubernetes NetworkPolicies do not directly support “deny” rules, you need to frame the policy as an “allow from all except” by not selecting the untrusted pods in the allow rule.
Here’s the YAML configuration for a policy that allows ingress to the nginx pods from any source that does not have the label app: untrusted
:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-except-untrusted
namespace: nginx-example
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchExpressions:
- key: app
operator: NotIn
values:
- untrusted
ports:
- protocol: TCP
port: 80
Step 2: Apply the NetworkPolicy
Save this configuration to a file named allow-except-untrusted.yaml
and apply it using the following command:
kubectl apply -f allow-except-untrusted.yaml
Step 3: Test the Configuration
To ensure the policy is functioning as intended, you can perform tests from pods with different labels:
From an Untrusted Pod: Try to access the nginx service from a pod labeled as
untrusted
:kubectl run -it --rm --namespace=nginx-example --image=busybox untrusted-pod --labels="app=untrusted" -- wget -qO- http://nginx-deployment.nginx-example.svc.cluster.local:80
From a Trusted Pod: Try the same from a pod not labeled as
untrusted
:kubectl run -it --rm --namespace=nginx-example --image=busybox trusted-pod --labels="app=trusted" -- wget -qO- http://nginx-deployment.nginx-example.svc.cluster.local:80
Expected Output
- Untrusted Pod: The request should fail if the NetworkPolicy is working correctly. You may see a timeout or connection error.
- Trusted Pod: This request should succeed, displaying the default nginx start page or a successful HTTP response.
Monitoring and Adjustments
- Monitor Logs: Keep an eye on the logs of your nginx pods to see the access attempts and ensure that untrusted requests are being blocked.
- Adjust Policies: As requirements change, you might need to update the labels or the scope of the NetworkPolicy to fine-tune the traffic rules.
By using the NotIn
operator with matchExpressions in a NetworkPolicy, you can effectively control pod traffic by excluding specific sources. This approach helps you to safeguard your applications from unwanted access while maintaining necessary connectivity within your cluster.
Last updated 03 Jun 2024, 13:43 +0530 .