【Kubernetes】K8s笔记(十一):Ingress 集群进出流量总管
0. Ingress 解决了什么问题
上一篇笔记中讲解了 Service 的功能和运行机制。Service 本质上是一个由 kube-proxy 控制的四层负载均衡,在 TCP/IP 协议栈上转发流量。然而四层负载均衡能做的很有限,现在绝大多应用运行在应用层(五层/ OSI 七层)的 HTTP/HTTPS 协议之上,有更多的高级路由条件,而这些在传输层是不可见的。
Service 比较适合代理集群内部的服务。如果想要把服务暴露到集群外部,就只能使用 NodePort 或者 LoadBalancer 这两种方式,而它们都缺乏足够的灵活性,难以管控。
Kubernetes 为了解决这个问题,引入了一个新的 API 对象做七层负载均衡。除了七层负载均衡,这个对象还承担了更多的职责——作为流量的总入口,管理进出集群的数据(南北向流量),让外部用户能够安全便捷地访问集群内部的服务。这个 API 对象被命名为 Ingress,意思就是集群内外边界上的入口。
*图示是一个将所有流量都发送到同一 Service 的简单 Ingress 示例 图片来源
1. Ingress Controller
Service 本身是没有服务能力的,它只是一些 iptables
规则,真正配置、应用这些规则的实际上是节点里的 kube-proxy 组件。如果没有 kube-proxy,Service 定义得再完善也没有用。
同样的,Ingress 也只是一些 HTTP 路由规则的集合,相当于一份静态的描述文件,真正要把这些规则在集群里实施运行,还需要有另外一个东西,这就是 Ingress Controller,它的作用就相当于 Service 的 kube-proxy,能够读取、应用 Ingress 规则,处理、调度流量。
为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。Ingress 控制器不是随集群自动启动的,用户可以选择最适合集群的 Ingress 控制器实现。Kubernetes 目前支持和维护 AWS、 GCE 和 Nginx Ingress 控制器。还有很多控制器可供选择。
从 Ingress Controller 的描述上我们也可以看到,HTTP 层面的流量管理、安全控制等功能其实就是经典的反向代理,而 Nginx 则是其中稳定性最好、性能最高的产品,所以它也理所当然成为了 Kubernetes 里应用得最广泛的 Ingress Controller。不过,因为 Nginx 是开源的,谁都可以基于源码做二次开发,所以它又有很多的变种。这里我们选取 Nginx 对 Ingress Controller 的开发实现 NGINX Ingress Controller。
*图示展示了 Ingress Controller 在集群中的位置 图片来源
2. 指定 Ingress Class 使用多个 Ingress Controller
起初,Kubernetes 集群内只有一个 Ingress Controller,这样的用法会带来一些问题:
由于某些原因,项目组需要引入不同的 Ingress Controller,但 Kubernetes 不允许这样做
Ingress 规则太多,都交给一个 Ingress Controller 处理会让它不堪重负
多个 Ingress 对象没有很好的逻辑分组方式,管理和维护成本很高
集群里有不同的租户,他们对 Ingress 的需求差异很大甚至有冲突,无法部署在同一个 Ingress Controller 上
Kubernetes 就又提出了一个 Ingress Class 的概念,让它插在 Ingress 和 Ingress Controller 中间,作为流量规则和控制器的协调人,解除了 Ingress 和 Ingress Controller 的强绑定关系。
Kubernetes 用户可以转向管理 Ingress Class,用它来定义不同的业务逻辑分组,简化 Ingress 规则的复杂度。比如说,我们可以用 Class A 处理博客流量、Class B 处理短视频流量、Class C 处理购物流量。这些 Ingress 和 Ingress Controller 彼此独立,不会发生冲突。
3. 使用 YAML 描述 Ingress / Ingress Class
首先用命令 kubectl api-resources
查看它们的基本信息:
NAME SHORTNAMES APIVERSION NAMESPACED KIND
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
*Ingress Controller 是一个处理流量的应用程序,稍后可以使用 Deployment 和 DaemonSet 来部署
3.1 Ingress
Ingress 可以使用 kubectl create
来创建样板文件,它需要用两个附加参数:
--class
- 指定 Ingress 从属的 Ingress Class 对象--rule
- 指定路由规则,基本形式是URI=Service
,也就是说是访问 HTTP 路径就转发到对应的 Service 对象,再由 Service 对象转发给后端的 Pod
$ export out="--dry-run=client -o yaml"
$ kubectl create ing ngx-ing --rule="ngx.test/=ngx-svc:80" --class=ngx-ink $out
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ngx-ing
spec:
ingressClassName: ngx-ink
rules:
- host: ngx.test
http:
paths:
- backend:
service:
name: ngx-svc
port:
number: 80
path: /
pathType: Exact
这份 YAML 文档中有两个关键字段 ingressClassName
和 rules
,rules
的格式稍显复杂:它将路由规则拆散为 host
和 http path
,在 path
里又指定了路径的匹配方式,可以是精确匹配 Exact
或者是前缀匹配 Prefix
,再用 backend
来指定转发的目标 Service 对象。
3.2 Ingress Class
Ingress Class 本身并没有什么实际的功能,只是起到联系 Ingress 和 Ingress Controller 的作用,所以它的定义非常简单,在 spec
里只有一个必需的字段 controller
,表示要使用哪个 Ingress Controller,具体的名字就要看实现文档了。
比如,要使用 Nginx 开发的 Ingress Controller,那么就要用名字 nginx.org/ingress-controller
:
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: ngx-ink
spec:
controller: nginx.org/ingress-controller
4. 使用 Ingress / Ingress Class
使用 kubectl apply
创建 Ingress 和 Ingress Class 这两个对象:
$ kubectl apply -f ngx-ing-class.yaml
ingressclass.networking.k8s.io/ngx-ink created
$ kubectl apply -f ngx-ing.yaml
ingress.networking.k8s.io/ngx-ing created
然后我们查看 Ingress 和 Ingress Class 的状态:
$ kubectl get ingress -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
ngx-ing ngx-ink ngx.test 80 67s
$ kubectl get ingressclass -o wide
NAME CONTROLLER PARAMETERS AGE
ngx-ink nginx.org/ingress-controller <none> 84s
可以使用 kubectl describe
查看详细的信息:
$ kubectl describe ing ngx-ing
Name: ngx-ing
Labels: <none>
Namespace: default
Address:
Ingress Class: ngx-ink
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
ngx.test
/ ngx-svc:80 (10.10.1.38:80,10.10.1.40:80,10.10.1.41:80)
Annotations: <none>
Events: <none>
可以看到 Ingress 对象的路由规则 Host/Path
就是在 YAML 里设置的域名 ngx.test/
。
5. 使用 Ingress Controller
准备好了 Ingress 和 Ingress Class,接下来就需要部署真正处理路由规则的 Ingress Controller。
Nginx Ingress Controller 以 Pod 的形式运行在 Kubernetes 里,同时支持 Deployment 和 DaemonSet 两种部署方式。我们现在根据 Nginx Ingress Controller Installation Docs 部署 Nginx Ingress Controller。
在使用 kubectl
的主机上首先克隆仓库并进入部署文件夹:
$ git clone https://github.com/nginxinc/kubernetes-ingress.git --branch v2.4.1
$ cd kubernetes-ingress/deployments
Nginx Ingress Controller 的安装略微麻烦一些,有很多个 YAML 需要执行,但如果只是做简单的试验,就只需要用到 4 个 YAML:
$ kubectl apply -f common/ns-and-sa.yaml
namespace/nginx-ingress created
serviceaccount/nginx-ingress created
$ kubectl apply -f rbac/rbac.yaml
clusterrole.rbac.authorization.k8s.io/nginx-ingress created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress created
$ kubectl apply -f common/nginx-config.yaml
configmap/nginx-config created
$ kubectl apply -f common/default-server-secret.yaml
secret/default-server-secret created
前两条命令为 Ingress Controller 创建了一个独立的名字空间 nginx-ingress
,还有相应的账号和权限,这是为了访问 apiserver 获取 Service、Endpoint 信息用的;后两条则是创建了一个 ConfigMap 和 Secret,用来配置 HTTP/HTTPS 服务。
接下来我们还需要部署一些 Custom Resources,没有它们我们部署的 Ingress Controller 就无法运行:
默认情况下,需要为虚拟服务器、虚拟服务器路由、传输服务器和策略创建自定义资源的定义。否则,Ingress Controller Pod 将不会变为 Ready 状态。如果要禁用该要求,请将
-enable-custom-resources
命令行参数配置为Readyfalse
并跳过此部分。
$ kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
customresourcedefinition.apiextensions.k8s.io/policies.k8s.nginx.org created
$ kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
customresourcedefinition.apiextensions.k8s.io/transportservers.k8s.nginx.org created
$ kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
customresourcedefinition.apiextensions.k8s.io/virtualserverroutes.k8s.nginx.org created
$ kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
customresourcedefinition.apiextensions.k8s.io/virtualservers.k8s.nginx.org created
部署 Ingress Controller 不需要我们自己从头编写 Deployment,Nginx 已经为我们提供了示例 YAML (位置是:kubernetes-ingress/deployments/deployment/nginx-ingress.yaml
),现在我们对其进行一些小小的改动:
metadata
里的name
要改成自己的名字,比如ngx-ing-dep
spec.selector
和template.metadata.labels
也要修改成自己的名字,比如还是用ngx-ing-dep
containers.image
可以改用apline
版本,加快下载速度,比如nginx/nginx-ingress:2.2-alpine
最下面的
args
要加上-ingress-class=ngx-ink
,也就是前面创建的 Ingress Class 的名字,这是让 Ingress Controller 管理 Ingress 的关键
apiVersion: apps/v1
kind: Deployment
metadata:
name: ngx-ing-dep
namespace: nginx-ingress
spec:
replicas: 1
selector:
matchLabels:
app: ngx-ing-dep
template:
metadata:
labels:
app: ngx-ing-dep
spec:
serviceAccountName: nginx-ingress
automountServiceAccountToken: true
containers:
- image: nginx/nginx-ingress:2.2-alpine
imagePullPolicy: IfNotPresent
name: nginx-ingress
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
- name: readiness-port
containerPort: 8081
- name: prometheus
containerPort: 9113
readinessProbe:
httpGet:
path: /nginx-ready
port: readiness-port
periodSeconds: 1
resources:
requests:
cpu: "100m"
memory: "128Mi"
securityContext:
allowPrivilegeEscalation: true
runAsUser: 101 #nginx
runAsNonRoot: true
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
- -ingress-class=ngx-ink
有了 Ingress Controller,这些 API 对象的关联就更复杂了。然后我们创建对象:
$ kubectl apply -f ngx-ing-dep.yaml
deployment.apps/ngx-ing-dep created
注意 Ingress Controller 位于名字空间 nginx-ingress
,所以查看状态需要用 -n
参数显式指定,否则我们只能看到 default
名字空间里的 Pod:
$ kubectl get deploy -n nginx-ingress
NAME READY UP-TO-DATE AVAILABLE AGE
ngx-ing-dep 1/1 1 1 10m
$ kubectl get pod -n nginx-ingress
NAME READY STATUS RESTARTS AGE
ngx-ing-dep-7c48c74865-vzmnf 1/1 Running 0 11m
现在 Ingress Controller 就算是运行起来了。还有最后一道工序,因为 Ingress Controller 本身也是一个 Pod,想要向外提供服务还是要依赖于 Service 对象。所以至少还要再为它定义一个 Service,使用 NodePort 或者 LoadBalancer 暴露端口,才能真正把集群的内外流量打通。
这里还有个取巧的办法,使用 kubectl port-forward
直接把本地的端口映射到 Kubernetes 集群的某个 Pod 里,在测试验证的时候非常方便。
$ kubectl port-forward -n nginx-ingress ngx-ing-dep-7c48c74865-vzmnf 8080:80 &
可以修改 /etc/hosts
来手工添加域名解析,也可以使用 --resolve
参数,指定域名的解析规则,比如在这里把 ngx.test
强制解析到 127.0.0.1
,也就是被 kubectl port-forward
转发的本地地址。
和 Service 一样,Ingress 把请求转发到了集群内部的 Pod,但 Ingress 的路由规则不再是 IP 地址,而是 HTTP 协议里的域名、URI 等要素。
再补充一点,目前的 Kubernetes 流量管理功能主要集中在 Ingress Controller 上,已经远不止于管理“入口流量”了,它还能管理“出口流量”,也就是 egress,甚至还可以管理集群内部服务之间的“东西向流量”。此外,Ingress Controller 通常还有很多的其他功能,比如 TLS 终止、网络应用防火墙、限流限速、流量拆分、身份认证、访问控制等等,完全可以认为它是一个全功能的反向代理或者网关。
【Kubernetes】K8s笔记(十一):Ingress 集群进出流量总管的更多相关文章
- 简单操作:10分钟实现在kubernetes(k8s)里面部署服务器集群并访问项目(docker三)
前言 经过docker安装.k8s开启并登录,我们终于到 "部署k8s服务器集群并访问项目" 这一步了,实现的过程中有太多坑,好在都填平了,普天同庆. 在进行当前课题之前,我们需要 ...
- Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录
0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 k8s架构目录:Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录 一.感谢 在此感谢.net ...
- Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列之集群部署环境规划(一)
0.前言 整体架构目录:ASP.NET Core分布式项目实战-目录 k8s架构目录:Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录 一.环境规划 软件 版本 ...
- Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列之自签TLS证书及Etcd集群部署(二)
0.前言 整体架构目录:ASP.NET Core分布式项目实战-目录 k8s架构目录:Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录 一.服务器设置 1.把每一 ...
- Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列之flanneld网络介绍及部署(三)
0.前言 整体架构目录:ASP.NET Core分布式项目实战-目录 k8s架构目录:Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录 一.flanneld介绍 ...
- Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列之部署master/node节点组件(四)
0.前言 整体架构目录:ASP.NET Core分布式项目实战-目录 k8s架构目录:Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录 1.部署master组件 ...
- K8S部署Redis Cluster集群(三主三从模式) - 部署笔记
一.Redis 介绍 Redis代表REmote DIctionary Server是一种开源的内存中数据存储,通常用作数据库,缓存或消息代理.它可以存储和操作高级数据类型,例如列表,地图,集合和排序 ...
- kubernetes将集群外部流量引入集群内
一.service:pod是有生命周期的,我们想给客户一个固定的访问端点,在客户端与服务端之间启动一个固定的中间层,依赖于kubernetes的一个附件CoreDns.kubernetes有三类网路地 ...
- Kubernetes 部署 Nebula 图数据库集群
Kubernetes 是什么 Kubernetes 是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes 的目标是让部署容器化的应用简单并且高效,Kubernetes 提供了应 ...
随机推荐
- 【Go实战基础】GO语言是什么,有哪些优势
一.简介 2007年,为了提高在多核.网络机器(networked machines).大型代码库(codebases)的业务场景下的开发效率,Google 首席软件工程师决定创造一种语言那就是 Go ...
- CAD二次开发(.net)优秀网站分享
Autodesk官方网站 官方帮助文档:AutoCAD 2016 帮助: Managed .NET Developer's Guide (.NET) (autodesk.com) DXF帮助手册:DX ...
- 前端利器躬行记(8)——VSCode插件研发
VSCode提供了丰富的 API,可以借助编辑器扩展许多定制功能. 本次研发了一款名为 Search Method 的插件,在此记录整个研发过程. 一.准备工作 1)安装环境 首先是全局安装 yo 和 ...
- Python获取时光网电影数据
Python获取时光网电影数据 一.前言 有时候觉得电影真是人类有史以来最伟大的发明,我喜欢看电影,看电影可以让我们增长见闻,学习知识.从某种角度上而言,电影凭借自身独有的魅力大大延长了人类的&quo ...
- 大促活动如何抵御大流量 DDoS 攻击?
每一次活动大促带来的迅猛流量,对技术人而言都是一次严峻考验.如果在活动期间遭受黑产恶意DDoS攻击,无疑是雪上加霜.电商的特性是业务常态下通常不会遭受大流量DDoS攻击,且对延迟敏感,因此只需要在活动 ...
- Order Siblings by 排序
在层次查询中,如果想让"亲兄弟"按规矩进行升序排序就需要使用ORDER SIBLINGS BY 这个特定的排序语句,若要降序输出可以在其后添加DESC关键字. 通过这个实验给大家展 ...
- docker-compose入门--翻译
在这一页,你将学习到如何构建一个简单的python的web应用,并通过Docker compose来运行.这个应用程序使用的是Flask框架,并维护着一个存储在reids里的点击计数器.由于这个案例使 ...
- PLM产品生命周期管理,包含哪些阶段?
PLM:Product Lifecycle Management=产品生命周期管理.产品的整个生命周期包括:投入期.成长期.成熟期.衰退期.结束期.PLM系统使企业可以把多年积累的所有产品相关数据放到 ...
- .NET 7 RC1 正式发布
从年初2 月份发布第一个预览版,经历7个预览版后,Microsoft 西雅图时间9月14日发布了 .NET 7 RC 1:https://devblogs.microsoft.com/dotnet/a ...
- 【前端】在浏览器控制台,直接发Ajax请求
我们在日常的开发的过程中,经常需要前端测试发送请求测试一些数据.但是由于一些session,cookie的存在,我们无法在postman上创建一些会话.那么这样,我们就可以在浏览器上直接发送Ajax请 ...