Kubernetes 的外部访问方式
前言
我们知道在 K8s 集群内部,由于 pod 的不可靠性引入了 service 的概念,将提供相同服务若干副本的 pod 通过标签创建一个 service ,集群内部通过访问该 service 通过 Endpoint 负载均衡到 pod 来实现服务请求。
那么 K8s 如何提供外部访问方式呢?
NodePort
每个集群节点都会在节点上打开一个端口,并将在端口上接受到的流量重定向到基础服务,可以通过所有节点的专用端口访问。
如图,可以通过所有 Node 的该 Port 访问
使用
创建一个服务并将其类型设置为 NodePort,通过创建 NodePort 服务,可以让 K8s 在所有节点上保留一个端口,将传入的连接转发给服务部分的 pod。
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort # 类型 NodePort
ports:
- port: 80 # Pod 端口
targetPort: 8080 # ClusterIP Port
nodePort: 30080 # 外部访问 NodePort,不写会随机
selector:
app: nginx2
LoadBalancer
LoadBalancer 本质上来说是 NodePort 的扩展,通常需要在支持自动提供负载均衡器的云基础架构上运行。
使用
创建服务后,通过 external-ip 来提供访问服务。
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: LoadBalancer # 类型 LoadBalancer
ports:
- port: 80 # Pod 端口
targetPort: 80 # ClusterIP Port
selector:
app: nginx2
Ingress
引入 Ingress 的一个重要原因是每个 LoadBalancer 服务都需要自己的负载均衡器,以及独立的公有 IP 地址,而 Ingress 只需要一个公网 IP 就可以为许多服务提供访问。当客户端向 Ingress 发送 HTTP 请求时,Ingress 会根据请求的主机名和路径决定请求转发到的服务;
要想 Ingress 资源正常工作,必须要有 Ingress 控制器在集群中运行,可以选择不同的 Ingress 控制器,如:Nginx/Envoy/Treafik/Kong,或一些公有云提供的服务。
使用
功能迭代较快,下面提供 k8s 版本 v1.17.2,使用 nginx 作为 ingress-controller
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress-1
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # (1)
spec:
rules:
- host: test.example.com # (2)
http:
paths:
- path: /foo # (3)
backend:
serviceName: nginx-service # (4)
servicePort: 80
- path: /bar
backend:
serviceName: nginx-service2
servicePort: 80
(1) nginx 作为 controller 时需要的注解,路径匹配说明详情见https://kubernetes.io/zh/docs/concepts/services-networking/ingress/
(2) 访问的主机名
(3) 路径
(4) 对应的服务
创建 Ingress 资源,当访问 test.example.com/foo 时,转到 nginx-service 服务,且端口为 80;当访问 test.example.com/bar 时,转到 nginx-service2 服务,且端口为 80.
*k8s v18 后,需要多加入 pathType 选项,如 Prefix,Exact。
Port Forward
除了上述几种提供外部访问 pod 的方式,额外描述一种在调试时快速访问 pod 的方法:
通过 kubectl port-forward 命令,它可以在本机上开启一个转发端口,间接转发到 K8s 内部的某个 Pod 的端口上。这种方式是TCP转发,不限于HTTP。
kubectl port-forward test2-nginx 8888:80 --address 0.0.0.0 (绑定到0.0.0.0)