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

时间:2018-06-15 09:26:51

标签: kubernetes

在我的设置中,有一组最初构建为与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: {}`
      

2 个答案:

答案 0 :(得分:2)

  

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

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

  • IF 您要将容器缩放在一起,然后将它们放在同一个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和端口: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的容器(由以前的服务覆盖)想要访问数据库,他们将使用主机:svc-my-database和端口:3306

    apiVersion: 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)

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

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

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

如果您现在使用同名创建子域的服务,则可以通过hostname.service-name.namespace.svc.cluster.local从群集中的任何位置访问该广告连播

示例:

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,因此服务正确定位它们。

此时,查看会发生什么(来自群集内的任何窗格):

/ # 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。