Kubernetes名前空間のすべてのポッドのキャッシュをクリアしたい。 1つのリクエストをエンドポイントに送信し、エンドポイントはネームスペース内のすべてのポッドにHTTP呼び出しを送信してキャッシュをクリアします。現在、Kubernetesを使用して1つのポッドのみをヒットでき、どのポッドがヒットするかを制御することはできません。
ロードバランサーがRRに設定されていても、ポッドに連続的にヒットする(n回、nはポッドの総数)と、他のリクエストが忍び寄ることがあります。
同じ問題がここで説明されましたが、実装の解決策が見つかりませんでした: https://github.com/kubernetes/kubernetes/issues/18755
Hazelcastを使用してキャッシュのクリア部分を実装しようとしています。すべてのキャッシュを保存し、Hazelcastがキャッシュの更新を自動的に処理します。
この問題に別のアプローチがある場合、または特定のリクエストのすべてのエンドポイントにヒットするようにkubernetesを構成する方法がある場合、ここで共有すると非常に役立ちます。
ポッドでkubectlを取得し、api-serverにアクセスできる場合は、すべてのエンドポイントアドレスを取得してcurlに渡すことができます。
kubectl get endpoints <servicename> \
-o jsonpath="{.subsets[*].addresses[*].ip}" | xargs curl
ポッドでkubectlを使用しない代替:
ポッドからAPIサーバーにアクセスする推奨方法は、kubectlプロキシを使用することです。 https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#accessing-the-api- from-a-pod これはもちろん、少なくとも同じオーバーヘッドを追加します。または、REST apiを直接呼び出して、トークンを手動で提供する必要があります。
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は必要ありません。この方法では、APIサーバーにアクセスするためにcurlとjson出力を解析するために「jq」のみが必要です。
curl $APISERVER/api/v1/namespaces/default/endpoints --silent \
--header "Authorization: Bearer $TOKEN" --insecure \
| jq -rM ".items[].subsets[].addresses[].ip" | xargs curl
UPDATE(最終バージョン)
通常、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 MiB、しかしJSONを簡単に解析するためには価値があります)
別の方法を見つけようとしている皆さんのために、分散イベントリスナーとしてhazelcastを使用しました。 githubに同様のPOCを追加しました: https://github.com/vinrar/HazelcastAsEventListener
このスクリプト を使用してこの問題を修正しました。 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
を実行する必要があります。