怎样从公网访问k8s服务
默认情况下,k8s创建的服务是无法对公网提供访问的,如果要从公网访问k8s服务,一般有三种方式,NodePort、LoadBalancer、Ingress,下面简单介绍NodePort、LoadBalancer,着重讲解Ingress
本文使用的deployment同官方教程nginx-deployment,图片是从ingress-nginx官方文档拷贝过来借用,如侵必删
NodePort
如上图所示,客户端访问集群内任意机器端口30100,k8s自动将请求转发到对应的服务
- 创建NodePort类型的service(不指定nodeport的情况下,默认从30000-32767中挑选一个端口使用)
1 | kubectl expose deployment nginx-deployment --type="NodePort" --port 80 |
- 查看service
kubectl get svc
,输出如下
1 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE |
- 验证
外部客户端先访问集群内任意节点端口31402,然后节点会转发到与端口关联的k8s内部服务nginx-deployment。
在物理机上访问服务curl http://vm1:31402
,对比在虚拟机如vm1上执行curl http://10.110.255.135
,两者的输出是一致的
- 删除service
1 | kubectl delete svc nginx-deployment |
注意:考虑到线上一般是直接通过域名访问,如果不想在域名后还要添加端口访问服务,如www.noname.io:31402
,那么还需要使用nginx/haproxy建立一个反向代理的网关进行管理
LoadBalancer
如上图所示,客户端的请求抵达LoadBalancer指定的IP(这里的IP有点奇怪,应该是与节点IP同一个CIDR但被保留的IP才对,看下面metallb),然后机器将流量转发到对应的服务
一般情况下,各个云服务厂商有提供专门支持k8s的LoadBalancer,本文依赖的k8s是自建的裸集群(bare-metal),默认不支持LoadBalancer,因此需要先安装metallb
metallb安装
- 下载配置文件,修改image地址,然后使用kubectl执行
1 | kubectl apply -f ./metallb-native.yaml |
- 查看pod运行状态
1 | kubectl get pods -n metallb-system -o wide |
输出如下
1 | NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES |
- 配置IP池
配置IP池用于LoadBalancer分配,注意,要确保这部分IP不要被dhcp分配给其他任何机器
1 | # vi ip-address-pool.yaml |
执行命令kubectl apply -f ip-address-pool.yaml
到这里就创建好了
实践
- 创建LoadBalancer类型的service
1 | kubectl expose deployment nginx-deployment --type="LoadBalancer" --port 80 |
- 查看service
kubectl get svc
,输出如下
192.168.122.20这个地址不是节点IP,而是从IP池里挑选的未被使用的
1 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE |
- 验证
在物理机上访问服务curl -D- http://192.168.122.20 -H 'Host: www.noname.io'
,对比在虚拟机上执行curl -D- http://10.111.110.163
,两者的输出是一致的
- 删除service
1 | kubectl delete svc nginx-deployment |
Ingress
Ingress在整个k8s架构中扮演着集群网关的角色,提供了如负载均衡、SSL终结和基于名称的虚拟托管功能,当然,你可以用在a/b测试、版本升级这种用途,目前支持的协议是http,后续的继任者Gateway提供了更强大的功能,如支持更多协议、流量管理、更灵活的配置等,但这里暂不做过多介绍
Ingress的运行方式有好几种,其中比较常见的是NodePort以及LoadBalancer。其工作原理是:客户端通过NodePort或者LoadBalancer的方式访问ingress,ingress再通过路由转发到指定的k8s内部服务
本文使用的ingress是ingress-nginx,当然,你也可以选择envoy或higress等
ingress-nginx
拷贝文件夹
baremetal
或cloud
,修改deploy.yaml中的image地址执行命令
kubectl apply -k .
查看pod运行状况
1 | kubectl get pods -o wide -n ingress-nginx |
输出如下,前两个是一次性的job,忽略
1 | NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES |
- 查看controller运行状况
1 | kubectl get svc ingress-nginx-controller -n ingress-nginx |
如果你执行的是cloud
配置,也就是LoadBalancer
方式,输出如下
1 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE |
如果你执行的是baremetal
配置,也就是NodePort
方式,输出如下
1 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE |
- 验证
访问ingress地址
LoadBalancer
方式如下
1 | # LoadBalancer如下 |
输出如下
1 | HTTP/1.1 404 Not Found |
到这里,ingress安装完成
实践
- 创建默认类型为ClusterIP的服务(该服务无法在集群外部访问,适合验证我们创建的ingress)
1 | kubectl expose deployment nginx-deployment |
- 查看service
kubectl get svc
,输出如下
1 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE |
- 配置ingress规则
该规则指定www.noname.io的所有流量都转发到nginx-deployment服务
1 | # example-ingress.yaml |
- 验证
访问ingress地址,仅展示LoadBalancer方式
1 | curl -D- http://192.168.122.20 -H 'Host: www.noname.io' |
done
参考文档
3 Ways to Expose Applications Running in Kubernetes Cluster to Public Access
Ingress
在 Minikube 环境中使用 NGINX Ingress 控制器配置 Ingress
Bare-metal considerations
Using Nginx Ingress Controller in Kubernetes bare-metal setup
Using Metal LB on a bare-metal(OnPrem) Kubernetes Setup