Setting up a firewall with Network Policies
While setting up the network policy, you may need to refer to the namespace created earlier. In order to being abel to referred to, namespace should have a label. Lets update the namespace with a label.
file: instavote-ns.yaml
kind: Namespace
apiVersion: v1
metadata:
name: instavote
labels:
project: instavote
apply
kubectl get namespace --show-labels
kubectl apply -f instavote-ns.yaml
kubectl get namespace --show-labels
Locking down access to a namespace
Now, define a restrictive network policy which would,
- Block all incoming connections
- Block all outgoing connections
+-----------------------------------------------------------+
| |
| +----------+ +-----------+ |
x | | results | | db | |
| | | | | |
| +----------+ +-----------+ |
| |
| |
| +----+----+--+ |
| | worker | |
| | | |
| +----+-------+ |
| |
| |
| +----------+ +-----------+ |
| | vote | | redis | |
x | | | | | |
| +----------+ +-----------+ |
| |
+-----------------------------------------------------------+
file: instavote-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default
namespace: instavote
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
apply
kubectl get netpol
kubectl apply -f instavote-netpol.yaml
kubectl get netpol
kubectl describe netpol/default
Try accessing the vote and results ui. Can you access it ?
Troubleshooting Tip
: If you do not see the above policy being in effect (i.e. if you can still access the applications), go back and check if you have applied the label to the namespace as mentioned in the beginning of this section.
Enabling external traffic to outward facing applications
+-----------------------------------------------------------+
| |
| +----------+ +-----------+ |
=====> | results | | db | |
| | | | | |
| +----------+ +-----------+ |
| |
| |
| +----+----+--+ |
| | worker | |
| | | |
| +----+-------+ |
| |
| |
| +----------+ +-----------+ |
| | vote | | redis | |
=====> | | | | |
| +----------+ +-----------+ |
| |
+-----------------------------------------------------------+
To the same file, add a new network policy object.
file: instavote-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default
namespace: instavote
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: public-ingress
namespace: instavote
spec:
podSelector:
matchExpressions:
- {key: role, operator: In, values: [vote, result]}
policyTypes:
- Ingress
ingress:
- {}
where,
instavote-ingress is a new network policy which,
- defines policy for pods with vote and results role
- and allows them incoming access from anywhere
apply
kubectl apply -f instavote-netpol.yaml
Exercise
- Try accessing the ui now and check if you are able to.
- Try to vote, see if that works? Why ?
Enabling communication between pods in the same namespace
When you tried to vote, you might have observed that it does not work. Thats because the default network policy we created earlier blocks all outgoing traffic. Which is good for securing the environment, however you still need to provide inter connection between services from the same project. Specifically vote, worker and results apps need outgoing connection to redis and db. Lets allow that with a egress policy.
+-----------------------------------------------------------+
| |
| +------------+ +-----------+ |
=====> | results | ------>| db | |
| | | | | <-------+ |
| +------------+ +-----------+ | |
| | |
| | |
| +----+----+---+ |
| | worker | |
| | | |
| +----+--------+ |
| | |
| | |
| +----------+ +-----------+ | |
| | vote | | redis | <-------+ |
=====> | | ------> | | |
| +----------+ +-----------+ |
| |
+-----------------------------------------------------------+
Edit the same policy file and add the following snippet,
file: instavote-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default
namespace: instavote
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: instavote
egress:
- to:
- namespaceSelector:
matchLabels:
project: instavote
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: public-ingress
namespace: instavote
spec:
podSelector:
matchExpressions:
- {key: role, operator: In, values: [vote, result]}
policyTypes:
- Ingress
ingress:
- {}
where,
instavote-egress is a new network policy which,
- defines policy for pods with vote, worker and results role
- and allows them outgoing access to any pods in the same namespace, and that includes redis and db
Troubleshooting Exercise
Applying the above policy has no effect on the communication between vote and redis applications. You could validate this by loading the vote app and submit a vote. It should not work. There is a problem in the network policy file above. Analyse the policies, compare them against the kubernetes api reference document, understand how its being applied and see if you could fix this problem. Your task is to ensure that vote and redis apps are communicating with one another.
Nano Project
The above network policies are a good start. However you could even further restrict access by creating a granular network policy for each application.
Create network policies with following specs,
vote
- allow incoming connections from anywhere, only on port 80
- allow outgoing connections to redis
- block everything else, incoming and outgoing
redis
- allow incoming connections from vote and worker, only on port 6379
- block everything else, incoming and outgoing
worker
- allow outgoing connections to redis and db
- block everything else, incoming and outgoing
db
- allow incoming connections from worker and results, only on port 5342
- block everything else, incoming and outgoing
result
- allow incoming connections from anywhere, only on port 80
- allow outgoing connections to db
- block everything else, incoming and outgoing