Kubenetes: Возможно ли ударить несколько контейнеров с одним запросом в кластере Кубернетес

Я хочу очистить кеш во всех модулях в моем пространстве имен Kubernetes. Я хочу отправить один запрос к конечной точке, который затем отправит HTTP-вызов всем модулям в пространстве имен для очистки кэша. В настоящее время я могу поразить только одну капсулу с помощью Kubernetes, и у меня нет контроля над тем, какая из капсул будет поражена.

Эта проблема обсуждалась здесь, но я не смог найти решение для реализации: https://github.com/kubernetes/kubernetes/issues/18755

Я пытаюсь реализовать очистку части кэша с помощью Hazelcast, в которой я буду хранить весь кэш, а Hazelcast автоматически позаботится об обновлении кэша.

Если есть альтернативный подход к этой проблеме или способ настроить kubernetes для достижения всех конечных точек для некоторых конкретных запросов, обмен здесь был бы очень полезен.

Ответ 1

Если в вашем модуле есть kubectl и у вас есть доступ к api-серверу, вы можете получить все адреса конечных точек и передать их в curl:

kubectl get endpoints <servicename> \
        -o jsonpath="{.subsets[*].addresses[*].ip}" | xargs curl

Альтернатива без кубектл в стручке:

рекомендуемый способ доступа к серверу API из модуля - использование прокси-сервера kubectl: https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#accessing-the-api-from-a- стручок это, конечно, добавил бы, по крайней мере, те же накладные расходы. В качестве альтернативы вы можете напрямую вызвать API REST, вам нужно будет предоставить токен вручную.

APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ")
TOKEN=$(kubectl describe secret $(kubectl get secrets \
     | grep ^default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d " ")

если вы предоставляете переменные APISERVER и TOKEN, вам не нужен kubectl в вашем модуле, поэтому вам нужен только curl для доступа к серверу api и jq для анализа вывода json:

curl $APISERVER/api/v1/namespaces/default/endpoints --silent \
     --header "Authorization: Bearer $TOKEN" --insecure \
     | jq -rM ".items[].subsets[].addresses[].ip" | xargs curl

ОБНОВЛЕНИЕ (окончательная версия)

APISERVER обычно может быть установлен на kubernetes.default.svc, и токен должен быть доступен по адресу /var/run/secrets/kubernetes.io/serviceaccount/token в модуле, поэтому нет необходимости предоставлять что-либо вручную:

TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token); \
curl https://kubernetes.default.svc/api/v1/namespaces/default/endpoints --silent \
     --header "Authorization: Bearer $TOKEN" --insecure \
     | jq -rM ".items[].subsets[].addresses[].ip" | xargs curl

jq доступен здесь: https://stedolan.github.io/jq/download/ (<4 МБ, но оно того стоит для простого анализа JSON)

Ответ 2

Для тех из вас, кто пытается найти альтернативу, я использовал hazelcast в качестве распределенного прослушивателя событий. Добавлен аналогичный POC на github: https://github.com/vinrar/HazelcastAsEventListener

Ответ 3

Я исправил эту проблему с помощью этого скрипта. Вам просто нужно написать эквивалентную команду для вызова API. Я использовал curl чтобы сделать это.

Ниже приведено использование скрипта:

function usage {
    echo "usage: $PROGNAME [-n NAMESPACE] [-m MAX-PODS] -s SERVICE -- COMMAND"
    echo "  -s SERVICE   K8s service, i.e. a pod selector (required)"
    echo "     COMMAND   Command to execute on the pods"
    echo "  -n NAMESPACE K8s namespace (optional)"
    echo "  -m MAX-PODS  Max number of pods to run on (optional; default=all)"
    echo "  -q           Quiet mode"
    echo "  -d           Dry run (don't actually exec)"
}

Например, чтобы запустить команду curl http://google.com на всех пакетах службы с именем s1 и пространством имен n1, необходимо выполнить ./kcdo -s s1 -n n1 -- curl http://google.com.