k8s教程(service篇)-ingress 7层路由机制(上)

简介: k8s教程(service篇)-ingress 7层路由机制(上)

01 引言

声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》的读书笔记

在前面,我们知道Service的表现形式为IP地址和端口号ClusterIP:Port),即工作在TCP/IP层。而对于基于HTTP的服务来说,不同的URL地址经常对应到不同的后端服务或者虚拟服务器(Virtual Host),这些应用层的转发机制仅通过KubernetesService机制是无法实现的。

所以Kubernetes从1.1版本开始引入Ingress资源对象,用于将Kubernetes集群外的客户端请求路由到集群内部的服务上,同时提供7层(HTTP和HTTPS)路由功能。

02 ingress概念

Kubernetes 使用了一个Ingress策略定义一个具体提供转发服务的Ingress Controller,两者结合,实现了基于灵活Ingress策略定义的服务路由功能。

如果是对Kubernetes集群外部的客户端提供服务,那么Ingress Controller实现的是类似于边缘路由器(Edge Router)的功能。需要注意的是,Ingress只能以HTTPHTTPS提供服务,对于使用其他网络协议的服务,可以通过设置Service的类型 typeNodePortLoadBalancer对集群外部的客户端提供服务

2.1 简单例子

使用Ingress进行服务路由时,Ingress Controller基于Ingress规则将客户端请求直接转发到Service对应的后端Endpoint(Pod)上,这样会跳过kube-proxy设置的路由转发规则,以提高网络转发效率,下图是一个典型的HTTP层路由的例子:

其中:

  • 对http:/mywebsite.com/api的访问将被路由到后端名为api的Service上;
  • 对http:/mywebsite.com/web的访问将被路由到后端名为web的Service上;
  • 对http:/mywebsite.com/docs的访问将被路由到后端名为docs的Service上。

03 完整案例

下面先通过一个完整的例子对Ingress Controller的部署、Ingress策略的配置,以及客户端如何通过Ingress Controller访问服务对Ingress的原理和应用进行说明。

3.1 部署ingress controller

Ingress Controller需要实现基于不同HTTP URL向后转发的负载分发规则, 并可以灵活设置7层负载分发策略。目前Ingress Controller已经有许多实现方案, 包括NginxHAProxyKongTraefikSkipperIstio等开源软件的实现,以及公有云GCEAzureAWS等提供的Ingress应用网关,用户可以参考官方网站根据业务需求选择适合的Ingress Controller

本例基于Nginx提供的Ingress Controller进行说明。

在Kubernetes中,Ingress Controller 会持续监控 API Server 的 /ingress 接口 (即用户定义的到后端服务的转发规则)的变化。当/ingress接口后端的服务信息发生变化时,Ingress Controller会自动更新其转发规则

Nginx Ingress Controller 可以以DaemonsetDeployment模式进行部署,通常可以考虑通过设置 nodeSelector或 亲和性调度策略将其调度到固定的几个Node上提供服务。

对于客户端应用如何通过网络访问Ingress Controller

  • 通过在容器级别设置hostPort,将80和443端口号映射到宿主机上,这样客户端应用可以通过 URL地址“http://<NodeIP>:80”或“https://<NodeIP>:443”访问Ingress Controller(本例演示);
  • 可以配置Pod使用hostNetwork模式直接监听宿主机网卡的IP地址和端口号
  • 使用Service的NodePort将端口号映射到宿主机上

下面是Nginx Ingress ControllerYAML定义,其中将Pod创建在namespace“nginx-ingress”中,通过nodeSelector“role=ingress-nginx-controller” 设置了调度的目标Node,并设置了hostPort将端口号映射到宿主机上供集群外部的客户端访问。该配置文件包含了Namespace、ServiceAccount、RBAC、 Secret、ConfigMap和Deployment等资源对象的配置。


namespace的定义如下:

# nginx-ingress-controller.yaml
apiVersion: v1
kind: Namespace
metadata:
name: nginx-ingress

ServiceAccount的定义如下:

apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress
namespace: nginx-ingress

RBAC相关资源的定义如下:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nginx-ingress
rules:
- apiGroups:
  - ""
  resources:
    - services
  - endpoints
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  verbs:
  - get
  - list
  - watch
  - update
  - create
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
  - list
- apiGroups:
  - extensions
  resources:
  - ingresses
  verbs:
  - list
  - watch
  - get
- apiGroups:
  - "extensions"
  resources:
  - ingresses/status
  verbs:
  - update
- apiGroups:
  - k8s.nginx.org
  resources:
  - virtualservers
  - virtualserverroutes
  - globalconfigurations 
  - transportservers
  - policies
  verbs:
  - list
  - watch
  - get
- apiGroups:
  - k8s.nginx.org
  resources:
  - virtualservers/status
  - virtualserverroutes/status
  verbs:
  - update
---
kind: ClusterRoleBinding
apiversion: rbac.authorization.k8s.io/v1
metadata:
  name: nginx-ingress
subjects:
- kind: ServiceAccount
  name:nginx-ingress
  namespace: nginx-ingress 
  roleRef:
  kind: ClusterRole
  name: nginx-ingress
  apiGroup: rbac.authorization.k8s.io

Secret的定义如下:

apiVersion: v1
kind: Secret
metadata: 
  name: default-server-secret
  namespace: nginx-ingress 
type: Opaque
data:
  tls.secret:
    xxx...
  tls.key:
    xxxx... 

ConfigMap的定义如下:

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
  namespace: nginx-ingress 
data:

Deployment的定义如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress
  namespace: nginx-ingress 
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-ingress
  template:
    metadata:
      labels:
        app: nginx-ingress
  spec:
    nodeSelector:
    role: ingress-nginx-controller 
    serviceAccountName: nginx-ingress 
    containers:
    - image: nginx/nginx-ingress:1.7.2 
      imagePullPolicy: IfNotPresent 
      name: nginx-ingress
      ports:
      - name: http
        containerPort: 80
        hostPort: 80
      - name: https
        containerPort: 443
        hostPort: 443
      securityContext:
        allowPrivilegeEscalation: true 
        runAsUser: 101 #nginx 
        capabilities:
          drop:
        - ALL
        add:
        - NET_BIND_SERVICE
       env:
       - name: POD_NAMESPACE 
         valueFrom:
           fieldRef:
             fieldPath: metadata.namespace
       - name: POD_NAME 
         valueFrom:
         fieldRef:
         fieldPath: metadata.name
       args:
       - -nginx-configmaps=$(POD NAMESPACE)/nginx-config
         - -default-server-tls-secret=$(POD NAMESPACE)/default-server-secret

通过kubectl create命令创建nginx-ingress-controller:

查看nginx-ingress-controller容器,确认其正常运行:

用curl访问Nginx Ingress Controller所在宿主机的80端口,验证其服务是否正常,在没有配置后端服务时Nginx会返回404应答:

3.2 创建ingress策略

本例对域名mywebsite.com的访问设置Ingress策略,定义对其/demo路径的访问转发到后端webapp Service的规则:

# mywebsite-ingress.yaml
apiversion: networking.k8s.io/v1 
kind: Ingress
metadata:
  name: mywebsite-ingress
spec:
  rules:
  - host: mywebsite.com
  http:
    paths:
    - path: /demo
      pathType: ImplementationSpecific 
      backend:
        service:
          name: webapp
        port:
          number: 8080

通过该Ingress定义设置的效果:客户端对目标地址 http://mywebsite.com/demo的访问将被转发到集群内的服务“webapp”上,完整的URL为“http://webapp:8080/demo”。

Ingress策略生效之前,需要先确保webapp服务正确运行。同时注意Ingress中对路径的定义需要与后端webapp服务提供的访问路径一致,否则将被转发到一个不存在的路径上,引发错误。

创建:

一旦Ingress资源成功创建,Ingress Controller就会监控到其配置的路由策略,并更新到Nginx的配置文件中生效

以本例中的Nginx Controller为例,它将更新其配置文件的内容为在Ingress中设定的路由策略。

登录一个nginx-ingress-controller Pod,在/etc/nginx/conf.d目录下可以看到

Nginx Ingress Controller自动生成的配置文件default-mywebsite-ingress.conf,查看其内容,可以看到对mywebsite.com/demo的转发规则的正确配置:

3.3 客户端通过Ingress Controller访问后端webapp服务

由于Ingress Controller容器通过hostPort将服务端口号80映射到了宿主机上,所以客户端可以通过Ingress Controller所在的Node访问mywebsite.com提供的服务。

需要说明的是,客户端只能通过域名mywebsite.com访问服务,这时要求客户端或者DNSmywebsite.com域名解析到node的真实IP地址上。

通过curl访问mywebsite.com提供的服务(可以用--resolve参数模拟DNS解析,目标地址为域名;也可以用-H'Host:mywebsite.com'参数设置在HTTP头中要访问的域名,目标地址为IP地址),可以正确访问到myweb服务/demo/的页面内容。

04 ingress资源对象配置

4.1 定义

一个ingress资源对象的定义如下:

apiversion: networking.k8s.io/v1 
kind: Ingress
metadata:
  name: mywebsite-ingress 
spec:
  rules:
  - host: mywebsite.com
    http:
      paths:
      - path: /demo
        pathType: ImplementationSpecific 
        backend:
          service:
            name: webapp
            port:
              number: 8080

Ingress资源主要用于定义路由转发规则,可以包含多条转发规则的定义,通spec.rules进行设置。下面对其中的关键配置进行说明。

4.2 规则 (rules)相关设置

规则 (rules)相关设置如下:

配置 描述
host(可选配置) 基于域名的访问,客户端请求将作用于指定域名的客户端请求
http.paths 一组根据路径进行转发的规则设置,每个路径都应配置相应的后端服务信息(服务名称和服务端口号)。只有客户端请求中的host和path都匹配之后,才会进行转发。
backend 目标后端服务,包括服务的名称和端口号。

Ingress Controller将根据每条rule中path定义的URL路径将客户端请求转发到backend定义的后端服务上。

如果一个请求同时被在Ingress中设置的多个URL路径匹配,则系统将以最长的匹配路径为优先。如果有两条同等长度的匹配路径,则精确匹配类型(Exct) 优先于前缀匹配类型(Prefix)。

4.3 后端(Backend)设置

后端通常被设置为目标服务(Service),通常还应该为不匹配任何路由规则 (rule)的请求设置一个默认的后端,以返回HTTP 404响应码来表示没有匹配的规则。

默认的后端服务可以由Ingress Controller提供,也可以在Ingress资源对象中设置。

另外,如果后端不是以KubernetesService提供的,则也可以设置为提供服务的资源对象,在这种情况下使用resource字段进行设置。例如,下例中的Ingress设置的后端地址为通过CRD“StorageBucket”定义的某个服务,同时设置为默认的后端:

apiversion: networking.k8s.io/v1 
kind: Ingress
metadata:
  name: ingress-resource-backend 
spec:
  defaultBackend:
    resource:
      apiGroup: k8s.example.com 
      kind: StorageBucket
      name: static-assets
rules:
- http:
    paths:
    - path: /icons
      pathType: ImplementationSpecific 
    backend:
    resource:
      apiGroup: k8s.example.com 
      kind: StorageBucket
      name: icon-assets

通过这个Ingress的定义,客户端对路径/icons的访问将会被路由转发到后端名为“icon-assets”的StorageBucket服务上。不匹配任何规则的请求则侧被路由转发到默认的后端(defaultBackend)上。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
目录
相关文章
|
1月前
|
缓存 Kubernetes Docker
容器服务ACK常见问题之容器服务ACK ingress websocket配置失败如何解决
容器服务ACK(阿里云容器服务 Kubernetes 版)是阿里云提供的一种托管式Kubernetes服务,帮助用户轻松使用Kubernetes进行应用部署、管理和扩展。本汇总收集了容器服务ACK使用中的常见问题及答案,包括集群管理、应用部署、服务访问、网络配置、存储使用、安全保障等方面,旨在帮助用户快速解决使用过程中遇到的难题,提升容器管理和运维效率。
|
1月前
|
存储 运维 Kubernetes
容器服务ACK常见问题之修改service的名字失败如何解决
容器服务ACK(阿里云容器服务 Kubernetes 版)是阿里云提供的一种托管式Kubernetes服务,帮助用户轻松使用Kubernetes进行应用部署、管理和扩展。本汇总收集了容器服务ACK使用中的常见问题及答案,包括集群管理、应用部署、服务访问、网络配置、存储使用、安全保障等方面,旨在帮助用户快速解决使用过程中遇到的难题,提升容器管理和运维效率。
|
2月前
|
Kubernetes 应用服务中间件 nginx
百度搜索:蓝易云【使用Kubernetes部署Nginx应用教程】
现在,你已经成功在Kubernetes集群上部署了Nginx应用。通过访问Service的外部IP地址,你可以访问Nginx服务。
42 4
|
3月前
|
Kubernetes 负载均衡 应用服务中间件
kubernetes—Ingress详解
kubernetes—Ingress详解
74 0
|
3月前
|
Kubernetes 应用服务中间件 nginx
|
4月前
|
Kubernetes 应用服务中间件 nginx
k8s ingress不生效的bug 解决了。
k8s ingress不生效的bug 解决了。
100 0
|
4月前
|
Kubernetes 负载均衡 应用服务中间件
k8s学习-Ingress(安装、模板、创建、删除)
k8s学习-Ingress(安装、模板、创建、删除)
101 0
|
4月前
|
Kubernetes 负载均衡 网络协议
k8s学习-Service(概念、模板、创建、外部代理、删除等)
k8s学习-Service(概念、模板、创建、外部代理、删除等)
147 0
|
3月前
|
Kubernetes 负载均衡 网络协议
|
1月前
|
容器
在容器服务ACK中,如果你想更改ALB Ingress的域名和端口
【2月更文挑战第15天】在容器服务ACK中,如果你想更改ALB Ingress的域名和端口
15 3