Automatyzacja z Kubectl, Bash and CRON.
Ostatnio natknąłem się na następujące wymaganie - pobierz dane z poda w kubernetesie i prześlij do bucketu w chmurze. Wyglądało prosto, więc zabrałem się odrazu do roboty. Ze strony infra nic szczególnego:
bastion -> k8s -> bastion -> tar data -> gcs.
Aby to zadanie zrealizować, będziemy potrzebować kilku rzeczy, takich jak dostęp do klastra k8s, tak też od tego zacząłem. Istnieje conajmniej kilka sposobów aby autoryzować dostęp do klastra k8s, ale sam wybrałem stworzenie ServiceAccount z odpowiednimi uprawnieniami. Takie rozwiązanie ma tą zaletę, że daje elastyczność przy ewentualnej zmianie w/w uprawnień. Kiedy już ServiceAccount został stworzony, przeszedłem do zainstalowania narzędzi, które umożliwiają interakcję z google, kubernetes-em i gcs-em:
1. gcloud - do interakcji z google
2. kubectl - do interakcji z kubernetes
3. gsutil - do interakcji z gcs
4. gcloud-auth-plugin - do autoryzacji dostępu z GKE.
Do tej pory wszystko przebiega sprawnie.
Po ukończeniu powyższych kroków, napisałem skrypt, który wygląda dość prosto:
#!/bin/bash
CURRENT_DATE=`date -I`
GCS=$BUCKET_NAME
echo "Activating proper service account..."
gcloud auth activate-service-account --key-file=$PATH_TO_YOUR_SA
gcloud container clusters get-credentials $CLUSTER_NAME --region $REGION --project $PROJECT
echo "Copying data into local folder..."
/home/$USER/google-cloud-sdk/bin/kubectl cp namespace/pod-name:/data local-data/
echo "Packing data..."
tar czf backup-data-${CURRENT_DATE}.tar.gz local-data/
echo "Sending data to gcs..."
gcloud storage cp backup-data-${CURRENT_DATE}.tar.gz gs://${GCS}
echo "Removing dumps ..."
rm local-data/*
rm backup-data-${CURRENT_DATE}.tar.gz
echo "Finished ! ${CURRENT_DATE}"
Po napisaniu w/w, zmieniłem ustawienia skryptu na to, żeby był wykonywalny, przez prostą komendę chmod +x script_name.sh. Kiedy skrypt mógł być wykonywany, pozostało go tylko przetestować. Tak też zrobiłem i zadziałał dobrze. Pozostało dodać tylko odpowiedni wpis w CRON, ustawić odpowiedni czas do wykonywania skryptu, wpisać ściężkę i zrobione. Cóż...nie do końca. Następnego dnia spojrzałem i skrypt zadziałał, cron również, ale archiwum było puste. Dlaczego ? Kilka rzeczy się na to złożyło. Pierwsza z nich to binarki google-cloud-sdk nie są domyślnie wpisywane do zmiennej $PATH, co skutkuje tym, że kubectl się wogóle nie wykonuje. Jednym z rozwiązań jest ustawienie ścieżki bezwzględnej do binarki. Po zastosowaniu zmian nadal pojawiał się problem, zatem napisałem prosty skrypt do zdebugowania problemu:
#!/bin/bash
echo "Activating proper service account..."
gcloud auth ...
gcloud container ...
echo "Get pods lists for ..."
/home/$USER/google-cloud-sdk/bin/kubectl get pods -n namespace 2>&1 > /home/$USER/test.log
I znowu niepowodzenie. Tym razem okazało się, że argumenty są przekazywane w nieprawidłowym porządku - to samo polecenie wykonane w konsoli nie napotyka żadnych problemów. Ot co, jedna z zagadek kubectl-a. Żeby obejść problem zmieniłem kolejność i powstało coś takiego:
#!/bin/bash
echo "Activating proper service account..."
gcloud auth ...
gcloud container ...
echo "Get pods lists for ..."
/home/$USER/google-cloud-sdk/bin/kubectl -n namespace get pods 2>&1 > /home/$USER/test.log
...i okazuje się, że działa. Pomyślałem, że skoro powyższe działa, to zmodyfikuje oryginalny skrypt i powinno być ok. Niestety, nic bardziej mylnego ! Metoda prób i błędów okazała się owocna i z dodatkiem prostego przekierowania problem został odkryty - brak wykrycia binarki gke-auth-plugin. Stwierdziłem, że szkoda czasu na kolejne workaroundy i dodałem do zmiennej $PATH lokalizację z binarkami google-cloud-sdk:
export PATH="/home/$USER/google-cloud-sdk/bin:$PATH"
i o to chodziło - teraz pliki są prawidłowo pobierane do lokalnego katalogu, kompresowane i wysyłane do GCS.

