Kubernetes:需要通信的多个容器+暴露的nodePort

问题描述 投票:1回答:2

在我的设置中,有一组容器最初构建为与docker-compose一起运行。搬到Kubernetes后,我面临以下挑战:

  1. docker-compose设法提供某种类型的内部DNS,允许容器通过其名称进行寻址。如何在Kubernetes中创建这样的网络?到目前为止我发现了什么: 它们都可以是一个pod的一部分,因此可以通过localhost进行通信 他们都可以拥有一个带有匹配键:值对和服务的公共标签,但是如何处理端口?
  2. 我需要将内部端口暴露给某个NodePort,因为它必须公开可用。这样的服务配置怎么样?到目前为止我发现了什么: 这样的事情: apiVersion: v1 kind: Service metadata: labels: app: frontend name: frontend-nodeport spec: type: NodePort ports: - name: "3000-30001" port: 3000 nodePort: 30001 selector: app: frontend status: loadBalancer: {}`
kubernetes
2个回答
2
投票

Docker-compose设法提供某种类型的内部DNS,允许容器通过其名称进行寻址。如何在Kubernetes中创建这样的网络?

在您研究过程中,您确实可以采用两种方法:

  • 如果要将容器缩放在一起,则将它们放在同一个pod中,并通过localhost通过不同的端口进行通信。这种情况不太可能发生,因为当容器化应用程序与单个服务/服务器上的一个物理盒子上的进程更相似时,这种方法更合适。
  • 如果您的容器要分开缩放,这可能是您的情况,那么请使用服务。使用服务代替localhost(在上一点中),您将使用服务名称(如果pod位于相同的名称空间中)或FQDN(servicename.namespace.svc.cluster.local),如果跨名称空间访问服务。与之前的点相反,您必须为容器设置不同的端口(因为您使用localhost),在这种情况下,您可以跨多个服务使用相同的端口,因为service:port必须是唯一的。如果您希望这样做,也可以使用服务重新映射容器中的端口。

既然你把这个问题作为一个介绍性问题提出两个问题:

  • 服务解析从pod /容器的角度来看。要测试它,你实际上需要执行到实际的容器(或来自主机的代理),这是常见的混淆点。只是为了安全的测试服务:实际容器内的端口可访问性,而不是来自主服务器。
  • 最后,为了模仿容器间网络的docker-compose设置,您不需要公开NodePort或其他任何东西。 kubernetes中的服务层将负责DNS处理。 NodePort有不同的意图。

我需要将内部端口暴露给某个NodePort。这样的服务配置怎么样?

你是一个很好的轨道,这里是nice overview让你入门,并提供与你的问题相关的参考如下:

apiVersion: v1
kind: Service
metadata:  
  name: my-nodeport-service
selector:    
  app: my-app
spec:
  type: NodePort
  ports:  
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30036
    protocol: TCP

编辑:请举例说明如果容器单独缩放,service.yaml将如何显示?

  • 第一个是,例如,api服务器,我们称之为svc-my-api,它将使用标记为app: my-api的pod并与pod的端口80进行通信,并且可以被其他pod(在相同的命名空间中)作为主机访问:svc-my-api和port :8080 apiVersion: v1 kind: Service metadata: name: svc-my-api labels: app: my-api spec: selector: app: my-api ports: - protocol: TCP port: 8080 targetPort: 80
  • 第二个是,比如,mysql服务器,我们称之为svc-my-database。假设来自api pod的容器(由以前的服务覆盖)想要访问数据库,他们将使用host:svc-my-database和port:3306apiVersion: v1 kind: Service metadata: name: svc-my-database labels: app: my-database spec: selector: app: my-database ports: - name: http protocol: TCP port: 3306 targetPort: 3306

1
投票

1.-您可以向pod资源(或任何其他将要创建pod的参数)添加一些参数,如下所示:

...
spec:
  hostname: foo-{1..4}        #keep in mind this line
  subdomain: bar              #and this line
  containers:
  - image: busybox
...

注意:所以想象一下你刚刚创建了4个pods,主机名为foo-1, foo-2, foo-3 and foo-4。这些是独立的豆荚。你不能做foo- {1..4}。所以这只是为了演示目的。

如果您现在创建一个与子域同名的服务,则可以通过hostname.service-name.namespace.svc.cluster.local从群集中的任何位置访问该pod。

例:

apiVersion: v1
kind: Service
metadata:
  name: bar     #my subdomain is called "bar", so is this service
spec:
  selector:
    app: my-app
  ports:
  - name: foo
    port: 1234
    targetPort: 1234

现在,假设我的pod中有标签app: my-app,因此该服务正确定位它们。

此时,查看发生了什么(从集群内的任何pod):

/ # nslookup foo-1.bar.my-namespace.svc.cluster.local
Server:    10.63.240.10
Address 1: 10.63.240.10 kube-dns.kube-system.svc.cluster.local

Name:      foo-1.bar.my-namespace.svc.cluster.local
Address 1: 10.60.1.24 foo-1.bar.my-namespace.svc.cluster.local

2.-你问题的第二部分几乎是正确的。这是一个NodePort服务:

apiVersion: v1
kind: Service
metadata:
  name: svc-nodeport
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: my-app
  type: NodePort

此服务在端口80上运行,因此可以在群集内的端口80上访问它。它会将端口映射到节点上超过30000的随机端口。现在,来自外部世界的节点的端口30001(例如)上可以使用相同的服务。最后,它会将请求转发到容器的端口8080。

© www.soinside.com 2019 - 2024. All rights reserved.