Cilium no EKS [Lab Session]
Tags: community, kubernetes, cilium, ebpf
Published: 2024-07-07 10:54:21

> **eBPF-based Networking, Observability, Security**
> Cilium is an open source, cloud native solution for providing, securing, and observing network connectivity between workloads, fueled by the revolutionary Kernel technology eBPF

> _Source: https://cilium.io/_

**Network & Service Mesh (sidecarless)**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97y9niuvyq0oyf1snfax.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oi6s6waulh0lp4a64onm.png)

{% embed https://youtu.be/e10kDBEsZw4?si=RESMnqdWvibBaJMw %}

Source: https://cilium.io/

---

## Arquitetura do Lab

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ettag8yxwybnzv136maa.png)

Repositórios:
- EKS: https://github.com/paulofponciano/EKS-Cilium
- App Microsserviços: https://github.com/msfidelis/nutrition-overengineering 

## Deploy da infra

```sh
git clone https://github.com/paulofponciano/EKS-Cilium.git
```
```sh
cd EKS-Cilium
```

> Altere as variáveis necessárias para o seu lab em [_variables.tfvars_](https://github.com/paulofponciano/EKS-Cilium/blob/main/variables.tfvars)

```sh
tofu init
```
```sh
tofu plan --var-file variables.tfvars
```
```sh
tofu apply --var-file variables.tfvars
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dx6oyi0ut3625oh063uv.png)

Por padrão, o EKS vai subir com Amazon VPC CNI, podemos ver o DaemonSet 'aws-node'. No cenário desse lab, removemos esse DaemonSet e fazemos a reciclagem dos nodes - Executando um **Terminate** nos nodes atuais. Com isso, o EKS vai subir novos nodes para o replace. Como CNI, utilizamos o Cilium.

```sh
kubectl get ds -A
```
```sh
kubectl delete ds aws-node -n kube-system
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z91xx0qxf9ym2u6q5hb6.png)

O **Terminate** dos nodes iniciais pode ser feito na console ou CLI. ⚠️ É importante tomar cuidado nessa ação para não afetar nenhum outro recurso que não seja do lab.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33w13gkgzryi7iu1j2fe.png)

Após a reciclagem dos nodes, podemos ver que está tudo certo no namespace 'kube-system':

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcllpl4oz00m3qd6dlxp.png)

Usando o **cilium-cli**, podemos ver o status do Cilium neste cluster:

```sh
cilium status
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j78f0iopgribvoh714e7.png)

Se conectarmos diretamente em um node, podemos ver a _conflist_ do Cilium CNI:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2a5y7wg9bkoq83h8gtbg.png)

## Deploy da app

Utilizamos uma app baseada em microsserviços, do Grande Matheus Fidelis [@fidelissauro](https://x.com/fidelissauro). Valeu Matheus!
Essa app utiliza gRPC em sua comunicação interna.

```sh
git clone https://github.com/msfidelis/nutrition-overengineering.git
```
```sh
cd nutrition-overengineering/samples/cilium
```

Ajuste o 'host' no manifesto de ingress da [health-api](https://github.com/msfidelis/nutrition-overengineering/blob/main/samples/cilium/health-api.yml) se necessário. Aqui ficou assim:

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: health-api
  namespace: health-api
spec:
  ingressClassName: cilium
  rules:
  - host: health-api.pauloponciano.digital
    http:
      paths:
      - backend:
          service:
            name: health-api
            port:
              number: 8080
        path: /
        pathType: Prefix
```

Foi criado manualmente um registro no DNS público apontando o host para o CNAME do Network Load Balancer.

Apply dos manifestos:

```sh
kubectl apply -f .
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xu4u10dt0f5rlz9p0134.png)

Podemos fazer um teste rápido e ver o retorno da api:

```sh
for i in {1..3}
do
  curl --location --request POST 'http://health-api.pauloponciano.digital/calculator' \
  --header 'Content-Type: application/json' \
  --data-raw '{
     "age": 26,
     "weight": 90.0,
     "height": 1.77,
     "gender": "M",
     "activity_intensity": "very_active"
  }' --silent | jq .
done
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uhsneib1ybtkg6cui2vk.png)

## Hubble UI e Prometheus

Da mesma forma que foi criado o registro no DNS público para a _health-api_, também foram criados registros para acesso ao hubble-ui e o grafana (o grafana faz parte do kube-prometheus-stack).

Vamos aumentar a volume na _health-api_ utilizando o k6 com script abaixo:

```js
import http from 'k6/http';

export default function () {
  const url = 'http://health-api.pauloponciano.digital/calculator';
  const payload = JSON.stringify({
    age: 26,
    weight: 90.0,
    height: 1.77,
    gender: 'M',
    activity_intensity: 'very_active',
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
  };

  const response = http.post(url, payload, params);
  console.log(response.body);
}
```

```sh
k6 run http_k6.js --vus=200 --duration=60m
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/veu3rametd6mw7ek525u.png)

Agora podemos ver no Hubble as interações entre os serviços muito próximo do _real time_:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owg6n78g4o884j1dk77h.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgnmfbvkvjpv0xyysmw1.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4nw7koa39svgyu3zuqxk.png)

Como ele é interativo, é possível ver mais detalhes das conexões focando em cada componente:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/65hewjfisjrsk2xkv5n7.png)

Agora vamos dar uma olhada no Grafana. Quando foi feito o deploy do **kube-prometheus-stack** via Helm na execução de terraform, também foram importados dois dashboards:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9dz2quembzc47vnbo6im.png)

Acessando o dashboard **Hubble L7 HTTP Metrics by Workload**, podemos ver algumas métricas dos microsserviços.

**health-api:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f25uka875n7w19sa4n89.png)

**recommendations-grpc:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4wdlnba9ug1kzx4l39vv.png)

**imc-grpc:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/duxpc796oau9mxlkewa2.png)

## Tetragon e Loki

O **Tetragon** também é executado como um DaemonSet. Com ele podemos ver as _Syscalls_ que estão acontecendo no ambiente e ele tem a capacidade de fazer _enforce_. No lab, foi feito deploy do **Promtail + Loki**, com eles, guardamos esses eventos do Tetragon em uma bucket do S3 e podemos visualizar no Grafana.

**Tetragon Events** dashboard:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/imgdo4ojderqp4bhb2gz.png)

Executando aleatoriamente alguns comandos de 'kubectl exec', e com as queries do Loki já configuradas, pegamos alguns eventos que podem ser considerados maliciosos. Isso graças a quantidade de informações que o Tetragon gera:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b58w88ueanz60xa1iwwz.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xtxzj3x6h6lrb1naizin.png)

---

Recomendo de verdade que assistam a talk do Matheus Fidelis na LINUXtips, mostrando isso ao vivo e com as explicações sobre o poder e as possibilidades que o eBPF proporciona para tecnologias como o Cilium.

{% embed https://www.youtube.com/watch?v=U7pNEmsjT40&t=15118s %}

---

Keep shipping! 🐳