我有一个名为my-service的服务,其端点名为refreshCachemy-service托管在多个服务器上,偶尔我希望其中一台服务器上的my-service事件在所有服务器上触发my-service上的refreshCache。为此,我手动维护托管my-service的所有服务器的list,拉出该列表,并为每个服务器向<server>/.../refreshCache发送REST请求。

我现在正在将我的服务迁移到k8s。与之前类似,我在托管my-service的所有服务器上运行refreshCache,我现在希望能够在托管my-service的所有pod上运行refreshCache。不幸的是,我不能手动维护一个list的pod IP,因为我的理解是IP在k8s中是短暂的,所以我需要能够从其中一个pod中的容器内动态获取节点中所有pod的IP。这可能吗?

注意:我知道kubectl get endpoints ...可以使用此信息,但是我的容器中不能使用kubectl

分析解答

您不需要kubectl来访问Kubernetes API。您可以使用任何可以发出HTTP请求的工具来执行此操作。

Kubernetes API是一个简单的HTTP REST API,如果它在集群中作为Pod运行,则所需的所有身份验证信息都会出现在容器中。

对于来自群集中容器内的获取Endpoints对象 my-service,您可以执行以下操作:

curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
  https://kubernetes.default.svc:443/api/v1/namespaces/{namespace}/endpoints/my-service

注意:将{namespace}替换为my-service端点资源的命名空间。

要提取返回的JSON的IP地址,您可以将输出传递给像jq这样的工具:

... | jq -r '.subsets[].addresses[].ip'

请注意,执行此操作的Pod需要对Endpoints资源具有读取权限,否则将拒绝API请求。

您可以使用ClusterRole,ClusterRoleBinding和Service Account执行此操作(您只需将其设置一次):

kubectl create sa endpoint-reader
kubectl create clusterrole endpoint-reader --verb=get,list --resource=endpoints
kubectl create clusterrolebinding endpoint-reader --serviceaccount=default:endpoint-reader --clusterrole=endpoint-reader

然后,通过在pod.spec.serviceAccountName字段中指定它,将endpoint-reader ServiceAccount用于要执行上述curl命令的Pod。

授予任何其他API操作(即动词和资源的组合)的权限以相同的方式工作。