Troubleshooting encore... Résolution DNS avec du Cilium et des pods en HostNetwork.

Troubleshooting encore... Résolution DNS avec du Cilium et des pods en HostNetwork.
Photo by Jp Valery / Unsplash

Petite note de la soirée avec le setup d'une stack Elastic. Pour le setup de la stack, je vous laisse lire la belle doc upstream d'Elastic et l'installation de celle-ci par l'opérateur OLM (Operator Lifecycle Manager) qui va bien. Ce qui est intéressant ici c'est sa mise en oeuvre conjointement au CNI (Container Network Interface) Cilium. Cilium outre le fait qu'il soit très à la mode en ce moment, notamment parce qu'il utilise les eBPF (confer la doc: which is no longer an acronym for anything) du kernel linux. Projet très en vogue en ce moment permettant de tourner des scripts en eBPF en kernel space. Une bonne explication est donnée sur ce blog, je trouve. Cela permet d'avoir des performances incomparable avec les autres CNI utilisant netfilter.

Bref, ici on a un problème lorsque l'on déploie son cluster elasticsearch et ses agents. Une fois un agent sur un autre nœud que celui sur lequel tourne le serveur fleet (ou elastic peu importe) où il est censé envoyer ses informations. Celui-ci n'arrive pas à requêter le DNS du cluster. On a pas de réponse du DNS tout court.

Etudions cela en détails.

Qui plante ?

On voit que l'agent sur le nœud distant CrashLoopBackoff.

$ kc get pods -owide
NAME                                       READY   STATUS             RESTARTS         AGE     IP            NODE                  NOMINATED NODE   READINESS GATES
elastic-agent-agent-cbfwf                  0/1     CrashLoopBackOff   66 (3m56s ago)   7h1m    192.168.1.2   gilgamesh.uruk.home   <none>           <none>
elastic-agent-agent-qgnq9                  1/1     Running            14 (10m ago)     7h      192.168.1.3   enlil.uruk.home       <none>           <none>
elasticsearch-uruk-es-elastic-0            1/1     Running            0                7m49s   10.2.0.199    enlil.uruk.home       <none>           <none>
fleet-server-uruk-agent-6f686bc686-p2lqf   1/1     Running            3 (7m28s ago)    9h      10.2.0.39     enlil.uruk.home       <none>           <none>
kibana-uruk-kb-568f744864-kwvp8            1/1     Running            2 (6m39s ago)    9h      10.2.0.194    enlil.uruk.home       <none>           <none>

Pourquoi ?

On regarde pourquoi:

$ kc logs elastic-agent-agent-cbfwf
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
{"log.level":"info","@timestamp":"2022-09-30T23:46:58.165Z","log.origin":{"file.name":"cmd/enroll_cmd.go","file.line":471},"message":"Starting enrollment to URL: https://fleet-server-uruk-agent-http.elastic.svc:8220/","ecs.version":"1.6.0"}
{"log.level":"warn","@timestamp":"2022-09-30T23:47:48.302Z","log.logger":"transport","log.origin":{"file.name":"transport/tcp.go","file.line":52},"message":"DNS lookup failure \"fleet-server-uruk-agent-http.elastic.svc\": lookup fleet-server-uruk-agent-http.elastic.svc on 10.3.0.10:53: read udp 10.0.0.12:49829->10.3.0.10:53: i/o timeout","ecs.version":"1.6.0"}
Error: fail to enroll: fail to execute request to fleet-server: lookup fleet-server-uruk-agent-http.elastic.svc on 10.3.0.10:53: read udp 10.0.0.12:49829->10.3.0.10:53: i/o timeout
For help, please see our troubleshooting guide at https://www.elastic.co/guide/en/fleet/8.4/fleet-troubleshooting.html
Error: enrollment failed: exit status 1
For help, please see our troubleshooting guide at https://www.elastic.co/guide/en/fleet/8.4/fleet-troubleshooting.html

Debug

Oh un DNS lookup failure. Etrange. Tout le monde résout bien à part ça… Dans ce cas, on lance un petit pod de debug dans le namespace. J'ai pris une définition de pod je ne sais plus où, je vous le copie colle ici, à modifier selon vos tests. Ici, j'ai spécifiquement indiqué le nœud sur lequel tourner, positionné sur le réseau du nœud et changé la politique de résolution de nom du pod pour coller au pod qui part en vrille:

apiVersion: v1
kind: Pod
metadata:
  name: dnsutils
  #  namespace: kube-system
spec:
  containers:
  - name: dnsutils
    image: k8s.gcr.io/e2e-test-images/jessie-dnsutils:1.3
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
  dnsConfig:
    searches:
      - operators.svc.cluster.local
      - svc.cluster.local
      - cluster.local
  nodeName: gilgamesh.uruk.home
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet

Et ensuite, on y va:

$ kc exec -it dnsutils -- bash 
root@gilgamesh:/# nslookup fleet-server-uruk-agent-http.elastic.svc
;; reply from unexpected source: 192.168.1.3#53, expected 10.3.0.10#53
;; reply from unexpected source: 192.168.1.3#53, expected 10.3.0.10#53

Ah intéressant. Après, c'est un peu bête le pod étant sur le même réseau que le host, je peux très bien faire le test depuis le host lui-même:

$ nslookup fleet-server-uruk-agent-http.elastic.svc
;; reply from unexpected source: 192.168.1.3#53, expected 10.3.0.10#53
;; reply from unexpected source: 192.168.1.3#53, expected 10.3.0.10#53

Chou blanc, donc. Bien alors qu'est-ce qu'il se passe, à priori tout est bien positionné niveau paramétrage alors qu'est-ce qui cloche ?

Seek and .....

Je me dis que je vais regarder sur le site de Cilium dans la doc, forum, slack si je trouve quelque chose. Ils ont une très bonne documentation de troubleshooting qui m'a bien servi. J'ai tenté de regarder si j'avais un problème global mais tout est au vert. Il faut donc regardé les communications au global du pod qui s'occupe de router le traffic du pod pour m'apercevoir d'un truc louche:

$ kc exec -n kube-system cilium-gsvb9 -it -- cilium monitor | grep 53
Defaulted container "cilium-agent" out of: cilium-agent, mount-cgroup (init), apply-sysctl-overwrites (init), clean-cilium-state (init)
[...]
-> overlay flow 0x0 , identity remote-node->unknown state unknown ifindex cilium_vxlan orig-ip 0.0.0.0: 192.168.1.2:48474 -> 10.2.0.113:53 udp
[...]

A chaque fois, qu'une résolution DNS est demandée il y a cette trace qui apparait. On peut y voir remote-node->unknown et state unknown...

Après un peu de recherche sur le github du projet, l'issue #12141 donne une piste. Il faudrait retiré le masquerading de la configuration. L'issue date un peu alors il faudra suivre les changements de configuration, le paramètre ne s'appelant plus global.masquerade mais enable-ipv4-masquerading.

... Resolv

Il faudra éditer le configmap de cilium et changer le paramètre pour résoudre le problème:

$ kc edit cm cilium-config -n kube-system
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
[...]
  enable-ipv4-masquerade: "false"
[...]

Ensuite, retestons:

$ nslookup fleet-server-uruk-agent-http.elastic.svc 10.2.0.113
Server:         10.2.0.113
Address:        10.2.0.113#53

** server can't find fleet-server-uruk-agent-http.elastic.svc: REFUSED

Essayons avec le fqdn plutôt:

nslookup fleet-server-uruk-agent-http.elastic.svc.cluster.local 10.2.0.113
Server:         10.2.0.113
Address:        10.2.0.113#53

Name:   fleet-server-uruk-agent-http.elastic.svc.cluster.local
Address: 10.3.19.109

Mieux. Et idem dans le pod dnsutils, il n'était pas nécessaire de tester dans un pod ici car le réseau utilisé était celui du noeud... A faire moins tard la prochaine fois...