(八)Kubernetes Ingress资源

网友投稿 231 2022-09-11

(八)Kubernetes Ingress资源

前言

​​Kubernetes​​​提供了两种内建的云端负载均衡机制(​​cloud load balancing​​​)用于发布公共应用,一种是工作于传输层的​​Service​​​资源,它实现的是​​“TCP负载均衡器”​​​,另一种是​​Ingress​​​资源,它实现的是​​“HTTP(S)负载均衡器”​​。TCP负载均衡器无论是​​iptables​​还是​​ipvs​​模型的​​Service​​资源都配置于​​Linux​​内核中的​​Netfilter​​之上进行四层调度,是一种类型更为通用的调度器,支持调度​​HTTP​​、​​MySQL​​等应用层服务。不过,也正是由于工作于传输层从而使得它无法做到类似卸载​​HTTPS​​中的​​SSL​​会话等一类操作,也不支持基于​​URL​​的请求调度机制,而且,​​Kubernetes​​也不支持为此类负载均衡器配置任何类型的健康状态检查机制。HTTP(S)负载均衡器​​HTTP(S)​​负载均衡器是应用层负载均衡机制的一种,支持根据环境做出更好的调度决策。与传输层调度器相比,它提供了诸如可自定义​​URL​​映射和​​TLS​​卸载等功能,并支持多种类型的后端服务器健康状态检查机制。

Ingress概述

什么是Ingress?

通常情况下,​​service​​​和​​pod​​​仅可在集群内部网络中通过​​IP​​地址访问。所有到达边界路由器的流量或被丢弃或被转发到其他地方。从概念上讲,可能像下面这样:internet |------------[ Services ]Ingress是授权入站连接到达集群服务的规则集合。internet |[ Ingress ]--|-----|--[ Services ]你可以给​​Ingress​​​配置提供外部可访问的​​URL​​​、负载均衡、​​SSL​​​、基于名称的虚拟主机等。用户通过​​POST Ingress​​​资源到​​API Server​​​的方式来请求​​Ingress​​​。​​Ingress controller​​​负责实现​​Ingress​​​,通常使用负载平衡器,它还可以配置边界路由和其他前端,这有助于以​​HA​​方式处理流量。

Ingress和Ingress Controller

​​Ingress​​​是​​Kubernetes API​​​的标准资源类型之一,它其实就是一组基于​​DNS​​​名称(​​host​​​)或​​URL​​​路径把请求转发至指定的​​Service​​​资源的规则,用于将集群外部的请求流量转发至集群内部完成服务发布。然而,​​Ingress​​​资源自身并不能进行“流量穿透”,它仅是一组路由规则的集合,这些规则要想真正发挥作用还需要其他功能的辅助,如监听某套接字,然后根据这些规则的匹配机制路由请求流量。这种能够为​​Ingress​​​资源监听套接字并转发流量的组件称为​​Ingress​​​控制器(​​Ingress Controller​​)。​​Ingress​​​控制器并不直接运行为​​kube-controller-manager​​​的一部分,它是​​Kubernetes​​​集群的一个重要组件,类似​​CoreDNS​​,需要在集群上单独部署。

Ingress工作流程

如下图所示,流量到达外部负载均衡器(​​externalLB​​​)后,首先转发至​​Service​​​资源​​Ingres-nginx​​​上,然后通过​​Ingress​​​控制器基于​​Ingress​​​资源定义的规则将客户端请求流量直接转发至与​​Service​​​对应的后端​​Pod​​​资源之上。这种转发机制会绕过​​Service​​​资源(​​app Service​​​;​​api Service​​​),从而省去了由​​kube-proxy​​​实现的端口代理开销。​​Ingress​​​规则需要由一个​​Service​​​资源对象辅助识别相关的所有​​Pod​​​资源。如下​​Ingress​​​通过​​app service​​​资源去匹配后端的​​pod1​​​和​​pod2​​​;这个​​app service​​只是起到一个辅助识别功能。

先决条件

在使用​​Ingress resource​​​之前,必须先了解下面几件事情。​​Ingress​​​是​​beta​​​版本的​​resource​​​,在​​kubernetes1.1​​​之前还没有。你需要一个​​Ingress Controller​​​来实现​​Ingress​​​,单纯的创建一个​​Ingress​​没有任何意义。​​GCE/GKE​​​会在​​master​​​节点上部署一个​​Ingress Controller​​​。你可以在一个​​Pod​​​中部署任意个自定义的​​Ingress Controller​​​。你必须正确的​​annotate​​​每个​​Ingress​​​,比如运行多个​​Ingress Controller​​​和关闭​​glbc​​。

Ingress清单文件几个字段说明

​​Ingress​​​资源是基于​​HTTP​​​虚拟主机或​​URL​​​的转发规则,​​spec​​​字段中嵌套了​​rules​​​、​​backend​​​、​​tls​​​等字段进行定义。下面这个示例中,它包含了一个转发规则,把发往​​ilinux.io​​​的请求代理给名为​​myapp-svc​​​的​​Service​​资源。

apiVersion: extensions/v1beta1kind: Ingressmetadata: name: ingress-demo namespace: default annotations: kubernetes.io/ingress.class: "nginx"spec: rules: - host: ilinux.io paths: - backend: serviceName: myapp-svc servicePort: 80#说明:上面资源清单文件中的annotations用于识别其所属的Ingress控制器的类别,这一点在集群上部署多个Ingress控制器时尤为重要。

​​Ingress Spec​​​(​​# kubectl explain ingress.spec​​​)中的字段是定义​​Ingress​​资源的核心组成部分,主要嵌套如下三个字段:rules <[]Object>:用于定义当前​​Ingress​​资源的转发规则列表;未由​​rules​​定义规则,或者没有匹配到任何规则时,所有流量都会转发到由​​backend​​定义的默认后端。backend :默认的后端用于服务那些没有匹配到任何规则的请求;定义​​Ingress​​资源时,至少应该定义​​backend​​或​​rules​​两者之一;此字段用于让负载均衡器指定一个全局默认的后端。tls <[]Object>:​​TLS​​配置,目前仅支持通过默认端口​​443​​提供服务;如果要配置指定的列表成员指向了不同的主机,则必须通过​​SNI TLS​​扩展机制来支持此功能。​​ingress.spec.rules.Controller(Nginx)

描述

​​Ingress​​​ 控制器自身是运行于​​Pod​​​中的容器应用,一般是​​Nginx​​​或​​Envoy​​​一类的具有代理及负载均衡功能的守护进程,它监视着来自​​API Server​​​的​​Ingress​​对象状态,并根据规则生成相应的应用程序专有格式的配置文件并通过重载或重启守护进程而使新配置生效。​​Ingress​​​控制器其实就是托管于​​Kubernetes​​​系统之上的用于实现在应用层发布服务的​​Pod​​​资源,跟踪​​Ingress​​资源并实时生成配置规则。

运行为​​Pod​​​资源的​​Ingress​​控制器进程通过下面两种方式接入外部请求流量:

1、以​​Deployment​​​控制器管理​​Ingress​​​控制器的​​Pod​​​资源,通过​​NodePort​​​或​​LoadBalancer​​​类型的​​Service​​​对象为其接入集群外部的请求流量,这就意味着,定义一个​​Ingress​​​控制器时,必须在其前端定义一个专用的​​Service​​资源。

2、借助于​​DaemonSet​​​控制器,将​​Ingress​​​控制器的​​Pod​​​资源各自以单一实例的方式运行于集群的所有或部分工作节点之上,并配置这类​​Pod​​​对象以​​HostPort​​​(如下图中的a)或​​HostNetwork​​(如下图中的b)的方式在当前节点接入外部流量。

部署

​​Ingress-nginx官网​​

​​Ingress-nginx GitHub仓库地址​​

​​Ingress安装文档​​

1)在​​github​​​上下载配置清单​​yaml​​文件,并创建部署

[root@k8s-master ~]# mkdir ingress-nginx #这里创建一个目录专门用于ingress-nginx(可省略)[root@k8s-master ~]# cd ingress-nginx/[root@k8s-master ingress-nginx]# wget #下载配置清单yaml文件[root@k8s-master ingress-nginx]# ls #查看下载的文件mandatory.yaml[root@k8s-master ingress-nginx]# kubectl apply -f mandatory.yaml #创建Ingressnamespace/ingress-nginx createdconfigmap/nginx-configuration createdconfigmap/tcp-services createdconfigmap/udp-services createdserviceaccount/nginx-ingress-serviceaccount createdclusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole createdrole.rbac.authorization.k8s.io/nginx-ingress-role createdrolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding createdclusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding createddeployment.apps/nginx-ingress-controller created

2)验证

[root@k8s-master ingress-nginx]# kubectl get pods -n ingress-nginx #查看生成的pod,注意这里在ingress-nginx名称空间NAME READY STATUS RESTARTS AGEnginx-ingress-controller-79f6884cf6-5fb6v 1/1 Running 0 18m[root@k8s-master ingress-nginx]# kubectl describe pod nginx-ingress-controller-79f6884cf6-5fb6v -n ingress-nginx 查看该pod的详细信息Name: nginx-ingress-controller-79f6884cf6-5fb6vNamespace: ingress-nginxPriority: 0Node: k8s-node2/192.168.1.33Start Time: Fri, 27 Sep 2019 17:53:07 +0800Labels: app.kubernetes.io/name=ingress-nginx app.kubernetes.io/part-of=ingress-nginx pod-template-hash=79f6884cf6Annotations: prometheus.io/port: 10254 prometheus.io/scrape: trueStatus: RunningIP: 10.244.2.73......

3)如果是裸机部署,还需要安装​​service​​​。(比如​​VMware​​虚拟机、硬件服务器等)

---同样去官网下载配置清单文件,也可以自定义创建。[root@k8s-master ingress-nginx]# wget ingress-nginx]# kubectl apply -f service-nodeport.yaml #创建service资源service/ingress-nginx created[root@k8s-master ingress-nginx]# kubectl get svc -n ingress-nginx #查看service资源NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEingress-nginx NodePort 10.107.40.182 80:32699/TCP,443:30842/TCP 9s[root@k8s-master ingress-nginx]# kubectl describe svc/ingress-nginx -n ingress-nginx #查看该service的详细信息Name: ingress-nginxNamespace: ingress-nginxLabels: app.kubernetes.io/name=ingress-nginx app.kubernetes.io/part-of=ingress-nginxAnnotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/par...Selector: app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginxType: NodePortIP: 10.107.40.182Port: 80/TCPTargetPort: 80/TCPNodePort: 32699/TCPEndpoints: 10.244.2.73:80Port: 443/TCPTargetPort: 443/TCPNodePort: 30842/TCPEndpoints: 10.244.2.73:443Session Affinity: NoneExternal Traffic Policy: ClusterEvents:

通过上面创建的​​service​​​资源对象可以看出,随机分配的​​~]# mkdir ingress-nginx/ingress[root@k8s-master ~]# cd ingress-nginx/ingress/

(1)、创建​​testing​​​名称空间(也可以使用命令直接创建​​# kubectl create namespace my-namespace​​,不过这里使用资源清单格式创建)

[root@k8s-master ingress]# vim namespace-testing.yaml #编写namespace清单文件apiVersion: v1kind: Namespacemetadata: name: testing labels: env: testing[root@k8s-master ingress]#[root@k8s-master ingress]# kubectl apply -f namespace-testing.yaml #创建namespacenamespace/testing created[root@k8s-master ingress]#[root@k8s-master ingress]# kubectl get namespace testing #验证NAME STATUS AGEtesting Active 12s

(2)、部署​​nginx​​​实例,这里使用​​Deployment​​​控制器于​​testing​​​中部署​​nginx​​​相关的​​Pod​​对象。

[root@k8s-master ingress]# vim deployment-nginx.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: deploy-nginx namespace: testingspec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.12 ports: - name: containerPort: 80[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl apply -f deployment-nginx.yaml deployment.apps/deploy-nginx created[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl get deploy -n testingNAME READY UP-TO-DATE AVAILABLE AGEdeploy-nginx 3/3 3 3 5s[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl get pods -n testingNAME READY STATUS RESTARTS AGEdeploy-nginx-686bddcb56-9g7pq 1/1 Running 0 6sdeploy-nginx-686bddcb56-gqpm2 1/1 Running 0 6sdeploy-nginx-686bddcb56-vtwkq 1/1 Running 0 6s

(3)、创建​​Service​​​资源,关联后端的​​Pod​​​资源。这里通过​​service​​​资源​​svc-nginx​​​的​​80​​​端口去暴露容器的​​80​​端口。

[root@k8s-master ingress]# vim service-nginx.yamlapiVersion: v1kind: Servicemetadata: name: svc-nginx namespace: testing labels: app: svc-nginxspec: selector: app: nginx ports: - name: port: 80 targetPort: 80 protocol: TCP[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl apply -f service-nginx.yaml service/svc-nginx created[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl get svc -n testingNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEsvc-nginx ClusterIP 10.99.233.90 80/TCP 6s[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl describe svc/svc-nginx -n testingName: svc-nginxNamespace: testingLabels: app=svc-nginxAnnotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"svc-nginx"},"name":"svc-nginx","namespace":"testing"},"s...Selector: app=nginxType: ClusterIPIP: 10.99.233.90Port: 80/TCPTargetPort: 80/TCPEndpoints: 10.244.1.76:80,10.244.1.77:80,10.244.2.74:80Session Affinity: NoneEvents:

(4)、创建​​Ingress​​​资源,匹配​​Service​​​资源​​svc-nginx​​​,并将​​svc-nginx​​的80端口暴露。

[root@k8s-master ingress]# vim ingress-nginx.yamlapiVersion: extensions/v1beta1kind: Ingressmetadata: name: nginx namespace: testing annotations: kubernetes.io/ingress.class: "nginx"spec: rules: - host: nginx.ilinux.io paths: - path: backend: serviceName: svc-nginx servicePort: 80[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl apply -f ingress-nginx.yaml ingress.extensions/nginx created[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl get ingress -n testingNAME HOSTS ADDRESS PORTS AGEnginx nginx.ilinux.io 80 16s[root@k8s-master ingress]# [root@k8s-master ingress]# kubectl describe ingress -n testingName: nginxNamespace: testingAddress: Default backend: default-()Rules: Host Path Backends ---- ---- -------- tomcat.ilinux.io svc-nginx:80 (10.244.1.76:80,10.244.1.77:80,10.244.2.74:80)Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"nginx","namespace":"testing"},"spec":{"rules":[{"host":"nginx.ilinux.io"," kubernetes.io/ingress.class: nginxEvents:

(5)、测试,通过​​Ingress​​​控制器的前端的​​Service​​​资源的​​NodePort​​来访问此服务,

#首先查看前面部署Ingress控制器的前端的Service资源的映射端口[root@k8s-master ingress-nginx]# kubectl get svc -n ingress-nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEingress-nginx NodePort 10.107.40.182 80:32699/TCP,443:30842/TCP 3m59s#终端测试,添加hosts[root@k8s-master ~]# cat /etc/hosts192.168.1.31 k8s-master nginx.ilinux.io192.168.1.32 k8s-node1 nginx.ilinux.io192.168.1.33 k8s-node2 nginx.ilinux.io#访问测试[root@k8s-master ~]# curl nginx.ilinux.io:32699Welcome to nginx!