22

我有一个运行 2 个 minions 的 kubernetes 集群。目前,我通过 2 个步骤使我的服务可访问:

  1. 启动复制控制器和 Pod
  2. 获取minion IP(使用kubectl get minions)并将其设置为服务的公共 IP。

向公众公开服务的建议做法是什么?我的方法似乎是错误的,因为我对单个 minion IP-s 的 IP-s 进行了硬编码。它似乎也绕过了 kubernetes 服务的负载平衡功能,因为客户端必须直接访问在单个 minions 上运行的服务。

要设置复制控制器和 pod,我使用:

id: frontend-controller
kind: ReplicationController
apiVersion: v1beta1
desiredState:
  replicas: 2
  replicaSelector:
    name: frontend-pod
  podTemplate:
    desiredState:
      manifest:
        version: v1beta1
        id: frontend-pod
        containers:
          - name: sinatra-docker-demo
            image: madisn/sinatra_docker_demo
            ports:
              - name: http-server
                containerPort: 4567
    labels:
      name: frontend-pod

设置服务(获取 minion ip-s 后):

kind: Service
id: frontend-service
apiVersion: v1beta1
port: 8000
containerPort: http-server
selector:
  name: frontend-pod
labels:
  name: frontend
publicIPs: [10.245.1.3, 10.245.1.4]
4

5 回答 5

8

正如我在上面的评论中提到的,createExternalLoadBalancer 是您正在寻找的适当抽象,但不幸的是,它尚未为所有云提供商实现,特别是对于您在本地使用的 vagrant。

一种选择是将集群中所有 Minion 的公共 IP 用于您想要外部化的所有服务。发往该服务的流量将最终到达其中一个 minions,在那里它将被 kube-proxy 进程拦截并重定向到与该服务的标签选择器匹配的 pod。这可能会导致跨网络的额外跃点(如果您登陆的节点上没有本地运行 pod),但对于对网络延迟不太敏感的应用程序,这可能不会引起注意。

于 2015-04-23T04:36:09.820 回答
7

正如罗伯特在他的回复中所说,这是即将推出的东西,但不幸的是尚不可用。

我目前正在我们的数据中心网络上运行 Kubernetes 集群。我有 1 个 master 和 3 个 minions 都在 CentOS 7 virtuals (vcenter) 上运行。我处理这个问题的方法是创建一个专用的“kube-proxy”服务器。我基本上只是在运行 Kube-Proxy 服务(以及用于网络的 Flannel),然后将“公共”IP 地址分配给连接到该服务器的网络适配器。当我说公共时,我的意思是我们本地数据中心网络上的地址。然后,当我创建要在集群外部访问的服务时,我只需将 publicIPs 值设置为 kube-proxy 服务器上的可用 IP 地址之一。当某人或某物试图从集群外部连接到此服务时,它将命中 kube-proxy,然后被重定向到正确的 minion。

虽然这看起来像是一种解决方法,但实际上这与他们提出解决此问题的内置解决方案后我期望发生的情况相似。

于 2015-04-27T00:48:39.783 回答
2

如果您在本地运行集群,我使用的解决方案是使用服务定义中的 nodeport 指令在您的 kubernetes 节点上公开服务,然后使用 HAproxy 轮询到集群中的每个节点。

这是暴露节点端口的样子:

apiVersion: v1
kind: Service
metadata:
  name: nginx-s
  labels:
    name: nginx-s
spec:
  type: NodePort
  ports:
    # must match the port your container is on in your replication controller
    - port: 80
      nodePort: 30000
  selector:
    name: nginx-s

注意:您指定的值必须在为节点端口配置的范围内。(默认:30000-32767)

这会在集群中的每个节点上的给定节点端口上公开服务。然后,我在运行 haproxy 的内部网络上设置了一台单独的机器,并在您要公开的指定节点端口上设置了一个可从外部访问的防火墙。

如果您查看其中一台主机上的 nat 表,您可以看到它在做什么。

root@kube01:~# kubectl create -f nginx-s.yaml
You have exposed your service on an external port on all nodes in your
cluster.  If you want to expose this service to the external internet, you may
need to set up firewall rules for the service port(s) (tcp:30000) to serve traffic.

See http://releases.k8s.io/HEAD/docs/user-guide/services-firewalls.md for more details.
services/nginx-s
root@kube01:~# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-PORTALS-CONTAINER  all  --  anywhere             anywhere             /* handle ClusterIPs; NOTE: this must be before the NodePort rules */
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
KUBE-NODEPORT-CONTAINER  all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL /* handle service NodePorts; NOTE: this must be the last rule in the chain */

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
KUBE-PORTALS-HOST  all  --  anywhere             anywhere             /* handle ClusterIPs; NOTE: this must be before the NodePort rules */
DOCKER     all  --  anywhere            !127.0.0.0/8          ADDRTYPE match dst-type LOCAL
KUBE-NODEPORT-HOST  all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL /* handle service NodePorts; NOTE: this must be the last rule in the chain */

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        anywhere

Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

Chain KUBE-NODEPORT-CONTAINER (1 references)
target     prot opt source               destination
REDIRECT   tcp  --  anywhere             anywhere             /* default/nginx-s: */ tcp dpt:30000 redir ports 42422

Chain KUBE-NODEPORT-HOST (1 references)
target     prot opt source               destination
DNAT       tcp  --  anywhere             anywhere             /* default/nginx-s: */ tcp dpt:30000 to:169.55.21.75:42422

Chain KUBE-PORTALS-CONTAINER (1 references)
target     prot opt source               destination
REDIRECT   tcp  --  anywhere             192.168.3.1          /* default/kubernetes: */ tcp dpt:https redir ports 51751
REDIRECT   tcp  --  anywhere             192.168.3.192        /* default/nginx-s: */ tcp dpt:http redir ports 42422

Chain KUBE-PORTALS-HOST (1 references)
target     prot opt source               destination
DNAT       tcp  --  anywhere             192.168.3.1          /* default/kubernetes: */ tcp dpt:https to:169.55.21.75:51751
DNAT       tcp  --  anywhere             192.168.3.192        /* default/nginx-s: */ tcp dpt:http to:169.55.21.75:42422
root@kube01:~#

特别是这条线

DNAT       tcp  --  anywhere             anywhere             /* default/nginx-s: */ tcp dpt:30000 to:169.55.21.75:42422

最后,如果您查看 netstat,您可以看到 kube-proxy 正在该端口上侦听并等待该服务。

root@kube01:~# netstat -tupan | grep 42422
tcp6       0      0 :::42422                :::*                    LISTEN      20748/kube-proxy
root@kube01:~#

Kube-proxy 将监听每个服务的端口,并将网络地址转换为容器所在的虚拟子网。(我认为?)我使用了 flannel。


对于一个两节点集群,HAproxy 配置可能与此类似:

listen sampleservice 0.0.0.0:80
    mode http
    stats enable
    balance roundrobin
    option httpclose
    option forwardfor
    server noname 10.120.216.196:30000 check
    server noname 10.155.236.122:30000 check
    option httpchk HEAD /index.html HTTP/1.0

现在可以通过 HAproxy 在端口 80 上访问您的服务。如果您的任何节点出现故障,由于复制控制器,容器将被移动到另一个节点,并且 HAproxy 只会路由到您的活动节点。

我很好奇其他人使用了什么方法,这正是我想出的。我通常不会在堆栈溢出上发帖,所以如果我没有遵循约定或格式正确,我深表歉意。

于 2016-05-05T00:15:37.433 回答
1

这是给MrE的。我在评论区没有足够的空间来发布这个答案,所以我不得不创建另一个答案。希望这可以帮助:

自从发布此回复以来,我们实际上已经远离了 Kubernetes。如果我没记错的话,虽然我真正需要做的就是在专用的 CentOS VM 上运行 kube-proxy 可执行文件。这是我所做的:

首先,我删除了 Firewalld 并将 iptables 放置到位。Kube-proxy 依赖 iptables 来处理其 NAT 和重定向。

其次,你需要安装 flanneld,这样你就可以在与你的 minions 上运行的 Docker 服务相同的网络上拥有一个桥接适配器。

然后我所做的就是为机器上安装的本地网络适配器分配多个 IP 地址。这些将是您在设置服务时可以使用的 IP 地址。这些将是集群外部可用的地址。

一旦这些都处理好,您就可以启动代理服务了。它将连接到 Master,并获取 flannel 网桥网络的 IP 地址。然后它会同步所有的 IPtables 规则,你应该被设置。每次添加新服务时,它都会创建代理规则并在所有 Minion(和您的代理)中复制这些规则。只要您在代理服务器上指定了一个可用的 IP 地址,该代理服务器就会将该 IP 地址的所有流量转发到正确的 minion。

希望这更清楚一点。请记住,虽然我已经有大约 6 个月没有参与 Kubernetes 项目了,所以我不确定自从我离开后发生了什么变化。他们甚至可能具有处理此类事情的功能。如果不是希望这可以帮助您处理好它。

于 2015-12-20T13:16:58.483 回答
0

您可以使用Ingress资源来允许来自 Kubernetes 集群外部的外部连接访问集群服务。

假设你已经部署了一个 Pod,你现在需要一个 Service 资源,例如:

apiVersion: v1 kind: Service metadata: name: frontend-service labels: tier: frontend spec: type: ClusterIP selector: name: frontend-pod ports: - name: http protocol: TCP # the port that will be exposed by this service port: 8000 # port in a docker container; defaults to what "port" has set targetPort: 8000

您需要一个 Ingress 资源: apiVersion: extensions/v1beta1 kind: Ingress metadata: name: frontend-ingress spec: rules: - host: foo.bar.com http: paths: - path: / backend: serviceName: frontend-service # the targetPort from service (the port inside a container) servicePort: 8000 为了能够使用 Ingress 资源,您需要部署一些Ingress 控制器。

现在,只要您知道 Kubernetes 主 IP,您就可以从 Kubernetes 集群外部访问您的应用程序: curl http://<master_ip>:80/ -H 'Host: foo.bar.com'


如果您使用一些 DNS 服务器,您可以添加此记录:foo.bar.com IN A <master_ip>或将此行添加到您的/etc/hosts文件中:<master_ip> foo.bar.com现在您可以运行: curl foo.bar.com


请注意,这样您将始终foo.bar.com使用端口 80 访问。如果您想使用其他端口,我建议使用 NodePort 类型的服务,仅用于那个非 80 端口。无论您使用哪个 Kubernetes VM IP(任何主 IP 或任何从 IP 都可以),它都会使该端口可解析。此类服务的示例: apiVersion: v1 kind: Service metadata: name: frontend-service-ssh labels: tier: frontend spec: type: NodePort selector: name: frontend-pod ports: - name: ssh targetPort: 22 port: 22 nodePort: 2222 protocol: TCP 如果您<master_ip> foo.bar.com的 /etc/hosts 文件中有,那么您可以访问:foo.bar.com:2222

于 2017-03-28T15:25:43.280 回答