容器化是一个逐步推进的过程,不是一蹴而就的。肯定是有一部分业务部署在 Kubernetes 中,有一部分业务还是部署在裸机或者虚拟机上。那么我们如何从 Kubernetes 集群外去访问 Kubernetes 集群里面的服务呢?或者说,我们如何将 Kubernetes 集群内的服务暴露到 Kubernetes 集群外?
之所以存在这个问题,一个核心的原因是容器网络跟机房网络不在一个网络平面,一般情况是不能互通的(只能单向通,即容器可以通过 SNAT 访问机房网络)。
首先想到的最简单的方式是,将pod设置为hostNetwork的,即直接使用宿主机网络。hostNetwork类型的pod与宿主机共享网络协议栈。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx
但是hostNetwork类型的pod也存在多方面的缺点:
我们可以将pod中某个容器的端口映射到宿主机端口上,然后通过访问宿主机ip+宿主机端口来访问pod。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 8080
hostPort: 8080
hostPort存在跟hostNetwork pod一样的缺点:
我们可以通过创建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也有一些缺点:
LoadBalancer service 是一个比较理想的选择。这个需要cloud-provider的支持,各个云服务提供商基于自己的LB服务对接实现 Kubernetes LoadBalancer service。
当用户创建LoadBalancerservice时,cloud-controller-manager会自动创建一个LB实例,分配一个VIP,并且会自动维护后端pod列表和LB的配置更新。然后我们可以访问VIP:port来访问后端服务
本文系作者在时代Java发表,未经许可,不得转载。
如有侵权,请联系nowjava@qq.com删除。