容器网络跟机房网络不在一个网络平面,一般不能互通,然则在混合环境中如何从 Kubernetes 集群外去访问 Kubernetes 集群里面的服务呢?本文将介绍该需求的多种实现方式。

本文由作者授权发布,未经许可,请勿转载。

作者:李岚清,网易杭州研究院云计算技术中心资深工程师

容器化是一个逐步推进的过程,不是一蹴而就的。肯定是有一部分业务部署在 Kubernetes 中,有一部分业务还是部署在裸机或者虚拟机上。那么我们如何从 Kubernetes 集群外去访问 Kubernetes 集群里面的服务呢?或者说,我们如何将 Kubernetes 集群内的服务暴露到 Kubernetes 集群外?

之所以存在这个问题,一个核心的原因是容器网络跟机房网络不在一个网络平面,一般情况是不能互通的(只能单向通,即容器可以通过 SNAT 访问机房网络)。

网易杭研自 2015 年就开始基于 Kubernetes 研发和打磨轻舟云原生平台,其中包括容器云组件,并曾探索容器与IaaS深度融合(以实现最优性能)的技术路线,对类问题此经验丰富。本文将基于网易轻舟团队研发经验,介绍如何通过多种方式来实现该需求。

HostNetwork

首先想到的最简单的方式是,将pod设置为hostNetwork的,即直接使用宿主机网络。hostNetwork类型的pod与宿主机共享网络协议栈。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  hostNetwork: true
  containers:
    - name: nginx
      image: nginx

但是hostNetwork类型的pod也存在多方面的缺点:

  • 假如pod重建,pod可能会调度到其他node上,这个时候pod的ip就改变了,那么客户端的配置很可能需要更改
  • 因为与宿主机共享网络协议栈,所以需要考虑端口冲突的问题。如果hostNetwork类型的pod太多,端口冲突将会非常常见,运维成本也会变高

HostPort

我们可以将pod中某个容器的端口映射到宿主机端口上,然后通过访问宿主机ip+宿主机端口来访问pod。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - containerPort: 8080
          hostPort: 8080

hostPort存在跟hostNetwork pod一样的缺点:

  • 假如pod重建,pod可能会调度到其他node上,这个时候node的ip就改变了,那么客户端的配置很可能需要更改
  • 因为需要把容器的端口映射到宿主机上,所以需要考虑端口冲突的问题

NodePort service

我们可以通过创建NodePort类型的Service来将pod暴露到 Kubernetes 集群外。当我们创建一个NodePort类型的service时, Kubernetes 会自动分配一个node port,并且会在所有的k8s node上创建相应的iptables规则,用户可以通过访问任一k8s node的ip+node port,即可访问后端服务。

(1)在 Kubernetes 集群中部署后端服务

# kubectl create deployment echoserver --image=cilium/echoserver:1.10.2

# kubectl get pods -o wide | grep echo
echoserver-64b895b74f-pl2dx                                     1/1     Running     0          26s   10.120.49.168   pubt2-k8s-for-iaas4.dg.163.org   <none>           <none>

(2)创建NodePort类型的service,并且关联上述pod:

# kubectl expose deployment echoserver --name=echoserver --type=NodePort --port=80 --target-port=8080
service/echoserver exposed
# kubectl get svc echoserver
NAME         TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
echoserver   NodePort   10.178.7.102   <none>        80:32712/TCP   3m48s

(3)尝试在 Kubernetes 集群外访问echoserver

# 随便挑选一个node作为跳板

# curl ${node}:32712

NodePort类型的service也有一些缺点:

  • 每当创建一个NodePort类型的service, Kubernetes 会自动分配一个端口,并且在所有的k8s node上配置针对该端口的dnat规则
  • 客户端需要考虑访问哪个node的ip,假如选择的这个node宕机了怎么办?

LoadBalancer service

LoadBalancer service 是一个比较理想的选择。这个需要cloud-provider的支持,各个云服务提供商基于自己的LB服务对接实现 Kubernetes LoadBalancer service。

当用户创建LoadBalancerservice时,cloud-controller-manager会自动创建一个LB实例,分配一个VIP,并且会自动维护后端pod列表和LB的配置更新。然后我们可以访问VIP:port来访问后端服务

# kubectl expose deployment echoserver --name=echoserver --type=LoadBalancer --port=80 --target-port=8080
service/echoserver exposed

# kubectl get svc echoserver
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
echoserver   LoadBalancer   10.178.10.19   10.194.73.231   80:33719/TCP   7s

# curl 10.194.73.231
...

轻舟LoadBalancer service支持外网、机房网和VPC私有网三种类型。使用方便,功能完善,有云服务商提供sla保证,缺点就是存在成本。

Ingress

用户也可以通过创建Ingress资源来将服务暴露到 Kubernetes 集群外,具体使用方式,我们会在后续文档中专门介绍,在此不再赘述。

参考文档

Accessing Kubernetes Pods from Outside of the Cluster

作者简介

李岚清,网易杭州研究院云计算技术中心轻舟容器编排团队资深系统开发工程师,具有多年Kubernetes开发、运维经验,主导实现了容器网络管理、容器混部等生产级核心系统研发,推动网易集团内部电商、音乐、传媒、教育等多个业务的容器化。

活动预告

直播:Service Mesh 技术在美团的落地和挑战

  • 讲师:刘世朋,美团基础架构部开发工程师
  • 时间:6月11日 19:00-20:00 在线直播
  • 议题介绍:主要介绍 Service Mesh 理念在美团的实践和落地。具体包括与美团已有服务治理系统的融合、与容器基础设施平台的融合、性能优化指标、运维监控实践和低成本业务接入等几个方面的工作。
  • 了解详情&报名直播预告:Service Mesh 技术在美团的落地和挑战

推荐阅读

Logo

开源、云原生的融合云平台

更多推荐