企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] 参考连接:[https://www.qikqiak.com/k8s-book/docs/40.ingress.html](https://www.qikqiak.com/k8s-book/docs/40.ingress.html) 参考链接:https://www.funtl.com/zh/service-mesh-kubernetes/Ingress-%E7%BB%9F%E4%B8%80%E8%AE%BF%E9%97%AE%E5%85%A5%E5%8F%A3.html#%E4%B8%89%E7%A7%8D%E5%A4%96%E9%83%A8%E8%AE%BF%E9%97%AE%E6%96%B9%E5%BC%8F ## 缘由 看了statefulset[基础教程]([https://kubernetes.io/zh/docs/tutorials/stateful-application/basic-stateful-set/](https://kubernetes.io/zh/docs/tutorials/stateful-application/basic-stateful-set/))的基础教程,并且把环境搭建起来后。pod内部是可以连通了。但是我不知道怎么去从外部访问。 ## 三种外部访问方式 ### NodePort NodePort 服务是引导外部流量到你的服务的最原始方式。NodePort,正如这个名字所示,**在所有节点(虚拟机)上开放一个特定端口**,任何发送到该端口的流量都被转发到对应服务。 NodePort 服务特征如下: * 每个端口只能是一种服务 * 端口范围只能是 30000-32767(可调) * 不在 YAML 配置文件中指定则会分配一个默认端口 > **建议:**不要在生产环境中使用这种方式暴露服务,大多数时候我们应该让 Kubernetes 来选择端口 ![](https://www.funtl.com/assets1/Lusifer_2019060601200002.png) ### LoadBalancer LoadBalancer 服务是暴露服务到 Internet 的标准方式。所有通往你指定的端口的流量都会被转发到对应的服务。它没有过滤条件,没有路由等。这意味着你几乎可以发送任何种类的流量到该服务,像 HTTP,TCP,UDP,WebSocket,gRPC 或其它任意种类。 ![](https://www.funtl.com/assets1/Lusifer_2019060601200003.png) ## Ingress Ingress 事实上不是一种服务类型。相反,它处于多个服务的前端,扮演着 “智能路由” 或者集群入口的角色。你可以用 Ingress 来做许多不同的事情,各种不同类型的 Ingress 控制器也有不同的能力。它允许你基于路径或者子域名来路由流量到后端服务。 Ingress 可能是暴露服务的最强大方式,但同时也是最复杂的。Ingress 控制器有各种类型,包括 Google Cloud Load Balancer, Nginx,Contour,Istio,等等。它还有各种插件,比如 cert-manager (它可以为你的服务自动提供 SSL 证书)/ 如果你想要使用同一个 IP 暴露多个服务,这些服务都是使用相同的七层协议(典型如 HTTP),你还可以获取各种开箱即用的特性(比如 SSL、认证、路由等等) ![](https://www.funtl.com/assets1/Lusifer_2019060601200004.png) ### Ingress组成 Ingress 使用开源的反向代理负载均衡器来实现对外暴露服务目的,比如用Nginx、Apache、Haproxy等。用的最多的是使用nginx来做的。 Nginx Ingress 一般有三个组件组成: * **ingress**是kubernetes的一个资源对象,用于编写定义规则。将nginx的配置抽象成一个Ingress对象,当用户每添加一个新的服务,只需要编写一个新的ingress的yaml文件即可。 * **反向代理负载均衡器**通常以Service的Port方式运行,接收并按照ingress定义的规则进行转发,通常为nginx,haproxy,traefik等,本文使用nginx。 * **ingress-controller**监听apiserver,获取服务新增,删除等变化,并结合ingress规则动态更新到反向代理负载均衡器上,并重载配置使其生效。 以上三者有机的协调配合起来,就可以完成 Kubernetes 集群服务的暴漏。 ![](https://cdn.jsdelivr.net/gh/wandouduoduo/wandouduoduo.github.io/articles/f6f38be4/1.png) **组件说明** externalLB : 外部的4层负载均衡器 ingress-nginx : nodePort 类型的 service 为ingress-nginx 的 pod 接入外部流量 ingress-nginx : ingress-nginx pod, 负责创建负载均衡 : Ingress 根据后端 Service 实时识别分类及 IP 把结果生成配置文件注入到 ingress-nginx pod 中 site1 : Service 对后端的pod 进行分类(只起分类作用) ### Ingress工作原理 * ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化。 * 然后读取它,按照自定义的规则,规则就是写明了那个域名对应哪个service,生成一段nginx配置。 * 在写到nginx-ingress-controller的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中。 * 然后reload一下使配置生效,以此达到分配和动态更新问题。 ### **Ingress解决痛点** **动态配置服务** 如果按照传统方式,当新增加一个服务时,我们可能需要在流量入口加一个反向代理指向我们新的服务,而使用ingress,只需要配置好ingress,当服务启动时,会自动注册到ingress当中,不需要额外的操作。 **减少不必要的Port暴露(安全,端口容易管理)** 我们知道部署k8s时,是需要关闭防火墙的,主要原因是k8s的很多服务会以nodeport方式映射出去,这样对于宿主机来说是非常的不安全的,而ingress可以避免这个问题,只需要将ingress自身服务映射出去,就可代理后端所有的服务,则后端服务不需要映射出去。 ### nginx服务 结合Statefulset的示例进行配置。这是未配置之前的示例: ``` apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: v1 kind: PersistentVolume metadata: name: "www-data-pv" labels: name: www-data-pv release: stable spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle nfs: path: /nfs/www/data server: 192.168.84.75 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: www-data-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi selector: matchLabels: name: www-data-pv release: stable --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: serviceName: "nginx" replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumes: - name: www persistentVolumeClaim: claimName: www-data-pvc ``` ## Ingress示例 我们知道前面我们使用 NodePort 和 LoadBlancer 类型的 Service 可以实现把应用暴露给外部用户使用,除此之外,Kubernetes 还为我们提供了一个非常重要的资源对象可以用来暴露服务给外部用户,那就是 ingress。 创建一个 ingress 对象:(ingress.yaml) ``` # Ingress 配置 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: web-cluster-external labels: name: web-cluster-external app: nginx spec: rules: - host: nginx.com http: paths: - backend: serviceName: web-cluster-external servicePort: 80 path: / ``` 然后为 traefik dashboard 创建对应的 ingress 对象: ``` $ kubectl create -f ingress.yaml ``` 可以查看ingress是否创建成功 ``` kubectl describe ingress web-cluster-external ``` 要注意上面的 ingress 对象的规则,特别是 rules 区域,我们这里是要为 ngin 建立一个 ingress 对象,所以这里的 serviceName 对应的是上面我们创建的 web-cluster-external ,端口也要注意对应 80端口,为了避免端口更改,这里的 servicePort 的值也可以替换成上面定义的 port 的名字: web ` ` 创建完成后,我们应该怎么来测试呢? * 第一步,在本地的**/etc/hosts**里面添加上 nginx.com 与 节点外网 IP 的映射关系 * 第二步,在浏览器中访问:nginx.com 我们会发现并没有得到我们期望的 inde.html界面,这是因为我们上面statefulset 部署 nginx 的时候没有外放NodePort端口。需要配置。ClusterIP都是集群内部访问的。需要我们建立一个名为service对象node.yaml ``` # cluster ip apiVersion: v1 kind: Service metadata: name: web-cluster-external labels: name: web-cluster-external app: nginx spec: selector: app: nginx ports: - name: http port: 80 targetPort: 80 nodePort: 32002 #增加 type: NodePort ``` 创建service对象 ``` kubectl apply node.yaml ``` 这样就可以通过节点 ip:32002来访问nginx啦。或者是通过域名来访问