电子商务毕业设计设计电商网站建设,网络营销方案500字,丰涵网站建设,电子工程网官方网站1 Ingress 概述
Kubernetes 对外暴露服务#xff08;Service#xff09;主要有两种方式#xff1a;NodePort#xff0c;LoadBalance#xff0c;此外 externalIps 也可以使各类 service 对外提供服务#xff0c;但是当集群服务很多的时候#xff0c;NodePort方式最大的缺…1 Ingress 概述
Kubernetes 对外暴露服务Service主要有两种方式NodePortLoadBalance此外 externalIps 也可以使各类 service 对外提供服务但是当集群服务很多的时候NodePort方式最大的缺点是会占用很多集群机器的端口LB方式最大的缺点则是每个Service一个LB又有点浪费和麻烦并且需要K8s之外的支持而 Ingress 则只需要一个 NodePort或者一个LB就可以满足所有 Service 对外服务的需求。工作机制大致如下图 Ingress为Kubernetes集群中的服务提供了入口可以提供负载均衡、SSL终止和基于名称的虚拟主机在生产环境中常用的Ingress有Treafik、Nginx、HAProxy、Istio等。
Ingress用于从集群外部到集群内部Service的HTTP和HTTPS路由流量从Internet到Ingress再到Services最后到Pod上通常情况下Ingress部署在所有的Node节点上。
Ingress可以配置提供服务外部访问的URL、负载均衡、终止SSL并提供基于域名的虚拟主机。但Ingress不会暴露任意端口或协议。
2 为什么需要Ingress资源
由于K8S集群拥有强大的副本控制能力Pod随时可能从一个节点上被驱逐到另一个节点上或者直接销毁再来一个新的。
然而伴随着Pod的销毁和重生Pod的IP等信息不断地在改变此时使用K8S提供的Service机制可以解决这一问题Service通过标签选定指定的Pod作为后端服务并监听这些Pod的变化。
在对外暴露服务时使用Service的NodePort是一个方法但同时也面临以下问题
1如何管理端口 当需要对外暴露的服务量比较多的时候端口管理的问题变会暴露出来。
此时的一个处理方案是使用一个代理服务例如nginx根据请求信息将请求转发到不同的服务器上。
2如何管理转发配置 每当有新服务加入都需要对该服务的配置进行修改、升级在服务数量逐渐变多后该配置项目会变得越来越大手工修改的风险也会逐渐增高。
那么需要一个工具来简化这一过程希望可以通过简单的配置动态生成代理中复杂的配置最好还可以顺手重新加载配置文件。
K8S刚好也提供了此类型资源。
2.1 Pod漂移问题
众所周知 Kubernetes 具有强大的副本控制能力能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的还可以动态扩容等总之一句话这个 Pod 可能在任何时刻出现在任何节点上也可能在任何时刻死在任何节点上那么自然随着 Pod 的创建和销毁Pod IP 肯定会动态变化那么如何把这个动态的 Pod IP 暴露出去这里借助于 Kubernetes 的 Service 机制Service 可以以标签的形式选定一组带有指定标签的 Pod并监控和自动负载他们的 Pod IP那么我们向外暴露只暴露 Service IP 就行了这就是 NodePort 模式即在每个节点上开起一个端口然后转发到内部 Pod IP 上如下图所示 2.2 端口管理问题
采用 NodePort 方式暴露服务面临一个问题是当服务一旦多起来NodePort 在每个节点上开启的端口会及其庞大而且难以维护这时候引出的思考问题是 “能不能使用 Nginx 啥的只监听一个端口比如 80然后按照域名向后转发” 这思路很好简单的实现就是使用 DaemonSet 在每个 node 上监听 80然后写好规则因为 Nginx 外面绑定了宿主机 80 端口(就像 NodePort)本身又在集群内那么向后直接转发到相应 Service IP 就行了如下图所示 2.3 域名分配及动态更新问题
从上面的思路采用 Nginx 似乎已经解决了问题但是其实这里面有一个很大缺陷每次有新服务加入怎么改 Nginx 配置总不能手动改或者来个 Rolling Update 前端 Nginx Pod 吧这时候 “伟大而又正直勇敢的” Ingress 登场如果不算上面的 NginxIngress 只有两大组件Ingress Controller 和 Ingress。
Ingress 简单的理解就是 原来要改 Nginx 配置然后配置各种域名对应哪个 Service现在把这个动作抽象出来变成一个 Ingress 对象可以用 yml 创建每次不要去改 Nginx 了直接改 yml 然后创建/更新就行了那么问题来了”Nginx 怎么办”
Ingress Controller 这东西就是解决 “Nginx 怎么动态调整”的Ingress Controoler 通过与 Kubernetes API 交互动态的去感知集群中 Ingress 规则变化然后读取按照根据ingress规则模板生成一段 Nginx 配置再写到 Nginx Pod 里最后 reload 一下工作流程如下图 当然在实际应用中最新版本 Kubernetes 已经将 Nginx 与 Ingress Controller 合并为一个组件所以 Nginx 无需单独部署只需要部署 Ingress Controller 即可 。
3 Ingress的工作方式
Ingress 工作原理 1ingress-controller通过和 kubernetes APIServer 交互动态的去感知集群中ingress规则变化 2然后读取ingress规则按照自定义的规则规则就是写明了哪个域名对应哪个service生成一段nginx配置 3将nginx配置写到nginx-ingress-controller的pod里这个ingress-controller的pod里运行着一个Nginx服务控制器会把生成的 nginx配置写入 /etc/nginx.conf文件中 4然后reload一下使配置生效。以此达到域名区分配置和动态更新的作用。
在使用普通的Service时集群中每个节点的kube-proxy在监听到Service和Endpoints的变化时会动态的修改相关的iptables的转发规则。 客户端在访问时通过iptables设置的规则进行路由转发达到访问服务的目的。
而Ingress则跳过了kube-proxy这一层通过Ingress Controller中的代理配置进行路由转发达到访问目标服务的目的。
实际上可以把IngressController看做一个拥有默认处理后端的代理根据Ingress资源的配置动态修改代理的配置文件以实现按照规则转发请求的功能。
4 ingress源码配置结构
type Ingress struct {metav1.TypeMeta json:,inlinemetav1.ObjectMeta json:metadata,omitempty// Ingess配置。Spec IngressSpec json:spec,omitempty// Ingress资源当前状态。Status IngressStatus json:status,omitempty
}
type IngressSpec struct {// 默认的后端服务当不匹配所有的Ingress规则的时候使用。// 一般情况默认后端都在Ingress控制器中配置该字段不进行声明配置。// 如果没有主机或路径与 Ingress 对象中的 HTTP 请求匹配则流量将路由到您的默认后端。Backend *IngressBackend json:backend,omitempty// TLS配置。目前Ingress只支持443一种TLS端口。// 如果列表中有多个不同的hosts将会在ingress controller支持SNI的情况下,// 通过使用SNI TLS扩展中声明的主机名在同个端口下使用多路复用。TLS []IngressTLS json:tls,omitempty// Ingress的规则。未匹配到规则列表中规则的请求将会被转发到默认后端上。Rules []IngressRule json:rules,omitempty
}
type IngressBackend struct {// 服务名。ServiceName string json:serviceName// 服务的端口。ServicePort intstr.IntOrString json:servicePort
}
type IngressRule struct {// 域名。// 不能使用IP地址不能使用端口。对HTTP服务使用80端口HTTPS服务使用443端口。Host string json:host,omitempty// 域名下的具体转发规则。// 未定义的情况下会将请求转发至默认后端。IngressRuleValue json:,inline,omitempty
}
type IngressRuleValue struct {HTTP *HTTPIngressRuleValue json:http,omitempty
}
type HTTPIngressRuleValue struct {Paths []HTTPIngressPath json:paths
}
type HTTPIngressPath struct {// 匹配的路径必须以/为开头。// 未定义的情况下会将请求转发至默认后端。Path string json:path,omitempty// 处理请求的后端服务。Backend IngressBackend json:backend
}
5 部署使用Ingress
5.1 部署 nginx-ingress-controller
5.1.1 部署ingress-controller pod及相关资源
[rootk8s-master opt]# mkdir /opt/ingress
[rootk8s-master opt]# cd ingress/
[rootk8s-master ingress]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.25.0/deploy/static/mandatory.yaml
--2022-08-09 17:07:00-- https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.25.0/deploy/static/mandatory.yaml
正在解析主机 raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.110.133, 185.199.108.133, ...
正在连接 raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... 已连接。
已发出 HTTP 请求正在等待回应... 200 OK
长度5976 (5.8K) [text/plain]
正在保存至: “mandatory.yaml”100%[] 5,976 --.-K/s 用时 0s 2022-08-09 17:07:00 (99.1 MB/s) - 已保存 “mandatory.yaml” [5976/5976])[rootk8s-master ingress]# ll
总用量 8
-rw-r--r--. 1 root root 5976 8月 9 17:07 mandatory.yaml
官方下载地址
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.25.0/deploy/static/mandatory.yaml
上面的下载地址可能无法下载可用国内的Gitee地址
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.25.0/deploy/static/mandatory.yaml
wget https://gitee.com/mirrors/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml
# mandatory.yaml文件中包含了很多资源的创建包括namespace、ConfigMap、roleServiceAccount等等所有部署ingress-controller需要的资源。
5.2 修改ClusterRole资源配置
vim mandatory.yaml
......
apiVersion: rbac.authorization.k8s.io/v1beta1
#RBAC相关资源从1.17版本开始改用rbac.authorization.k8s.io/v1rbac.authorization.k8s.io/v1beta1在1.22版本即将弃用
kind: ClusterRole
metadata:name: nginx-ingress-clusterrolelabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
rules:- apiGroups:- resources:- configmaps- endpoints- nodes- pods- secretsverbs:- list- watch- apiGroups:- resources:- nodesverbs:- get- apiGroups:- resources:- servicesverbs:- get- list- watch- apiGroups:- extensions- networking.k8s.io # 0.25版本增加 networking.k8s.io Ingress 资源的 api resources:- ingressesverbs:- get- list- watch- apiGroups:- resources:- eventsverbs:- create- patch- apiGroups:- extensions- networking.k8s.io # 0.25版本增加 networking.k8s.io/v1 Ingress 资源的 api resources:- ingresses/statusverbs:- update
5.3 ingress 暴露服务的方式
方式一DeploymentLoadBalancer 模式的 Service
如果要把ingress部署在公有云那用这种方式比较合适。用Deployment部署ingress-controller创建一个 type为 LoadBalancer 的 service 关联这组 pod。大部分公有云都会为 LoadBalancer 的 service 自动创建一个负载均衡器通常还绑定了公网地址。 只要把域名解析指向该地址就实现了集群服务的对外暴露
方式二DaemonSetHostNetworknodeSelector
用DaemonSet结合nodeselector来部署ingress-controller到特定的node上然后使用HostNetwork直接把该pod与宿主机node的网络打通直接使用宿主机的80/433端口就能访问服务。这时ingress-controller所在的node机器就很类似传统架构的边缘节点比如机房入口的nginx服务器。该方式整个请求链路最简单性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口一个node只能部署一个ingress-controller pod。 比较适合大并发的生产环境使用。
方式三DeploymentNodePort模式的Service
同样用deployment模式部署ingress-controller并创建对应的service但是type为NodePort。这样ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。 NodePort方式暴露ingress虽然简单方便但是NodePort多了一层NAT在请求量级很大时可能对性能会有一定影响。
采用方式二DaemonSetHostNetworknodeSelector
5.4 指定 nginx-ingress-controller 运行在node02 节点
[rootk8s-master ingress]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 7d1h v1.21.3
k8s-node01 Ready none 7d1h v1.21.3
k8s-node02 Ready none 7d1h v1.21.3
[rootk8s-master ingress]# kubectl label node k8s-node02 ingresstrue
node/k8s-node02 labeled
[rootk8s-master ingress]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-master Ready control-plane,master 7d1h v1.21.3 beta.kubernetes.io/archamd64,beta.kubernetes.io/oslinux,kubernetes.io/archamd64,kubernetes.io/hostnamek8s-master,kubernetes.io/oslinux,node-role.kubernetes.io/control-plane,node-role.kubernetes.io/master,node.kubernetes.io/exclude-from-external-load-balancers
k8s-node01 Ready none 7d1h v1.21.3 beta.kubernetes.io/archamd64,beta.kubernetes.io/oslinux,disktypessd,kubernetes.io/archamd64,kubernetes.io/hostnamek8s-node01,kubernetes.io/oslinux
k8s-node02 Ready none 7d1h v1.21.3 beta.kubernetes.io/archamd64,beta.kubernetes.io/oslinux,ingresstrue,kubernetes.io/archamd64,kubernetes.io/hostnamek8s-node02,kubernetes.io/oslinux
5.5 修改Deployment 为 DaemoSet,指定节点运行并开启hostNetwork网络
vim mandatory.yaml
...
apiVersion: apps/v1
# 修改 kind
# kind: Deployment
kind: DaemonSet
metadata:name: nginx-ingress-controllernamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx
spec:
# 删除Replicas
# replicas: 1selector:matchLabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxtemplate:metadata:labels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxannotations:prometheus.io/port: 10254prometheus.io/scrape: truespec:# 使用主机网络hostNetwork: true# 选择节点运行nodeSelector:ingress: trueserviceAccountName: nginx-ingress-serviceaccount
......
5.6 在所有node节点上传nginx-ingress-controller 镜像压缩包
ingree.contro.tar.gz 到 /opt/ingress 目录并解压和加载镜像
cd /opt/ingress
tar zxvf ingree.contro.tar.gz
docker load -i ingree.contro.tar
或者使用docker pull拉取镜像
[rootk8s-master ingress]# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.30.0
5.7 启动nginx-ingress-controller
[rootk8s-master ingress]# kubectl apply -f mandatory.yaml
namespace/ingress-nginx unchanged
configmap/nginx-configuration unchanged
configmap/tcp-services unchanged
configmap/udp-services unchanged
serviceaccount/nginx-ingress-serviceaccount unchanged
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17, unavailable in v1.22; use rbac.authorization.k8s.io/v1 ClusterRole
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole unchanged
Warning: rbac.authorization.k8s.io/v1beta1 Role is deprecated in v1.17, unavailable in v1.22; use rbac.authorization.k8s.io/v1 Role
role.rbac.authorization.k8s.io/nginx-ingress-role unchanged
Warning: rbac.authorization.k8s.io/v1beta1 RoleBinding is deprecated in v1.17, unavailable in v1.22; use rbac.authorization.k8s.io/v1 RoleBinding
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding unchanged
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding is deprecated in v1.17, unavailable in v1.22; use rbac.authorization.k8s.io/v1 ClusterRoleBinding
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding unchanged
daemonset.apps/nginx-ingress-controller unchanged
[rootk8s-master ingress]# kubectl get pod -n ingress-nginx -o wide
//nginx-ingress-controller 已经运行 node02 节点
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-nhsxt 1/1 Running 0 50m 192.168.161.18 k8s-node02 none none
[rootk8s-master ingress]# kubectl get cm,daemonset -n ingress-nginx -o wide
NAME DATA AGE
configmap/ingress-controller-leader-nginx 0 45m
configmap/kube-root-ca.crt 1 67m
configmap/nginx-configuration 0 67m
configmap/tcp-services 0 67m
configmap/udp-services 0 67mNAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
daemonset.apps/nginx-ingress-controller 1 1 1 1 1 ingresstrue 67m nginx-ingress-controller quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.25.0 app.kubernetes.io/nameingress-nginx,app.kubernetes.io/part-ofingress-nginx
到 node02 节点查看
[rootk8s-node02 ingress]# netstat -lntp | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 117191/nginx: maste
tcp 0 0 0.0.0.0:8181 0.0.0.0:* LISTEN 117191/nginx: maste
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 117191/nginx: maste
tcp6 0 0 :::10254 :::* LISTEN 117165/nginx-ingres
tcp6 0 0 :::80 :::* LISTEN 117191/nginx: maste
tcp6 0 0 :::8181 :::* LISTEN 117191/nginx: maste
tcp6 0 0 :::443 :::* LISTEN 117191/nginx: maste
由于配置了 hostnetworknginx 已经在 node 主机本地监听 80/443/8181 端口。其中 8181 是 nginx-controller 默认配置的一个 default backendIngress 资源没有匹配的 rule 对象时流量就会被导向这个 default backend。 这样只要访问 node 主机有公网 IP就可以直接映射域名来对外网暴露服务了。如果要 nginx 高可用的话可以在多个 node上部署并在前面再搭建一套 LVSkeepalived 做负载均衡
5.8 创建ingress规则
创建一个deploy和svc
[rootk8s-master ingress]# vim service-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-app
spec:replicas: 2seleector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginx-app-svc
spec:type: ClusterIPports:- protocol: TCPprot: 80targetPort:selector:app: nginx
创建ingress
#方法一extensions/v1beta1 Ingress 在1.22版本即将弃用
vim ingress-app.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: nginx-app-ingress
spec:rules:- host: www.liang.comhttp:paths:- path: /backend:serviceName: nginx-app-svcservicePort: 80#方法二
vim ingress-app.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx-app-ingress
spec:rules:- host: www.liang.comhttp:paths:- path: /pathType: Prefixbackend:service:name: nginx-app-svcport:number: 80
[rootk8s-master ingress]# kubectl apply -f service-nginx.yaml
deployment.apps/nginx-app unchanged
service/nginx-app-svc created
[rootk8s-master ingress]# kubectl apply -f ingress-app.yaml
ingress.networking.k8s.io/nginx-app-ingress created
[rootk8s-master ingress]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-app-845d4d9dff-4m44r 0/1 Running 0 15m
nginx-app-845d4d9dff-cvxrz 0/1 Running 0 15m
[rootk8s-master ingress]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-app-ingress none www.liang.com 80 15m
5.9 测试访问
本地host添加域名解析
[rootk8s-master ingress]# vim /etc/hosts127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.161.16 k8s-master
192.168.161.17 k8s-node01
192.168.161.18 k8s-node02
192.168.161.18 www.liang.com
[rootk8s-master ingress]# curl www.liang.com
5.10 查看 nginx-ingress-controller
[rootk8s-master ingress]# kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-nhsxt 1/1 Running 0 123m 192.168.161.18 k8s-node02 none none
[rootk8s-master ingress]# kubectl exec -it nginx-ingress-controller-nhsxt -n ingress-nginx /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
www-datak8s-node02:/etc/nginx$ more /etc/nginx/nginx.conf
可以看到从 start server www.liang.com 到 end server www.liang.com 之间包含了此域名用于反向代理的配置