30

Kubernetes(三) 如何从外部访问服务

 4 years ago
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.

JnAZVzY.jpg!web

十月 20, 2019 朴瑞卿

目录

  • 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-sw5pd8080 端口.

/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 ControllerIngress 的概念.

发布完成后, 我们创建一个 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

小结

通常地, 我们会考虑 LoadBalanceIngress 配合使用. 一方面是只是用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] .

欢迎关注公众号: (代码如诗) iYFFBbB.jpg!web

相关


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK