暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kubernetes教程之如何从外部访问服务

代码如诗 2019-10-20
162

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
中了.

  1. [root@nas-centos1 k8s-test]# kubectl get pods --namespace default

  2. NAME READY STATUS RESTARTS AGE

  3. k8s-test-578b77cd47-sw5pd 1/1 Running 0 6m29s

  4. k8s-test-578b77cd47-v6kmp 1/1 Running 0 6m29s


port-forward

port-forward
这种方式访问pod, 可以指定pod实例, 简单方便, 很适合调试之用.

通过kubectl port-forward
来配置转发:

  1. [root@nas-centos1 k8s-test]# kubectl port-forward --address 0.0.0.0 k8s-test-578b77cd47-sw5pd 9999:8080

  2. Forwarding from 0.0.0.0:9999 -> 8080

此时, 我们可以通过通过访问宿主机的9999
端口来访问到k8s-test-578b77cd47-sw5pd
8080
端口.

/k8s-test/timestamp
是该示例应用唯一一个api, 用于获取当前时间戳

 

  1. [root@nas-centos1 k8s-test]# curl http://10.33.30.95:9999/k8s-test/timestamp

  2. 1571151584224

NodePort

集群中每一个节点(Node)都会监听指定端口, 我们通过任意节点的端口即可访问到指定服务. 但过多的服务会开启大量端口难以维护.

参考文档: https://kubernetes.io/docs/concepts/services-networking/service/#nodeport

创建一个Service
, 并指定其类型为NodePort
.

k8s-test-service.yaml

  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: k8s-test-service

  5. spec:

  6. selector:

  7. app: k8s-test

  8. env: test

  9. ports:

  10. - port: 80 # 服务端口, 内部可访问

  11. targetPort: 8080 # 目标端口, 此处指的是pod的8080端口

  12. nodePort: 30080 # 节点端口, 外部可访问

  13. protocol: TCP

  14. type: NodePort

执行kubectl apply -f k8s-test-service.yaml
发布这个Service.

通过kubectl get services
可查看Service列表如下:

  1. [root@nas-centos1 k8s-test]# kubectl get services

  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

  3. k8s-test-service NodePort 10.244.234.143 <none> 80:30080/TCP 8s

  4. kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 32d

我们可以看到, 30080端口已经被绑定到该服务的80端口.

尝试通过node节点来访问应用:

  1. [root@nas-centos3 ~]# curl http://10.33.30.94:30080/k8s-test/timestamp

  2. 1571152525336

LoadBalance

参考文档:

  1. https://metallb.universe.tf/

  2. https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer

LoadBalance(负载均衡 LB)
通常由云服务商提供. 如果环境不支持LB, 那么创建的LoadBalance将始终处于<pending>
状态:

  1. [root@nas-centos1 k8s-test]# kubectl get services

  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

  3. k8s-test-service LoadBalancer 10.244.29.126 <pending> 80:32681/TCP 13s

  4. kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 33d

如果想要在本地开发环境测试LB, 我们可以选择MetalLB. 它是一个负载均衡实现. 安装方式此处不进行展开, 可参考官方文档

当我们的环境支持LB时, 我们可以创建如下Service, 来暴露服务:

  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: k8s-test-service

  5. spec:

  6. selector:

  7. app: k8s-test

  8. env: test

  9. ports:

  10. - port: 80 # 服务端口

  11. targetPort: 8080 # 目标端口, 此处指的是pod的8080端口

  12. protocol: TCP

  13. type: LoadBalancer

执行kubectl apply -f k8s-test-lb.yaml
命令发布配置. 此时可以查看到Service已经有了EXTERNAL-IP(10.33.30.2). 如下:

  1. [root@nas-centos1 k8s-test]# kubectl get services

  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

  3. k8s-test-service LoadBalancer 10.244.151.128 10.33.30.2 80:31277/TCP 2s

  4. kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 33d

尝试通过LB的IP来访问应用, 如下:

  1. [root@nas-centos1 k8s-test]# curl http://10.33.30.2/k8s-test/timestamp

  2. 1571235898264


Ingress

Ingress
公开了从群集外部到群集内 services
 的HTTP和HTTPS路由. 流量路由由Ingress
资源上定义的规则控制.

参考文档: https://kubernetes.github.io/ingress-nginx/deploy/

我们使用ingress controller的nginx实现来进行测试. 首先下载部署文件:

  1. wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

编辑文件vim mandatory.yaml
, 加入以下内容:

  1. template:

  2. spec:

  3. 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
来测试, 内容如下:

  1. apiVersion: networking.k8s.io/v1beta1

  2. kind: Ingress

  3. metadata:

  4. name: test-ingress

  5. annotations:

  6. nginx.ingress.kubernetes.io/rewrite-target: /k8s-test

  7. spec:

  8. rules:

  9. - http:

  10. paths:

  11. - path: /k8s-test

  12. backend:

  13. serviceName: k8s-test-service

  14. servicePort: 80

尝试访问:

  1. [root@nas-centos1 ingress]# curl http://10.33.30.94/k8s-test/timestamp

  2. 1571321623058

小结

通常地, 我们会考虑 LoadBalance
Ingress
配合使用. 一方面是只是用LB会产生大量的花费, 另一方面大量的LB同样会提高维护成本. 而LB配合Ingress使用, 通过不同的path来区分服务能达到很棒的效果. (这里和通过Nginx来暴露多个服务的原理基本相同)

 

参考文献

  • https://kubernetes.io


欢迎关注(代码如诗)

 

附录

[1] Deployment.yaml

  1. apiVersion: apps/v1

  2. kind: Deployment

  3. metadata:

  4. name: k8s-test

  5. labels:

  6. app: k8s-test

  7. spec:

  8. replicas: 2

  9. template:

  10. metadata:

  11. name: k8s-test

  12. labels:

  13. app: k8s-test

  14. env: test

  15. spec:

  16. containers:

  17. - name: k8s-test

  18. image: registry.cn-hangzhou.aliyuncs.com/piaoruiqing/k8s-test:0.0.1

  19. imagePullPolicy: IfNotPresent

  20. ports:

  21. - name: http-port

  22. containerPort: 8080

  23. imagePullSecrets:

  24. - name: docker-registry-secret

  25. restartPolicy: Always

  26. selector:

  27. matchLabels:

  28. app: k8s-test


[2] K8sTestApplication.java

  1. /**

  2. * @author piaoruiqing

  3. * @description: k8s test

  4. * @date: 2019/09/22 10:01

  5. * @since JDK 1.8

  6. */

  7. @RestController

  8. @RequestMapping(value = "/k8s-test")

  9. @SpringBootApplication

  10. public class K8sTestApplication {

  11. /**

  12. * get timestamp

  13. * @return

  14. */

  15. @GetMapping(value = "/timestamp")

  16. public ResponseEntity<?> getTimestamp() {

  17. return ResponseEntity.ok(System.currentTimeMillis() + "\n");

  18. }


  19. public static void main(String[] args) {

  20. SpringApplication.run(K8sTestApplication.class, args);

  21. }

  22. }

推荐阅读:

 

[版权声明]
本文发布于朴瑞卿的博客, 允许非商业用途转载, 但转载必须保留原作者朴瑞卿 及链接:http://blog.piaoruiqing.com. 如有授权方面的协商或合作, 请联系邮箱: piaoruiqing@gmail.com.


文章转载自代码如诗,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论