在服务容器化后用kubernetes进行编排时,针对kubernetes中服务的访问,流量暴露,通常有一些方案,本文就一些个人经验做了一些总结以及简单介绍

通过 kube-proxy 进行代理

在我们进行开发测试时,或者一些简单的个人测试时,我们可以通过kubectl port-forward 启动一个代理程序代理目标服务至该命令执行的宿主机端口进行访问测试,如果宿主机具备公网ip,并且代理的监控地址设置为0.0.0.0,就可以实现公网访问了,kubectl port-forward可以代理单个pod,deployment以及service,我们通过kubectl port-forward --help 查看命令帮助手册,可以很清楚的看到此代理方式,如下

Forward one or more local ports to a pod. This command requires the node to have 'socat' installed.

 Use resource type/name such as deployment/mydeployment to select a pod. Resource type defaults to 'pod' if omitted.

 If there are multiple pods matching the criteria, a pod will be selected automatically. The forwarding session ends
when the selected pod terminates, and rerun of the command is needed to resume forwarding.

Examples:
  # Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod
  kubectl port-forward pod/mypod 5000 6000

  # Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the
deployment
  kubectl port-forward deployment/mydeployment 5000 6000

  # Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the service
  kubectl port-forward service/myservice 5000 6000

  # Listen on port 8888 locally, forwarding to 5000 in the pod
  kubectl port-forward pod/mypod 8888:5000

  # Listen on port 8888 on all addresses, forwarding to 5000 in the pod
  kubectl port-forward --address 0.0.0.0 pod/mypod 8888:5000

  # Listen on port 8888 on localhost and selected IP, forwarding to 5000 in the pod
  kubectl port-forward --address localhost,10.19.21.23 pod/mypod 8888:5000

  # Listen on a random port locally, forwarding to 5000 in the pod
  kubectl port-forward pod/mypod :5000

Options:
      --address=[localhost]: Addresses to listen on (comma separated). Only accepts IP addresses or localhost as a
value. When localhost is supplied, kubectl will try to bind on both 127.0.0.1 and ::1 and will fail if neither of these
addresses are available to bind.
      --pod-running-timeout=1m0s: The length of time (like 5s, 2m, or 3h, higher than zero) to wait until at least one
pod is running

Usage:
  kubectl port-forward TYPE/NAME [options] [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]

Use "kubectl options" for a list of global command-line options (applies to all commands).

值得注意的是执行代理时,–address参数未指定时,默认代理至宿主机的回环地址127.0.0.1
以下进行简单测试:
我们启动一个nginx pod

kind: Pod
apiVersion: v1
metadata:
  name: testv1
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
      - containerPort: 80

使用kube prometheus监控集群以外kube export kubectl port-forward_cloud native


我们看到此nginx pod被调度至集群的一个node节点,我们甚至可以在master节点代理此pod(基于跨节点的pod通信),我们将此pod 80端口代理至宿主机的8888端口

使用kube prometheus监控集群以外kube export kubectl port-forward_kubernetes_02


我们访问该宿主机8888端口等同于直接访问该pod

NodePort 方式

最为常用还是NodePort方式,将 K8s 中 service 的类型设置为 NodePort 方式,会得到一个端口范围在 30000-32767 内的宿主机端口,同样宿主机具有公网 IP 就可以实现对服务的暴露,访问该端口即可向下对相同业务的一组pod进行负载均衡。
缺点:
1.通常一组相同业务的的pod集通过一个service nodeport至宿主机端口,我们知道当一个service 设置为nodeport后会在k8s 所有node节点开启此端口,当我们的业务较多时,k8s集群具有一定规模时,需要开启更多的service来访问业务时,宿主机端口管理可想而知是灾难性的
2. 次访问方式为IP+端口的四层访问模式,无法进行ssl证书的安装卸载
3. 我们访问单个node的nodeport端口也无法实现高可用

使用kube prometheus监控集群以外kube export kubectl port-forward_cloud native_03

四层LoadBalancer+NodePort 方式

针对每一个service的nodeport端口我们在上层增加一个四层负载的LoadBalancer 端口,LoadBalancer的一个端口负载均衡至一个service nodeport 端口的多个节点,LoadBalancer自身也是实现高可用,这样就可以实现nodeport服务访问的高可用。公有云环境下,图中的LoadBalancer可以使用云厂商的负载均衡服务来实现
缺点:
1.通常一组相同业务的的pod集通过一个service nodeport至宿主机端口,我们知道当一个service 设置为nodeport后会在k8s 所有node节点开启此端口,当我们的不用业务较多时,k8s集群具有一定规模时,需要开启更多的service来访问业务时,宿主机端口管理可想而知是灾难性的
2. 每一个nodeport端口需要占用一个LoadBalancer端口
3. 最上层的访问方式仍为IP+端口的四层访问模式,无法进行ssl证书的安装卸载

使用kube prometheus监控集群以外kube export kubectl port-forward_kubernetes_04

七层LoadBalancer+NodePort 方式

借助七层LoadBalancer实现域名访问,通过七层LoadBalancer的单个访问路径转发至单个service nodeport端口的多个节点进行负载均衡实现一个域名端口对应多个service端口,并且七层负载均衡可以实现ssl证书的安装卸载,nodeport服务的访问也可实现高可用。七层LoadBalancer本身实现高可用。公有云环境下,图中的LoadBalancer可以使用云厂商的负载均衡服务来实现,一般公有云服务商的负载均衡服务均实现了四层以及七层的负载均衡

缺点:

1.通常一组相同业务的的pod集通过一个service nodeport至宿主机端口,我们知道当一个service 设置为nodeport后会在k8s 所有node节点开启此端口,当我们的不用业务较多时,k8s集群具有一定规模时,需要开启更多的service来访问业务时,宿主机端口管理可想而知是灾难性的

使用kube prometheus监控集群以外kube export kubectl port-forward_cloud native_05

Ingress方式

在k8s中存在ingress资源实现单个域名根据不同访问路径转发至不同service(不需要nodeport),我们不需要在node节点暴露service端口。ingress只是一个转发规则的声明式资源,真正接受访问的还是实现了七层负载的一些ingress-Controller,ingress-Controller的业界实现有很多,比较有名以及常用的还是我们熟悉的Ingress-nginx,其实Ingress-nginx底层就是一个nginx,Ingress-nginx属于集群资源不属于某个namespace,Ingress-nginx能够watch ingress的动态变化,将ingress配置最终转化为nginx localtion配置打入nginx实现七层负载均衡,ingress-Controller的业界实现也都可以实现ssl证书的安装卸载,所以我们的请求还是需要访问 Ingress-Controller 的 NodePort 例如 Ingress-nginx 的 Controller 的 Service 的 NodePort,针对具体的业务域名一般不会带端口,我们根据路径来区分不同业务。图中的Ingress-nginx我们也可以通过直接部署一个nginx来实现,nginx的location中转发地址填写相关service的k8s的全域名即可,可以达到和 Ingress-nginx一样的效果
缺点:
1.虽然我们的服务不在node节点暴露端口,我们的域名总是指向单个node即可实现服务访问,上层无法实现高可用

使用kube prometheus监控集群以外kube export kubectl port-forward_docker_06

七层LoadBalancer+Ingress方式

在ingress的上层加一层七层LoadBalancer,七层LoadBalancer的http以及https端口转发至Ingress-Controller nodport的多个节点,域名以及ssl证书的安装配置都交给七层LoadBalancer实现,这样即可实现Ingress-Controller的高可用访问,公有云环境下,图中的LoadBalancer可以使用云厂商的负载均衡服务来实现

使用kube prometheus监控集群以外kube export kubectl port-forward_nginx_07


通常云厂商的LB服务均可实现四层以及七层负载均衡以及ssl证书安装卸载,图中可以在私有化环境中实现,公有云环境完全可以购买云厂商的LB服务减少运维维度。

以上为一些结合自身经验实际使用的一些总结,各种方式都有相应的优劣性,还需要我们结合实际场景选择最为合适的一种。