ingress流量控制与灰度金丝雀发布
一、ingress1、ingress是什么ingress是一种七层流量转发机制即七层负载均衡请求抵达ingress后ingress会匹配url的路径部分将不同的路径分发不同的后端svc一个svc代理一个微服务的多副本来处理请求到了svc之后svc依据自己标签选中的微服务pod以及负载均衡策略例如ipvs来将请求转发给指定pod注意svc拥有负载均衡能力的前提是它有clusterIP2、为何要用ingress为了用引入七层负载均衡把微服务重新汇聚成一个整体然后对外暴漏二、引入ingress之后完整的访问流程见图 第五章三、ingress相关概念1. ingress的控制器ingress controller----- 负载均衡软件跑在pod里----- k8s的控制器来对pod进行管理自愈为了解决两点问题1、配置中转发给某个svc最好用其fqdn域名而不是ip-》默认使用k8s的coredns2、ingress的软件需要能够被管理起来能够自愈----》引入k8s的控制器资源来管理需要把ingress的软件部署到pod里并且用k8s的控制器资源来管理ingress的七层负载均衡软件 负责管理维护其配置的守护进程》合在一起部署在同一个pod中》有一个专门的称呼叫ingress controller2. ingress对象是一种往ingress的软件中注入配置的一种非常方便的方式----》用yaml清单的方式注入配置四、ingress有3种部署方案到底用k8s中的哪种控制器资源来进行管理有何区别1. 按照是否需要为ingress的pod创建svc来区分可以分为两大方案pod是通过物理节点的IP端口暴露出去的对接的下游还有一个物理的负载均衡器软件的也可以这就需要每个物理节点都暴露ip端口能访问到k8s里的pod————svc会在每个物理节点添加ipvs转发规则还有一种方案deamenset就是在每个节点上都部署一个pod,他的网络模式为hostnetwork这样就能通过每个物理节点访问到ingress了。1、需要创建ingress的svc非hostNetwork网络模式depoyment来部署ingress的podpod的网络不是hostNetwork svctype为LoadBalancerdepoyment来部署ingress的podpod的网络不是hostNetwork svctype为NodePort2、不需要创建ingress的svc用hostNetwork网络模式转发路径更短效率更高Daemonset来部署ingress的podpod的网络就是hostNetwork五、部署ingress、测试使用注入匹配规则ingress controller ---------ingressclass--------ingress对象物理节点的ip:32568curl http://test.ingress.com:34780/host/test.htmlwget --no-check-certificate https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/baremetal/deploy.yaml # 最新下载地址需要换镜像地址 https://github.com/kubernetes/ingress-nginx/blob/main/deploy/static/provider/baremetal/deploy.yaml # 里面包含了代理的nodeport的svccat microservices.yaml EOF apiVersion: apps/v1 kind: Deployment metadata: labels: app: gowebhost name: gowebhost spec: replicas: 2 selector: matchLabels: app: gowebhost strategy: {} template: metadata: labels: app: gowebhost spec: containers: - image: nginx:1.18 name: nginx --- apiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: gowebhost name: gowebhost spec: ports: - port: 9999 protocol: TCP targetPort: 80 selector: app: gowebhost type: ClusterIP status: loadBalancer: {} --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: gowebip name: gowebip spec: replicas: 2 selector: matchLabels: app: gowebip strategy: {} template: metadata: labels: app: gowebip spec: containers: - image: nginx:1.18 name: nginx --- apiVersion: v1 kind: Service metadata: creationTimestamp: null labels: app: gowebip name: gowebip spec: ports: - port: 8888 protocol: TCP targetPort: 80 selector: app: gowebip type: ClusterIP status: loadBalancer: {} EOFcat ingress.yaml EOF apiVersion: networking.k8s.io/v1 # kubectl explain ingress.apiVersion kind: Ingress metadata: name: ingress-test namespace: default annotations: #kubernetes.io/ingress.class: nginx # 开启use-regex启用path的正则匹配 nginx.ingress.kubernetes.io/use-regex: true spec: ingressClassName: nginx rules: # 定义域名 - host: test.ingress.com http: paths: # 不同path转发到不同端口 - path: /ip pathType: Prefix backend: service: name: gowebip port: number: 8888 - path: /host pathType: Prefix backend: service: name: gowebhost port: number: 9999 EOF六、 ingress对象资源详解(一) 核心字段介绍ingress是一个API对象和其他对象一样通过yaml文件来配置为负载均衡程序注入配置一条 ingress就是写入nginx.conf中的一段配置1. 以如下ingress对象yaml为示例展开介绍apiVersion: networking.k8s.io/v1 # 可以查看详情kubectl explain ingress kind: Ingress metadata: name: ingress-test namespace: default annotations: # 注解 kubernetes.io/ingress.class: nginx #老版本选择ingress controller nginx.ingress.kubernetes.io/use-regex: true # 开启use-regex启用path的正则匹配 spec: tls: - hosts: - test.ingress.com secretName: ingress-tls ingressClassName: nginx # 选择ingress controller rules: # 定义域名 - host: test.ingress.com # 外部访问的域名 http: paths: # 不同path转发到不同端口 - path: /ip pathType: Prefix # 前缀匹配 backend: service: name: gowebip #svc的fqnd名 port: number: 8888 #svc的端口 - path: /host pathType: Prefix backend: service: name: gowebhost port: number: 9999与其他k8s对象一样ingress配置有几个重要的属性1、metadata.annotations(详细用法第八章节)在ingress配置中annotations很重要可以用来控制启用何种功能如下use-regex启用正则匹配:如上案例nginx.ingress.kubernetes.io/use-regex: true最终是在生成nginx配置中会采用location ~来表示正则匹配。kubectl get ingressclasses类跨名称空间的他在所有名称空间下都有会关联一个控制器创建一个ingress controller都会创建一个ingressclasses资源相关联等于是他的唯一id,注入配置是靠ingresscalsses找到控制器的2、tlstls用于定义https密钥、证书详见第七章节3、ingressClassName:见下一小节4、rulesrules中的pathType、backend以及defaultBackend见下下小节2. ingressClass.Name字段yaml [rootk8s-master-01 ~]# kubectl get ingressclass -o yaml # 可以查看到名为nginx的控制器 apiVersion: v1 items: - apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: ...... name: nginx # 这个名字就是你在创建ingress对象时引用的ingressClassName名 spec: controller: k8s.io/ingress-nginx # 这个名字是在ingress-controller控制器启动args里指定的 kind: List metadata: resourceVersion: 注意如果你的k8s中安装了多个ingress控制器在创建ingress对象时你就需要用ingressClassName来选择你想要的ingress控制器由于一个集群中可能有多个 Ingress 控制器所以我们还可以将一个特定的IngressClass对象标记为集群默认是Ingress类。只需要将一个 IngressClass 资源的 ingressclass.kubernetes.io/is-default-class 注解设置为true即可这样未指定 ingressClassName 字段的 Ingress 就会使用这个默认的 IngressClass。apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: annotations: ingressclass.kubernetes.io/is-default-class: true如果集群中有多个 IngressClass 被标记为默认准入控制器将阻止创建新的未指定 ingressClassName 的 Ingress 对象。最好的方式还是确保集群中最多只能有一个 IngressClass 被标记为默认。3. rules字段rules字段用于指定请求路由转发规则。一、host提供了 host 域名则 rules 则会匹配该域名的相关请求此外 host 主机名可以是精确匹配例如 foo.bar.com或者使用通配符来匹配例如 *.foo.com。二、http.paths定义访问的路径列表比如上面定义的 /testpath每个路径都有一个由 backend.service.name 和 backend.service.port.number 定义关联的 Service 后端在控制器将流量路由到引用的服务之前host 和 path 都必须匹配传入的请求才行。三、backend该字段其实就是用来定义后端的 Service 服务的与路由规则中 host 和 path 匹配的流量会将发送到对应的 backend 后端去。了解Resourcebackend 后端除了可以引用一个 Service 服务之外还可以通过一个 resource 资源进行关联Resource 是当前 Ingress 对象命名空间下引用的另外一个 Kubernetes 资源对象Resource 后端的一种常见用法是将所有入站数据导向带有静态资产的对象存储后端但是需要注意的是 Resource 与 Service 配置是互斥的只能配置一个如下所示apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-resource-backend spec: rules: - http: paths: - path: /icons pathType: ImplementationSpecific backend: resource: apiGroup: k8s.example.com kind: StorageBucket name: icon-assets该 Ingress 资源对象描述了所有的 /icons 请求会被路由到同命名空间下的名为 icon-assets 的 StorageBucket 资源中去进行处理。四、pathType字段事实上每个路径都需要有对应的路径类型当前支持的pathType 路径类型有三种kubectl explain ingress.spec.rules.http.paths.pathType FIELD: pathType string ENUM: Exact ImplementationSpecific PrefixExact精确/完全: 请求必须精确地匹配指定的路径、且区分大小写。例如如果路径设置为/foo则仅/foo会被匹配而/foo/或/foo/bar不会匹配。Prefix前缀: 基于以 / 分隔的 URL 路径前缀匹配匹配区分大小写。如果设置为/foo则任何以这个前缀开始的路径比如/foo、/foo/、/foo/bar都会被匹配。它不要求完全精确匹配只要求请求的路径以指定的path开头。ImplementationSpecific交给特定控制器实现: 当指定 pathType 为 ImplementationSpecific 时意味着匹配路径的具体行为将由所选的 Ingress 控制器来决定比如 nginx 或 traefik每个控制器可能会有它自己对路径匹配的解释和实现方式。在nginx的情况下这通常涉及到更多细微或复杂的匹配条件可能包括正则表达式或特定于nginx的行为。示例# 使用 ImplementationSpecific 类型的路径匹配方式具体行为由 Ingress Controller 决定 - path: /prefix-path pathType: Prefix backend: service: name: prefix-service port: number: 80 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress namespace: default spec: rules: - host: example.com http: paths: # 使用 Exact 类型的路径匹配方式路径必须与 /exact-path 完全一致 - path: /ip pathType: Exact backend: service: name: exact-service port: number: 80 --- # 使用 Prefix 类型的路径匹配方式任何以 /prefix-path 为前缀的路径都会匹配 - path: /prefix-path pathType: Prefix backend: service: name: prefix-service port: number: 80 --- # 使用 ImplementationSpecific 类型的路径匹配方式具体行为由 Ingress Controller 决定 - path: /regex-path pathType: ImplementationSpecific backend: service: name: regex-service port: number: 804. ingress-nginx的优化其实就是一个nginx内核有优化pstree -p uid 看一个ingressnginx的子进程5. 构建TLS站点deamser管理的ingress访问加上证书443https协议ssl证书#生成secret不需要挂载直接用ingress对象添加 kind: ingress spec: tls: - hosts: - test.ingress.com secretName: ingress-tls1、# 准备证书 openssl genrsa -out tls.key 2048 # 生成一个私钥 openssl req -new -x509 -key tls.key -out tls.crt -subj /CCN/STShangHai/LShangHai/OIngress/CNtest.ingress.com # 自签一个证书 2、# 生成secret不需要挂载直接用ingress对象添加 kubectl -n default create secret tls ingress-tls --certtls.crt --keytls.key你提供的这两条命令用于生成 RSA 私钥和自签名的 X.509 证书通常用于测试 HTTPS、Ingress 等场景具体解释如下 第一条命令生成 RSA 私钥 openssl genrsa -out tls.key 2048 genrsa指定生成 RSA 算法的私钥。 -out tls.key将生成的私钥保存到tls.key文件中。 2048指定私钥长度为 2048 位属于安全的长度兼顾安全性和性能。 执行后会在当前目录生成tls.key文件包含 2048 位的 RSA 私钥需妥善保管不可泄露。 第二条命令生成自签名证书 openssl req -new -x509 -key tls.key -out tls.crt -subj /CCN/STShangHai/LShangHai/OIngress/CNtest.ingress.com req处理证书请求Certificate Request的命令。 -new生成新的证书请求。 -x509跳过 “生成证书请求CSR” 步骤直接生成自签名的 X.509 证书无需 CA 机构签名。 -key tls.key指定使用前面生成的tls.key私钥来签名证书。 -out tls.crt将生成的证书保存到tls.crt文件中。 -subj指定证书的 “主题信息”避免交互式输入各字段含义 CCN国家CountryCN 代表中国。 STShangHai省份State这里是上海。 LShangHai城市Locality这里是上海。 OIngress组织Organization这里自定义为 “Ingress”。 CNtest.ingress.com通用名称Common Name通常是证书对应的域名后续访问该域名时证书会被匹配6. annotation一、域名重定向metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: https://www.baidu.com/s?wdegon二、设置白名单允许客户端的IP访问三、正则匹配七、发布策略什么是发布部署启用新代码发布过程中会遇到的问题1、发布过程中服务会暂时中断2、新版本遇到问题如何快速回滚总结为一个目标确保服务中断断时间不要过长于是诞生多种发布策略1. 滚动发布就一套环境在升级过程中并不是一下子启用所有新版本而是先启动一个新的再停一个老版本一点点向新版本滚动直到完成全部升级。如果环境中有10台机器只需要新增1台机器就可以滚动起来了优点1、节省机器、最小化停机时间、平滑过渡缺点1、新老版本共存在整个升级过程中极不稳定一旦访问出问题无法确定是新版本的问题还是老版本的问题关键是缺少对流量的控制2. 蓝绿发布蓝老绿新环境维度以整套环境基本单位来进行流量分发核心是部署两套环境两套环境的机器配置都一样老环境部署老版本新环境部署新版本在两套环境的基础上做流量的分配旧80%新20%然后逐步增加新环境的流量如果原环境中有10台机器新环境也需要有10台机器优点随时切换快速切回老环境也能抗住压力因为老环境原封不动的放着呢缺点耗费资源3. 金丝雀发布有时候会与灰度发布代表一个意思总体来说都是小范围尝试然后逐步扩大站在这个维度很多人会将金丝雀发布与灰度当成一个意思但细说的话有用法层面的区别流量维度站在整体流量的维度进行分配没有细分用户特征蓝绿有两套一样配置的环境流量分分配是以一个整个环境为单位分发的金丝雀先部署少数几台新版本然后采用流量的控制的方式逐步严重让一点一点扩大范围适用于迭代版本而不是大版本更新4. 灰度发布用户群体特征从所有用户中选出一些充当小白鼠从已经注册的用户中选出一部分给一点优惠让大家尝试新功能给你反馈发布方式先灰度验证再发正式环境关键区别金丝雀发布的流量分配不区分用户总结金丝雀发布可以被视为灰度发布的一种实现方式但灰度发布的范围更广涵盖了更多逐步发布的策略。(一) ingress-金丝雀发布四种Canary规则金丝雀发布小范围流量尝试然后逐步扩大控制流量的两大类方式1、基于权重canary-weight2、基于用户请求canary-by-header、 canary-by-header-value、canary-by-cookie