如何从 Kubernetes 集群外访问集群内的容器服务

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

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

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来访问后端服务

展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java