Implementando K8S Network Policy

George Tavares
5 min readNov 18, 2021

--

Ao realizar meus estudos no #bondedocka para uma possível certificação CKA/CKAD num futuro próximo vi que um dos tópicos um pouco obscuro é o network policy. O network policy permite configurar regras de acesso entre os diversos serviços rodando no kubernetes

Por padrão a política do network policy é permitir tudo, mas em clusters de produção é uma boa prática configurar restrições de acesso de forma que serviços que não precisem acessar determinado recurso esteja bloqueado. Por exemplo, em um caso onde um banco de dados que é acessado somente pela aplicação A, podemos criar uma regra onde somente a aplicação A pode acessar esse banco e se tivermos uma aplicação B, essa não conseguirá acesso.

Algo que devemos ter atenção é que nem todos os CNI de redes implementam esse recurso de network policy. Por favor verifique qual o cni esta sendo usado no seu cluster para verificar a disponibilidade do recurso. No meu estudo utilizei o calico.

Para simular um servidor eu utilizei um proxy reverso/load balance web chamado traefik que com poucas configurações permite que eu tenha duas portas abertas (80 e 8080) para simular algumas situações.

O deploy do pod e do serviço traefik realizei com o seguinte traefik.yaml:

---
apiVersion: v1
kind: Pod
metadata:
name: traefik
labels:
app: traefik
spec:
hostname: traefik
containers:
- image: traefik:v2.5
name: traefik
args: ["--api.insecure=true"]
ports:
- containerPort: 80
- containerPort: 8080
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: traefik
name: traefik
spec:
ports:
- port: 8080
name: config
protocol: TCP
targetPort: 8080
- port: 80
protocol: TCP
name: http
targetPort: 80
selector:
app: traefik

Por default o traefik já roda na porta 80, e com o flag “ — api.insecure=true” ele expõe a porta 8080, que é uma porta de monitoramento/configuração do traefik (para nos pouco importa, so queremos realizar acesso simples as portas para simular tipo um banco de dados). Para aplicar o yaml basta realizar um kubectl apply -f traefik.yaml.

A idéia que iremos simular no primeiro momento será um bloqueio de porta entre pods de forma que o pod busybox poderá acessar o traefik mas o pod busybox2 não conseguirá. Além de politicas entre pods, o network policy permite criar politicas entre namespaces ou usando CIDR's. As politicas que podem ser configuradas são de ingress (entrada no pod) ou egress (saída do pod). No nosso caso usaremos o ingress para isso

Bem comecemos com um teste simples para ver a conectividade sem nenhum network policy:

kubectl run busybox --image=busybox --labels=app=busybox -it/ # echo "GET /" |  nc -w 3 traefik 80
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close
400 Bad Request/ #/ # echo "GET /" | nc -w 3 traefik 8080
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close
400 Bad Request/ #/ # exit
Session ended, resume using 'kubectl attach busybox -c busybox -i -t' command when the pod is running

Dessa forma iniciamos um pod do busybox simples para testar a conectivida. Utilizei para o teste o netcat, com um flag (-w 3 ) para dar um timeout caso não consiga realizar acesso em 3 segundos. Neste caso ambos os requests foram bem sucedidos. Note que já subi o pod com o label app=busybox que usarei logo em seguida. Desta forma temos um pod com o label busybox e outro pod com o label traefik.

Vamos criar uma politica policy.yaml criando um ingress no traefik somente na porta 80:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access
namespace: default
spec:
podSelector:
matchLabels:
app: traefik
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: busybox
ports:
- protocol: TCP
port: 80
# - from:
# - podSelector:
# matchLabels:
# app: busybox
# ports:
# - protocol: TCP
# port: 8080

Novamente vamos realizar o kubectl apply -f policy.yaml para testar. A idéia desse arquivo de configuração é realizar restrições no pod com o label app=traefik, de forma que haja ingress somente dos pods com label app=busybox na porta 80. Vamos realizar os testes agora (caso tenha saído,podes atachar no pod):

kubectl attach busybox -c busybox -i -t
If you don't see a command prompt, try pressing enter.
/ # echo "GET /" | nc -w 3 traefik 80
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close
400 Bad Request/ #
/ # echo "GET /" | nc -w 3 traefik 8080
/ #

O request para a porta 80 ocorreu sem problema algum porém no request para a porta 8080 após os 3 segundos o prompt retornou (timeout)

Agora descomente as linhas referente a porta 8080 e realize o apply novamente. Desta forma o resultado é este:

kubectl attach busybox -c busybox -i -t
If you don't see a command prompt, try pressing enter.
/ # echo "GET /" | nc -w 3 traefik 80
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close
400 Bad Request/ #
/ # echo "GET /" | nc -w 3 traefik 8080
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close
400 Bad Request/ #
/ #

Por último, testemos o pod busybox2:

kubectl run busybox2 --image=busybox -it 
If you don't see a command prompt, try pressing enter.
/ # echo "GET /" | nc -w 3 traefik 80
/ # echo "GET /" | nc -w 3 traefik 8080
/ #

Como criei esse pod sem nenhum label , nenhum request passa na regra definida e ocorre o timeout.

O network policy é um recurso extremamente poderoso do k8s que permite realizar diversas configurações de segurança no k8s, além de ser um dos tópicos da certificação do CKA/CKAD. Com um pouco de atenção podemos entender o conceito e realizar diversos testes e configurações nas topologias requisitadas no exame.

https://asciinema.org/a/448977

--

--

George Tavares
George Tavares

No responses yet