开发者学堂课程【企业级运维之云原生与 Kubernets 实战课程:负载均衡和路由 】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/913/detail/14650
负载均衡和路由
摘要:本小节主要内容为负载均衡和路由,包括 service、ingress 的工作原理及使用方法。
目录
Ÿ 阿里云容器服务集群 service
Ÿ 阿里云容器服务集群 ingress
一、阿里云容器服务集群 service
K8s 作为容器编排工具,实现容器内服务访问入口有两种方式:
Ÿ 阿里云容器服务集群 service,通过 SVC 方式为前端微服务或者客户端暴露入口地址,由 SVC 负载均衡到后端的 Pod 上,如果 Pod 因删除重建,SVC 会通过控制器 将删除的 Pod 从 endpoint 中进行删除,流量将不会打到已删除的 Pod 上,SVC 为四层负载均衡,无法实现七层负载均衡,需要借助阿里云容器服务集群ingress。
Ÿ 阿里云容器服务集群 ingress。
1. 负载均衡类型的 service 实现原理
Loadblance 类型的服务:在使用一个集群内部 IP 地址和在 NodePort 上开放一个服务之外,向云提供商申请一个负载均衡器,会让流量转发到这个在每个节点上以:NodePort 的形式开放的服务上。
发布服务有四种服务类型
Ÿ ClusterIP:通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是默认的 ServiceType。
Ÿ NodePort:通过每个节点上的 IP 和静态端口(NodePort)暴露服务。 NodePort 服务会路由到自动创建的 ClusterIP 服务。通过请求 <节点 IP >:<节点端口>,可以从集群的外部访问一个 NodePort 服务,而<节点端口>是有节点自动创建。NodePort 流量如何转发到后端 Pod 内呢?首先将客户端访问节点 IP 和端口作为一个包重定向到 ClusterIP 类型的 SVC 上,然后由 ClusterIP 负载均衡到某个 Pod 上。
Ÿ LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上,登录阿里云平台可以进行 slb 监听创建及配置。
Ÿ ExternalName:通过返回 CNAME 和对应值,可以将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。无需创建任何类型代理。
关键组件:阿里云 cloud-controller-manager
Ÿ 创建 LoadBalancer 类型的 service;
Ÿ CCM 监听到对应的请求,解析 service 中的字段;
Ÿ 根据 service 配置决定是否创建 slb,如果未指定 slb 则会新建 slb;
Ÿ CCM 根据 service.endpoint 配置来调用 slb 接口更新 slb ,并根据 service 变更来维护 slb 生命周期。
2. 通过 Annotation 参数配置负载均衡
通过 Service YAML 文件中的 Annotation (注解),指定已有 SLB 的 ID 的方式或者 SLB 的类型,可以实现丰富的负载均衡功能。
3. 注意事项
CCM 组件创建出来的 SLB 配置,尽量不要手动直接修改,由集群根据 Service 的 Yaml 自动配置。
二、阿里云容器服务集群 Ingress
1. IngressController 工作原理
Ingress 是一种 K8s 资源对象,用于对外暴露服务。该资源对象定义了不同主机名(域名)及 URL 和对应后端 Service (K8s Service) 的绑定,根据不同的路径路由 http 和 https 流量。
而 Ingress Contoller 是一个 Pod 服务,封装了一个 web 前端负载均衡器,同时在其基础上实现了动态感知 Ingress 并根据 Ingress 的定义动态生成前端 web 负载均衡器的配置文件,比如 Nginx Ingress Controller 本质上就是一个 Nginx,只不过它能根据 Ingress 资源的定义动态生成 Nginx 的配置文件,然后动态 Reload。
为了使得 Ingress 资源正常工作,集群中必须要有个 Ingress Controller 来解析 Ingress 的转发规则。Ingress Controller 收到请求, 匹配 Ingress 转发规则转发到后端 Service,而 Service 转发到 Pod,最终由 Pod 处理请求。
Kubernetes 中,Service、Ingress 与 Ingress Controller 有着以下关系:
Ÿ Service 是后端真实服务的抽象, 一个 Service 可以代表多个相同的后端服务;
Ÿ Ingress 是反向代理规则,用来规定 HTTP/HTTPS 请求应该被转发到哪个 Service 上。例如根据请求中不同的 Host 和 URL 路径,让请求落到不同的 Service 上;
Ÿ Ingress 是反向代理规则,用来规定 HTTP/HTTPS 请求应该被转发到哪个 Service 上。例如根据请求中不同的 Host 和 URL 路径,让请求落到不同的 Service 上。
2. Ingress 基本操作
a. 创建 Deployment 和 Service
apiVersion:apps/v1
kind:Deployment
metadata:
name:test-web1
lables:
app:test-web1
spec:
replicas:1
selector:
matchLabls:
app:test-web1
spec:
containers:
- name:test-web1
imagePullPolicy:ifNotPresent
image: registry.cn-hangzhou.aliyuncs.com/yilong/ingress-test:webi
ports:
- containerPort:8080
---
apiVersion:v1
kind: Service
metadata:
name: webl-service
spec:
type: ClusterIP
selector:
app: test-web1
ports:port:8080
targetPot:8080
b. 创建 Ingress
apiVersion:networking.k8s.io/v1betal
kind:Ingress
metadata:
name:test-ingress
namespace:default
spec:
rules:
- host:test-ingress.com
http:
- path:/foo
backend:SeviceName:webl-service
servicePort:8080
- path:/bar
backend:
serviceName:webl-service
servicePort:8080
name:Ingress 的名称,本例为 test-ingress
host:指定服务访问域名
path:指定访问的 url 路径。SLB 将流量转发到 bACKend 之前,所有的入站请求都要先匹配 host 和 path
bACKend:由服务名称和服务端口组成
服务名称:Ingress 转发的 bACKend 服务名称
服务端口:服务暴露的端口
3. Ingress 高级用法
a. 配置 URL 重定向的路由服务
示例:
apiversion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: rewrite-test-ingress
namespace: default
annotations:
#URL重定向
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
-host:rewrite-test-ingress.com
http:
paths:
- path:/svc/(.*)
backend:
serviceName: web1-service
servicePort: 80
Rewrite配置
使用 inginx.ingress.kubernetes.io/rewrite-target
,注解支持基本的Rewrite 配置,对于一些复杂高级的 Rewrite 需求,可以通过如下注解来实现:
Ÿ nginx.ingress.kubernetes.io/server-snippet
:扩展配置到 Location 章节;
Ÿ nginx.ingress.kubernetes.io/configuration-snippet
:扩展配置到 Server 章节;
b. 配置安全的路由服务(https)
(1)准备服务证书(域名需要与您的 Ingress 配置保持一致);
Ÿ 执行以下命令,生成一个证书文件 tls.crt 和一个私钥文件 tls.key
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=foo.bar.com/O=foo.bar.com"
Ÿ 执行下命令,创建密钥;
kubectl create secret tls tls-test-ingress --key tls.key --cert tls.crt
(2)创建一个安全的 Ingress 服务;
apiversion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-test-ingress
spec:
#安全路由
tls:
- hosts:
#secret 跟 ingress 同一 namespac
- tls-test-ingress.com
secretName: tls-test-ingress
rules:
- host: tls-test-ingress.com
http:
paths:
- path:/foo
backend:
serviceName: web1-svc
servicePort: 80
c. 通过注解实现灰度发布
可以基于如下方法进行发布:
Ÿ 基于权重灰度:配置灰度服务的权重为 20%;
Ÿ 基于 header 灰度:请求 header 为 ACK:always 时,将访问灰度服务;请求header 为 ACK:never 时,将不访问灰度服务;其它 header 将根据灰度权重将流量分配给灰度服务;
Ÿ 基于 header 灰度(自定义 header 值):当请求 header 为 ACK:alibaba 时,将访问灰度服务;其他 header 将根据灰度权重将流量分配给灰度服务;
Ÿ 基于 cookie 灰度:当 header 不匹配时,请求的 cookie 为hangzhou_region=always
时,将访问灰度服务。
4. Ingress 常见问题
Q:Ingress 支持哪些 SSL/TLS 版本?
A:Ingress-Nginx 默认仅支持 TLS V1.2 版本,对于部分旧版本的浏览器,或者移动客户端 TLS 版本低于 1.2 时,会导致客户端在与 Ingress-Nginx 服务 SSL 版本协商时报错。
执行以下命令,修改kube-system/nginx-configuration ConfigMap
添加以下配置,为 Ingress-Nginx 开启支持更多 TLS 版本的功能。
ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256: ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHERSA-AES256-GCM-SHA384: ECDHE-ECDSA-CHACHA20-POLY1305: ECDHE-RSA-CHACHA20-POLY1305: DHE-RSA-AES128-GCM-SHA256: DHE-RSA-AES256-GCM-SHA384: DHE-RSA-CHACHA20-POLY1305: ECDHE-ECDSA-AES128-SHA256: ECDHE-RSA-AES128-SHA256: ECDHE-ECDSA-AES128-SHA: ECDHE-RSA-AES128-SHA: ECDHE-ECDSA-AES256-SHA384: ECDHE-RSA-AES256-SHA384: ECDHEECDSA-AES256-SHA: ECDHE-RSA-AES256-SHA: DHE-RSA-AES128-SHA256: DHE-RSA-AES256-SHA256: AES128-GCM-SHA256: AES256GCM-SHA384: AES128-SHA256: AES256-SHA256: AES128-SHA: AES256-SHA: DES-CBC3-SHA" ssl-protocols: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3"