Kubernetes-Objekte für Tests zur Laufzeit verändern: Beispiel am HCL Connections Component Pack

Kubernetes-Objekte für Tests zur Laufzeit verändern: Beispiel am HCL Connections Component Pack

Analyse und Debugging von Kubernetes-Elementen können sich als schwierig herausstellen. Vor allem wenn es sich um proprietäre Software handelt, bei der man nicht weiß, was im Container vor sich geht. Manchmal ist es notwendig, Code, Skripte oder andere Elemente im Container testweise zu verändern.

Da Container kurzlebig sind, kann man nicht den Quellcode einer Anwendung ändern und diese neu starten. Der Container würde in diesem Falle auf Basis des Images neu gebaut. Zwar könnte man ein eigenes Image erstellen, dass auf dem originalen aufbaut. Für schnelle Tests gestaltet sich dies jedoch als aufwändig. Zumal man die nicht mehr benötigten Images später aus der Registry löschen sollte.

Beispiel: Debugging des HCL Connections Component Pack

Ein solcher Beispielfall war der doppelte Hostname im IHS hinter einem Nginx-Ingress. Mittels kubectl exec konnte der Quellcode der NodeJS-Anwendung zwar analysiert werden. Zur Fehleranalyse war jedoch Debugging notwendig – zumindest in Form von Variablenausgaben.

Konkretes Beispiel: In der Datei /home/ibm/app/lib/server/suggestedCommunitiesService.js ist folgende Zeile zu finden:

const scHeaders = utilsOrientServer.sanitizeHeaders(req);

Hier vermutete ich ein Problem mit den Headern, beispielsweise fehlende oder ungültige Authentifizierungstokens. Daher wollte ich nach dieser Zeile gerne die Variable scHeaders mit console.log() ausgeben.

Anpassung des Einstiegspunktes

Interessant ist diesbezüglich die Anpassung des Einstiegspunktes. Jedes Image besitzt einen, meist in Form einer ENTRYPOINT Anweisung. Sie legt fest, welcher Befehl nach dem Buildprozess ausgeführt werden soll, um die gewünschte Anwendung zu starten. Jeder Container besitzt hierfür in Kubernetes die Eigenschaft command. Sie ermöglicht das Überschreiben des Einstiegspunktes.

Optional: Reduzierung von Replikas

Gehört der Container zu einem Deployment oder ReplikaSet, sollte man zumindest auf Testsystemen zuvor die Replikas auf 1 reduzieren. Ansonsten müsste man jeden zugehörigen Pod anpassen oder darauf hoffen, dass die Anfrage beim angepassten Pod landet. In diesem Beispiel arbeiten wir mit dem Deployment namens community-suggestions vom Component Pack:

kubectl scale deploy community-suggestions --replicas=1

Alten Einstiegspunkt ermitteln

Nun sollte nur noch ein Pod laufen:

$ kubectl get po | grep community-suggestions
community-suggestions-77d4b99c4c-4l47r    1/1       Running     0          5d

Zunächst müssen wir herausfinden, was im Container läuft. Dafür wechseln wir mit kubectl exec in den Container:

$ kubectl exec community-suggestions-77d4b99c4c-4l47r -- ps
PID   USER     TIME  COMMAND
    1 root      0:00 node /home/ibm/app/node_modules/.bin/cross-env NODE_ENV=production node lib/server/server.js
   14 root      2:04 node lib/server/server.js

Der Einstiegspunkt lautet hier:

/home/ibm/app/node_modules/.bin/cross-env NODE_ENV=production node lib/server/server.js

Einstiegspunkt mit Modifikation überschreiben

Um unsere Modifikation vorzunehmen, überschreiben wir den Einstiegspunkt: Er soll zunächst JS-Code zum Debuggen in die Datei einfügen, bevor der Applikationsserver gestartet wird. Dafür bearbeiten wir das Deployment

kubectl edit deploy community-suggestions

und suchen nach der Eigenschaft containers. Hier legen wir entsprechend eingerückt unseren Einstiegspunkt fest:

containers:
- command:
  - sh
  - -c
  - sed -i 's/\(const scHeaders = utilsOrientServer.sanitizeHeaders(req);\)/\1console.log("MY_TEST_HEADERS:", scHeaders);/g' /home/ibm/app/lib/server/suggestedCommunitiesService.js;
    node /home/ibm/app/node_modules/.bin/cross-env NODE_ENV=production node lib/server/server.js
  # ...

Die Codedatei führ nach der Deklaration und Zuweisung von scHeaders nun die Konsolenausgabe aus. Das Präfix MY_TEST_HEADERS hilft uns, dies in den Logs einfacher wiederzufinden:

$ kubectl logs -f $(kubectl get po | grep community-suggestions | awk '{print $1}')
MY_TEST_HEADERS: { 'x-request-id': '8f12bf924eecc1a3e84ed91f823d35b9',
  'x-forwarded-host': 'cnx65-k8s.internal, cnx65-k8s.internal' }

Leave a Reply