Pod内容器调用Kubernetes API超时,集群内API地址及获取方法咨询
这个问题我之前也碰到过,核心原因是集群内的容器和集群外的网络环境不一样——你在集群外能用节点IP访问API Server,但集群内的容器可能受限于CNI插件配置、网络策略或者节点防火墙,没法直接通过节点IP的6443端口连通API Server。
正确的访问地址
Kubernetes默认在集群的default命名空间下创建了一个名为kubernetes的Service,专门用来让集群内的应用访问API Server。你应该用这个Service的集群域名或者ClusterIP来替换.kube/config里的节点IP:
- 集群域名(推荐,稳定不变):
https://kubernetes.default.svc.cluster.local:443 - ClusterIP(动态分配,但一般不会变动):需要通过kubectl命令获取
获取ClusterIP的方法
直接用kubectl查询这个Service的信息即可:
kubectl get service kubernetes -n default
输出会类似这样:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d
其中CLUSTER-IP列的10.96.0.1就是你要的地址,对应的API地址就是https://10.96.0.1:443。
如果想直接提取ClusterIP,用这个命令更高效:
kubectl get service kubernetes -n default -o jsonpath='{.spec.clusterIP}'
更灵活的方式:用环境变量
其实Kubernetes会自动给集群内的Pod注入两个环境变量:
KUBERNETES_SERVICE_HOST:对应kubernetesService的ClusterIPKUBERNETES_SERVICE_PORT:对应Service的端口(默认是443)
你可以在应用里直接读取这两个环境变量,拼接成API地址https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT},这样连手动修改.kube/config都省了,适配性更强。
额外提示:关于认证
另外,其实集群内的应用可以通过ServiceAccount自动认证,不需要手动挂载.kube/config——你只需要给Pod绑定对应的ServiceAccount权限,Kubernetes会自动挂载认证相关的文件到Pod的/var/run/secrets/kubernetes.io/serviceaccount/目录下,大部分K8s客户端库(比如Java的client-go、Python的kubernetes-client)会自动识别这个路径的认证信息,比手动维护config文件更安全可靠。
内容的提问来源于stack exchange,提问作者Salvatore D'angelo

