企业级运维之云原生与Kubernetes实战课程
第二章第4讲 负载均衡和路由
视频地址: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上开放一个服务之外,向云提供商申请一个负载均衡器,会让流量转发到这个在每个节点上以<NodelP>: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"