如何通过Kubernetes中的另一个Pod访问部署在一个Pod上的服务?

时间:2018-11-21 06:16:45

标签: docker kubernetes kubectl kubelet

任何人都可以让我知道如何通过kubernetes集群中的另一个Pod访问部署在一个Pod上的服务吗?

示例:

有一个部署在Node1上的Nginx服务(以Pod名称为Nginx-12345)和另一个部署在Node2上的服务(以Pod名称为Service-23456)。现在,如果“服务”出于某种原因要与“ nginx”进行通信,那么我们如何在“ service-23456”窗格中访问“ nginx”?

5 个答案:

答案 0 :(得分:3)

有多种方法可以在kubernetes中访问该服务,您可以通过NodePort或LoadBalancer公开您的服务,并在集群外部访问它。

请参阅how to access the services的官方文档。

Kubernetes官方文件指出:

  

某些群集可能允许您SSH到群集中的节点。从那里您可能能够访问群集服务。这是一种非标准的方法,将在某些群集上有效,但在其他群集上无效。浏览器和其他工具可能会也可能不会安装。群集DNS可能无法正常工作。

因此,直接从其他节点访问服务取决于您所使用的Kubernetes集群类型。

编辑:

服务一旦部署到您的集群中,您就应该能够使用其名称与服务联系,并且Kube-DNS将以正确的ClusterIP进行回答,以与您的最终Pod对话。 ClusterIP由kube-proxy在Workers上创建的IPTables规则控制,该规则将您的请求NAT到最终容器的IP。

Kube-DNS命名约定为service.namespace.svc.cluster-domain.tld,默认群集域为cluster.local

例如,如果您想从任何命名空间联系mysql命名空间中名为db的服务,只需与mysql.db.svc.cluster.local对话即可。

如果这不起作用,则说明集群中的kube-dns可能存在问题。 希望这可以帮助。

EDIT2: ubuntu中的dns解析存在一些已知问题,Kubernetes官方文件指出

  

某些Linux发行版(例如Ubuntu),默认情况下使用本地DNS解析器(systemd-resolved)。 Systemd-resolved移动并用存根文件替换/etc/resolv.conf,当在上游服务器中解析名称时,该存根文件可能导致致命的转发循环。您可以使用kubelet的--resolv-conf标志来指向正确的resolv.conf(使用systemd-resolved,即/run/systemd/resolve/resolv.conf)来手动修复此问题。 kubeadm 1.11自动检测systemd-resolved,并相应地调整kubelet标志。

答案 1 :(得分:1)

我遇到了类似的问题,以下链接可能会解决您的问题。通常,所有服务在群集中都是可见的且可访问的。公开您的service-23456服务以键入CLusterID并连接端口8080。 然后,您可以从Nginx服务中调用端点“ http://service-23456:8080”。

Unable to communicate between 2 node,js apps in Istio enabled GKE cluster

答案 2 :(得分:0)

您是否将部署公开为服务?如果是这样,只需使用它的dns名称(例如http://nginx-1234)访问它-或如果它位于不同的命名空间中:http://nginx-1234.default.svc(将“默认”更改为服务所在的命名空间)或http://nginx-1234.default.svc.cluster.local

现在,如果您不公开服务,那么您可能应该这样做。您无需将其公开给外界,只需不定义服务类型,它仅在您的集群内部可用。

如果出于某种原因您不想公开服务(无法考虑任何原因),则可以向api服务器查询Pod IP。您将需要提供用于身份验证的令牌,但这些令牌在pod内可用:

获取令牌:

TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

调用api服务器:

curl https://kubernetes.default.svc/api/v1/namespaces/default/pods--silent \
     --header "Authorization: Bearer $TOKEN" --insecure

您可以通过添加?fieldSelector=spec.nodeName%3Dtargetnodename或类似内容(只需使用json路径)来优化查询。可以使用https://stedolan.github.io/jq/或任何其他JSON实用程序来解析输出。

答案 3 :(得分:0)

在这里回答了类似的问题: Kubernetes - How to acces to service from a web server in pod with a rest request

只需将“ ProductWebApp”替换为“ nginx”,将“ DashboardWebApp”替换为“ service”。

答案 4 :(得分:0)

我也遇到了类似的问题,我们通过 kubernetes 集群中的另一个 pod 访问部署在一个 pod 上的服务:

尝试了此页面中的一些解决方案,但当安全应用于 pod 时,它们不起作用。

当您尝试到达受保护的 Pod 时,这是解决方案:

http://service-name.namespace.svc.cluster.local:port-number

这通常适用于从一个 pod 到达另一个 pod,但是当您尝试到达的 pod 上应用了安全性时,这会失败。

在这里我遇到了同样的问题,因此您可以在尝试访问的 pod 中创建一个服务帐户:

service-account.yaml

apiVersion: v1

kind: ServiceAccount

metadata:

name: {{ template "kafka-schema-registry.fullname" . }}
An write a auth-policy to allow that service account :

auth-policy.yaml

{{- if .Values.auth.enabled -}}

apiVersion: security.istio.io/v1beta1

kind: AuthorizationPolicy

metadata:

name: {{ template "pod-name.fullname" . }}

spec:

selector:

matchLabels:

  app: {{ template "*pod-name*.name" . }}
action: ALLOW

rules:

from:

source:

principals: ["cluster.local/ns/name-space/sa/pod-name"]

to:

operation:

methods: ["GET", "POST", "PUT"]

After all the above changes done on above pod which you try to reach from another pods.

the other pods just needs to provide the service account name in the deployment.yaml

example as below :

deployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

name: {{ .Values.name }}

namespace: {{ .Values.namespace }}

labels:

app: {{ .Values.name }}
spec:

replicas: {{ .Values.replicaCount }}

selector:

matchLabels:

  app: {{ .Values.name }}
template:

metadata:

  annotations:

    prometheus.io/scrape: "true"

    prometheus.io/path: "/actuator/prometheus"

    prometheus.io/port: {{ .Values.service.port | quote }}

  labels:

    app: {{ .Values.name }}

spec:

  serviceAccountName: {{ *pod-name* }}