Note: If you have missed my previous articles on Docker and Kubernetes, you can find them here:
Application deployment models evolution.
Getting started with Docker.
Docker file and images.
Publishing images to Docker Hub and re-using them.
Docker- Find out what's going on.
Docker Networking- Part 1.
Docker Networking- Part 2.
Docker Swarm-Multi-Host container Cluster.
Docker Networking- Part 3 (Overlay Driver).
Introduction to Kubernetes.
Kubernetes- Diving in (Part 1)-Installing Kubernetes multi-node cluster.
Kubernetes-Diving in (Part2)- Services.
Kubernetes- Infrastructure As Code with Yaml (part 1).
Kubernetes- Infrastructure As Code Part 2- Creating PODs with YAML.
Kubernetes Infrastructure-as-Code part 3- Replicasets with YAML.
Kubernetes Infrastructure-as-Code part 4 - Deployments and Services with YAML.
Deploying a microservices APP with Kubernetes.
Kubernetes- Time based scaling of deployments with python client.
Kubernetes Networking - The Flannel network explained.
Kubernetes- Installing and using kubectl top for monitoring nodes and PoDs
Kubernetes Administration- Scheduling
Kubernetes Administration- Storage
Kubernetes Administration- Users
Microservices applications are made up of multiple components that run as PoDs, replicasets, or deployment. These components communicate with each other and with the external world through Kubernetes networking capabilities. Kubernetes does not have builtin networking modules but relies on third-party networking plugins that confirm to Container Networking Specification.
At a high level, any plugin should satisfy the following requirements:
Allow containers in the same PoD to communicate with each other and share the IP address.
Allow PoDs, agents to communicate with other PoDs on the Kubernetes cluster without requiring NAT.
Enforce network access control between PoDs, Namespaces, services etc with support for Network policies.
Not all networking plugins support policies. The Flannel plugin does not have support for policy controller, hence it is not possible to restrict communication between different PoDs running on the same cluster. Few others like, Calico networking plugin provides support for network policies along with a few other enhancements. In this article, I am going to show how easy it is to implement network policies with Calico.
To get started, we need to install Calico. Steps for installations are provided here.
Note: If you have installed flannel before, you need to uninstall it. To uninstall flannel:
root@sathish-vm2:/home/sathish# kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
I chose to install Calico with Kubernetes API datastore and the steps given in the installation URL works perfectly. The PoD network is default i.e 192.168.0.0/16
root@sathish-vm2:/home/sathish# curl https://docs.projectcalico.org/manifests/calico.yaml -O
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 183k 100 183k 0 0 323k 0 --:--:-- --:--:-- --:--:-- 323k
root@sathish-vm2:/home/sathish# kubectl apply -f calico.yaml
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
serviceaccount/calico-node created
deployment.apps/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
poddisruptionbudget.policy/calico-kube-controllers created
root@sathish-vm2:/home/sathish# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-744cfdf676-67qmc 1/1 Running 2 2m20s
calico-node-2dxjf 1/1 Running 0 2m28s
calico-node-pz8d2 1/1 Running 0 2m27s
coredns-f9fd979d6-d8wzr 1/1 Running 0 93d
coredns-f9fd979d6-xcxzc 1/1 Running 0 93d
etcd-sathish-vm2 1/1 Running 0 93d
kube-apiserver-sathish-vm2 1/1 Running 1 93d
kube-controller-manager-sathish-vm2 1/1 Running 0 29d
kube-proxy-lcf25 1/1 Running 0 93d
kube-proxy-tf8z8 1/1 Running 0 93d
kube-scheduler-sathish-vm2 1/1 Running 0 29d
Now that the calico plugin is installed, let's tryout network policies. For this, I will be using a pod running httpd server with a service (ClusterIP) and another pod with busybox that will emulate a client.
root@sathish-vm2:/home/sathish# kubectl run mywebserv --image=nginx
pod/mywebserv created
#Expose PoD as clusterIP
root@sathish-vm2:/home/sathish# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 93d
mywebserv ClusterIP 10.107.110.226 <none> 80/TCP 4s
As the service type is ClusterIP, it should be accessible to all PoDs. Let's check this out.
root@sathish-vm2:/home/sathish# kubectl run mybusybox --image=busybox --rm -it
/ # nc -z -v -w 2 10.107.110.226 80
10.107.110.226 (10.107.110.226:80) open
Lets now create a policy to block access from all pods to this service
root@sathish-vm2:/home/sathish# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mywebserv 1/1 Running 0 22m run=mywebserv
root@sathish-vm2:/home/sathish# cat denyweb.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-webservice
spec:
podSelector:
matchLabels:
run: mywebserv
policyTypes:
- Ingress
root@sathish-vm2:/home/sathish# kubectl create -f denyweb.yaml
networkpolicy.networking.k8s.io/deny-webservice created
root@sathish-vm2:/home/sathish# kubectl get networkpolicy
NAME POD-SELECTOR AGE
deny-webservice run=mywebserv 64s
The type of policy is Ingress, which means traffic inbound to the PoD. The default behaviour for policy is to drop all traffic. Since we did not specify any permit rules, all traffic is dropped. Let's check this out by running a simple test again with busybox.
root@sathish-vm2:/home/sathish# kubectl run mybusybox --image=busybox --rm -it
If you don't see a command prompt, try pressing enter.
/ # nc -z -v -w 2 10.107.110.226 80
nc: 10.107.110.226 (10.107.110.226:80): Connection timed out
It is possible to allow traffic selectively from certain PoDs by matching labels. Let's modify the created policy to try this out
root@sathish-vm2:/home/sathish# cat denyweb.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-webservice
spec:
podSelector:
matchLabels:
run: mywebserv
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
client: specialclient
#Delete and recreate the policy
kubectl delete -f denyweb.yaml
networkpolicy.networking.k8s.io "deny-webservice" deleted
kubectl create -f denyweb.yaml
networkpolicy.networking.k8s.io/deny-webservice created
Let's try accessing from a busybox PoD without specialclient label.
root@sathish-vm2:/home/sathish# kubectl run mybusybox --image=busybox --rm -it
If you don't see a command prompt, try pressing enter.
/ # nc -z -v -w 2 10.107.110.226 80
nc: 10.107.110.226 (10.107.110.226:80): Connection timed out
Now let's try from busybox PoD with proper label
root@sathish-vm2:/home/sathish# kubectl run mybusybox --image=busybox --rm -it --labels "client=specialclient"
If you don't see a command prompt, try pressing enter.
/ # nc -z -v -w 2 10.107.110.226 80
10.107.110.226 (10.107.110.226:80) open
Bingo it works!!
Ingress traffic can also be filtered on basis of the namespace, tcp/UDP ports, IP CIDR blocks etc. It is also possible to filter out Egress traffic with egress ACL rules. For a list of what's supported, you can refer the Kubernetes documentation here.
Hope this short intro to network policies was useful. Thanks for your visit and happy weekend :)
Comments