如何暴露Pod中的服务到Kubernetes集群外?

云计算 云原生
在Pod的yaml定义文件中配置该选项后,Pod就使用宿主机的网络栈,这样和直接访问运行在宿主机上的服务没有什么区别。

使用Kubernetes集群运行服务,提供服务的应用运行在Pod中。为了在集群外访问应用,有两类方式:一类是Pod自身实现;其次是依赖其他组件。

  • Pod自身暴露服务

1、hostNetwork:true

在Pod的yaml定义文件中配置该选项后,Pod就使用宿主机的网络栈,这样和直接访问运行在宿主机上的服务没有什么区别,使用“宿主机IP+端口”的方式访问运行在Pod中的服务,比如下面的Pod定义文件,

apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx:1.23.1
ports:
- containerPort: 80

执行后,登录容器运行的宿主机,可以看到有服务监听在80端口,

监听在宿主机的80端口

访问也是没有问题的(192.168.52.132是宿主机的IP)。

服务访问

如果Pod重启,可能会被调度到别的宿主机,这样的话,访问IP也需跟着变动,还有要防止端口冲突,如果已经有服务占用了宿主机的端口,新的Pod将不能启动。

2、hostPort

将上面Pod的yaml文件稍作修改,增加最后一行,去掉“hostNetwork: true”。

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

相对于第一种,可以灵活地配置对外暴露的端口。有一点需要注意,因为“hostPort”方式,服务监听在容器的网络栈,宿主机在防火墙上做了转发,所以查询宿主机8080端口,发现并没有服务监听,

监听端口

查看防火墙,宿主机做了端口转发。

Pod的IP

宿主机上执行DNAT

这种方式和第一种方式有相同的缺点,容器重启可能会被调度到其他的主机上。不能在一台宿主机上运行同样的Pod,除非人为调整Pod对外暴露的端口。

  • 依赖组件暴露服务

上面两种方法都是依赖Pod自身的资源定义暴露服务到集群外,下面两种方法依赖其他Kubernetes资源实现服务的暴露。

3、NodePort

“NodePort”是Kubernetes中“Service”资源的一个属性,默认“Service”实现集群内服务访问,当增加“NodePort”时,服务便可以在集群外被访问到,Kubernetes默认会从宿主机的端口30000-32767之间选择一个来提供访问,可以人为指定。

一个示例yaml文件。

apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.23.1
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30000
targetPort: 80
selector:
name: nginx

应用该yaml文件后,便可以在集群外通过“主机IP+30000”的方式访问服务。

nodePort方式访问服务

为了实现高可用,可以部署haproxy,后端为多个集群宿主机暴露的服务,这样可以提高可用性。“nodePort”方式的Service工作原理是这样:当流量进入宿主机暴露的30000端口后,会被转发给“Service”的“Cluster IP+端口”,然后通过Iptables(也有可能是ipvs,具体看实现)转发到对应的Pod。

4、Ingress

使用Ingress暴露服务的方式在生产环境中使用的比较多。Ingress API资源对象在kubernetes有内置,但要使用这个对象,需要安装“Controller”。可选的第三方“Controller”有很多,这里选择“Nginx Ingress controller”。(安装过程不涉及)。

示例yaml:

apiVersion: v1
kind: Pod
metadata:
namespace: test
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.23.1
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
namespace: test
name: nginx
spec:
ports:
- port: 8080
targetPort: 80
selector:
name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: test
name: nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: nginx.example.cc
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: nginx
port:
number: 8080

因为笔者的测试环境Ingress Controller使用nodePort方式运行,对外暴露的HTTP端口为31763。

ingress controller暴露的端口

使用Ingress资源定义中配置的域名访问部署的服务。

访问服务

生产环境可以修改Ingress controller网络的工作方式,比如使用“hostPort”,让其监听在80端口。

有一点需要注意,不同于“nodePort”引导流量到Service的Cluster IP,Ingress Controller会将集群外用户的流量直接送到Pod监听的端口,这样效率会高不少。

总结

除了以上介绍的四种暴露服务的方式,还可以采用“LoadBalancer”,它需要依赖云厂商,如果你的Kubernetes集群部署在公有云上,可以根据实际配置。

责任编辑:姜华 来源: 今日头条
相关推荐

2022-06-21 14:46:52

KubernetesPODMultus

2022-06-27 19:16:12

KubernetesK8s 集群

2022-07-08 14:17:18

Kubernetes集群高可用Linux

2020-04-26 11:16:46

KubernetesPodLinux

2022-08-09 09:10:43

Kubernetes容器

2022-07-18 14:45:22

Kubernetes暴露方案

2021-12-02 08:00:00

2022-07-04 09:13:54

KubernetespodLinux

2022-08-30 11:53:36

Kubernetes网络排查

2022-03-24 07:44:41

OPA安全策略Rego

2022-05-16 08:27:20

KubernetePodLinux

2022-07-07 10:47:16

2020-04-02 15:10:57

Kubernetes集群安全

2022-07-11 09:46:43

Kubernetes开源Linux

2022-09-05 09:25:53

KubernetesService

2022-03-03 08:42:10

NodePortServiceKubernetes

2022-04-15 15:56:30

云原生容器

2021-11-22 08:00:00

Kubernetes容器集群

2022-04-11 16:12:25

KubernetesPod

2021-11-22 16:21:28

点赞
收藏

51CTO技术栈公众号