Kubernetes(三) 如何从外部访问服务
source link: https://www.tuicool.com/articles/aaiMFvb
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
目录
- Kubernetes(三) 如何从外部访问服务
Kubernetes(三) 如何从外部访问服务
Kubernetes教程之对外暴露服务
文章地址: [ https://blog.piaoruiqing.com/blog/2019/10/20/kubernetes如何从外部访问服务/ )
前言
通过前文的讲解, 《跟着官方文档从零搭建K8S》 、《应用部署》相信读者已经对Kubernetes安装及部署应用有了一定的了解. 接下来, 本文将针对如何将服务暴露给外部进行讲解.
阅读这篇文章你能收获到:
- 了解Kubernetes暴露服务的几种方案及其优缺点.
阅读本文你需要:
- 了解基本的Kubernetes命令.
- 有一个Kubernetes环境
将服务暴露给外部客户端的几种方式
- 通过
port-forward
转发, 这种方式在之前的文章中有提到过, 操作方便、适合调试时使用, 不适用于生产环境 . - 通过
NodePort
, 此时集群中每一个节点(Node)都会监听指定端口, 我们通过任意节点的端口即可访问到指定服务. 但过多的服务会开启大量端口难以维护. - 通过
LoadBalance
来暴露服务.LoadBalance(负载均衡 LB)
通常由云服务商提供, 如果云环境中不提供LB服务, 我们通常直接使用Ingress
, 或使用MetalLB
来自行配置LB. - 通过
Ingress
公开多个服务.Ingress
公开了从群集外部到群集内services
的HTTP和HTTPS路由. 流量路由由Ingress
资源上定义的规则控制. 在云服务商不提供LB服务的情况下, 我们可以直接使用Ingress
来暴露服务. (另外, 使用LB + Ingress
的部署方案可以避免过多LB应用带来的花费).
准备
在开始之前, 笔者已经创建好了测试应用, 代码过长此处略去, 详见 附录[1] 和 附录[2]
我们通过 kubectl get pods
查看pod列表.
指的一提的是, 我们可以通过 --namespace
参数查看指定命名空间的pod列表, 也可以通过 --all-namespaces
来查看全部命名空间的pod列表.
由于没有指定命名空间,所以应用被放到 default
中了.
[root@nas-centos1 k8s-test]# kubectl get pods --namespace default NAME READY STATUS RESTARTS AGE k8s-test-578b77cd47-sw5pd 1/1 Running 0 6m29s k8s-test-578b77cd47-v6kmp 1/1 Running 0 6m29s
port-forward
port-forward
这种方式访问pod, 可以指定pod实例, 简单方便, 很适合调试之用.
通过 kubectl port-forward
来配置转发:
[root@nas-centos1 k8s-test]# kubectl port-forward --address 0.0.0.0 k8s-test-578b77cd47-sw5pd 9999:8080 Forwarding from 0.0.0.0:9999 -> 8080
此时, 我们可以通过通过访问宿主机的 9999
端口来访问到 k8s-test-578b77cd47-sw5pd
的 8080
端口.
/k8s-test/timestamp
是该示例应用唯一一个api, 用于获取当前时间戳
[root@nas-centos1 k8s-test]# curl http://10.33.30.95:9999/k8s-test/timestamp 1571151584224
[版权声明]
本文发布于朴瑞卿的博客, 允许非商业用途转载, 但转载必须保留原作者朴瑞卿 及链接: https://blog.piaoruiqing.com .
如有授权方面的协商或合作, 请联系邮箱: [email protected] .
NodePort
集群中每一个节点(Node)都会监听指定端口, 我们通过任意节点的端口即可访问到指定服务. 但过多的服务会开启大量端口难以维护.
参考文档: https://kubernetes.io/docs/concepts/services-networking/service/#nodeport
创建一个 Service
, 并指定其类型为 NodePort
.
k8s-test-service.yaml
apiVersion: v1 kind: Service metadata: name: k8s-test-service spec: selector: app: k8s-test env: test ports: - port: 80 # 服务端口, 内部可访问 targetPort: 8080 # 目标端口, 此处指的是pod的8080端口 nodePort: 30080 # 节点端口, 外部可访问 protocol: TCP type: NodePort
执行 kubectl apply -f k8s-test-service.yaml
发布这个Service.
通过 kubectl get services
可查看Service列表如下:
[root@nas-centos1 k8s-test]# kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-test-service NodePort 10.244.234.143 <none> 80:30080/TCP 8s kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 32d
我们可以看到, 30080端口已经被绑定到该服务的80端口.
尝试通过node节点来访问应用:
[root@nas-centos3 ~]# curl http://10.33.30.94:30080/k8s-test/timestamp 1571152525336
LoadBalance
参考文档:
LoadBalance(负载均衡 LB)
通常由云服务商提供. 如果环境不支持LB, 那么创建的LoadBalance将始终处于 <pending>
状态:
[root@nas-centos1 k8s-test]# kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-test-service LoadBalancer 10.244.29.126 <pending> 80:32681/TCP 13s kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 33d
如果想要在本地开发环境测试LB, 我们可以选择 MetalLB . 它是一个负载均衡实现. 安装方式此处不进行展开, 可参考 官方文档
当我们的环境支持LB时, 我们可以创建如下Service, 来暴露服务:
apiVersion: v1 kind: Service metadata: name: k8s-test-service spec: selector: app: k8s-test env: test ports: - port: 80 # 服务端口 targetPort: 8080 # 目标端口, 此处指的是pod的8080端口 protocol: TCP type: LoadBalancer
执行 kubectl apply -f k8s-test-lb.yaml
命令发布配置. 此时可以查看到Service已经有了EXTERNAL-IP(10.33.30.2). 如下:
[root@nas-centos1 k8s-test]# kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-test-service LoadBalancer 10.244.151.128 10.33.30.2 80:31277/TCP 2s kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 33d
尝试通过LB的IP来访问应用, 如下:
[root@nas-centos1 k8s-test]# curl http://10.33.30.2/k8s-test/timestamp 1571235898264
Ingress
Ingress
公开了从群集外部到群集内 services
的HTTP和HTTPS路由. 流量路由由 Ingress
资源上定义的规则控制.
参考文档: https://kubernetes.github.io/ingress-nginx/deploy/
我们使用ingress controller的nginx实现来进行测试. 首先下载部署文件:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
编辑文件 vim mandatory.yaml
, 加入以下内容:
template: spec: hostNetwork: true
-
hostNetwork
: 开启hostNetwork, 可以使ingress绑定到主机的80和443端口. -
访问ingress有多种方式, (1). 通过hostNetwork直接绑定到80和443端口, (2). 通过NodePort在Node上暴露端口(但这种方式只能绑定固定范围的端口, 默认值 30000-32767), (3). 通过LoadBalance, 这种方式和NodePort其实都是通过Service来暴露, 只不过是Service的不同类型.
-
mandatory.yaml中
template
只有一个, 很好找. (tips: 在vim中可以用/
进行查找). -
Ingress Controller
: 是一个反向代理程序, 它负责解析 Ingress 的反向代理规则. -
Ingress
: Ingress 是反向代理规则. 不要混淆Ingress Controller
和Ingress
的概念.
发布完成后, 我们创建一个 Ingress
来测试, 内容如下:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: test-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /k8s-test spec: rules: - http: paths: - path: /k8s-test backend: serviceName: k8s-test-service servicePort: 80
尝试访问:
[root@nas-centos1 ingress]# curl http://10.33.30.94/k8s-test/timestamp 1571321623058
小结
通常地, 我们会考虑 LoadBalance
和 Ingress
配合使用. 一方面是只是用LB会产生大量的花费, 另一方面大量的LB同样会提高维护成本. 而LB配合Ingress使用, 通过不同的path来区分服务能达到很棒的效果. (这里和通过Nginx来暴露多个服务的原理基本相同)
参考文献
附录
[1] Deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: k8s-test labels: app: k8s-test spec: replicas: 2 template: metadata: name: k8s-test labels: app: k8s-test env: test spec: containers: - name: k8s-test image: registry.cn-hangzhou.aliyuncs.com/piaoruiqing/k8s-test:0.0.1 imagePullPolicy: IfNotPresent ports: - name: http-port containerPort: 8080 imagePullSecrets: - name: docker-registry-secret restartPolicy: Always selector: matchLabels: app: k8s-test
[2] K8sTestApplication.java
/** * @author piaoruiqing * @description: k8s test * @date: 2019/09/22 10:01 * @since JDK 1.8 */ @RestController @RequestMapping(value = "/k8s-test") @SpringBootApplication public class K8sTestApplication { /** * get timestamp * @return */ @GetMapping(value = "/timestamp") public ResponseEntity<?> getTimestamp() { return ResponseEntity.ok(System.currentTimeMillis() + "\n"); } public static void main(String[] args) { SpringApplication.run(K8sTestApplication.class, args); } }
推荐阅读:
© 2019,朴瑞卿.
[版权声明]
本文发布于朴瑞卿的博客, 允许非商业用途转载, 但转载必须保留原作者朴瑞卿 及链接: https://blog.piaoruiqing.com . 如有授权方面的协商或合作, 请联系邮箱: [email protected] .
欢迎关注公众号: (代码如诗)
相关
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK