惠山网页制作,南沙网站建设优化,企业网站后台模板,自动设计logo的软件一、前言 本章节我们将了解K8S的相关网络概念#xff0c;包括K8S的网络通讯原理#xff0c;以及Service以及相关的概念#xff0c;包括Endpoint#xff0c;EndpointSlice#xff0c;Headless service#xff0c;Ingress等。
二、网络通讯原理和实现 同一K8S集群包括K8S的网络通讯原理以及Service以及相关的概念包括EndpointEndpointSliceHeadless serviceIngress等。
二、网络通讯原理和实现 同一K8S集群网络通信实现可以简化为以下几个模型Pod内容器之间的通信同一节点内Pod间的通信以及跨节点Pod的通信。 1、Pod内容器之间的通信 同一Pod内的容器是共享同一个网络命名空间的它们就像工作在同一台机器上可以使用localhost地址访问彼此的端口。其模型如下 我们来看下面实例其yaml文件如下
[rootk8s-master yaml]# cat network-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: network-pod
spec:containers:- name: busyboximage: busyboxcommand:- /bin/sh- -c- sleep 3000- name: nginximage: nginx:1.14.2ports:- containerPort: 80 该Pod包含两个容器busybox和nginx执行该文件创建Pod进入到 busybox容器访问nginx容器。
[rootk8s-master yaml]# kubectl exec -it network-pod -c busybox sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # curl
sh: curl: not found
/ # wget http://localhost
Connecting to localhost (127.0.0.1:80)
saving to index.html
index.html 100% |******************************************************************************************************************************************| 612 0:00:00 ETA
index.html saved
/ # cat index.html
!DOCTYPE html
html
head
titleWelcome to nginx!/title
style
... 可以看到在busybox容器中访问http://localhost可以获取到ngnix的页面。 2、同一节点内Pod间的通信 其通信模型如下图所示: 同一节点Pod都关联到同一个网桥地址段相同从容器内发送的数据从eh0网络接口发出再从veth接口出来发送给网桥。网桥判断目标地址如果是同一个地址段再由网桥发送给节点内部的对应Pod。 同样看个实例我们将上面的Pod拆解为两个。
[rootk8s-master yaml]# cat network-busybox-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: network-busybox-pod
spec:containers:- name: busyboximage: busyboxcommand:- /bin/sh- -c- sleep 3000
[rootk8s-master yaml]# cat network-nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: network-nginx-pod
spec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80 执行这两个文件创建Pod后进入busybox访问nginx(ip为10.244.36.80)。
[rootk8s-master yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
network-busybox-pod 1/1 Running 0 20m 10.244.36.79 k8s-node1 none none
network-nginx-pod 1/1 Running 0 19m 10.244.36.80 k8s-node1 none none
[rootk8s-master yaml]# kubectl exec -it network-busybox-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # wget http://10.244.36.80
Connecting to 10.244.36.80 (10.244.36.80:80)
saving to index.html
index.html 100% |*****************************************************************************************************************************************************************************************| 612 0:00:00 ETA
index.html saved 可以看到在busybox容器中访问http://10.244.36.80可以获取到ngnix的页面。 3、跨节点Pod间通信
其通信模型如下 当一个报文从一个节点容器发送到另一个节点容器报文先通过veth到网桥再到节点物理适配器通过网络传到其他节点的物理适配器在通过其网桥最终经过veth到达目标容器。这里需要有个前提pod 的IP地址 必须是唯一的 跨节点的网桥必须使用非重叠 地址段这个需要通过IP地址规划保证。 上面的实例中两个Pod都在k8s-node1节点上我们将上面的busybox的Pod调度到master节点上。删除busybox的Pod,并改写下yaml内容。
[rootk8s-master yaml]# cat network-busybox-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: network-busybox-pod
spec:containers:- name: busyboximage: busyboxcommand:- /bin/sh- -c- sleep 3000tolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoSchedule
执行该文件创建Pod可以看到新Pod调度到Master上
[rootk8s-master yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
network-busybox-pod 1/1 Running 0 20s 10.244.235.202 k8s-master none none
network-nginx-pod 1/1 Running 0 24m 10.244.36.80 k8s-node1 none none 进入该Pod访问nginx
[rootk8s-master yaml]# kubectl exec -it network-busybox-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # wget http://10.244.36.80
Connecting to 10.244.36.80 (10.244.36.80:80)
saving to index.html
index.html 100% |*****************************************************************************************************************************************************************************************| 612 0:00:00 ETA
index.html saved 可以看到在busybox容器中访问http://10.244.36.80可以获取到ngnix的页面。
三、Service Service是K8S的核心概念之一它是基于Pod上的业务网络层为同一组Pod提供统一的访问入口将请求负载转发到后端的Pod上其作用类似于业务网关。
1、Service创建 在创建Service之前我们先创建其后端应用该应用使用镜像tcy83/k8s-service-app,镜像java代码如下
Controller
RequestMapping(/k8s)
public class TestController {private static Integer appId;GetMapping(getServiceApp)ResponseBodypublic String getServiceApp(){return this this service app:generateAppId();}public static int generateAppId(){if(appId null){Random random new Random();appId random.nextInt(1000);}return appId;}
} 解释下该段代码当访问/k8s/getServiceApp,返回一段字符串显示应用的appId该appId在首次访问时随机分配后续访问将保持不变以便区别不同的应用实例。 接下来就采用Deployment部署3个该应用的pod。其中yaml文件内容如下
apiVersion: apps/v1
kind: Deployment
metadata:name: serviceapp-deploymentlabels:app: serviceapp-deployment
spec:replicas: 3selector:matchLabels:app: serviceapp-deploytemplate:metadata:labels:app: serviceapp-deployspec:containers:- name: k8s-service-app image: tcy83/k8s-service-app:0.1 ports:- containerPort: 8080
创建完成后我们看下pod运行情况
[rootk8s-master yaml]# kubectl get pod -l appserviceapp-deploy -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
serviceapp-deployment-649c69c89d-2k2hm 1/1 Running 0 90m 10.244.36.78 k8s-node1 none none
serviceapp-deployment-649c69c89d-h5s5g 1/1 Running 0 90m 10.244.36.119 k8s-node1 none none
serviceapp-deployment-649c69c89d-sjv55 1/1 Running 0 90m 10.244.36.123 k8s-node1 none none 根据pod的ip和port能成功访问每一个应用。
[rootk8s-master ~]# curl http://10.244.36.78:8080/k8s/getServiceApp
this this service app:400
[rootk8s-master ~]# curl http://10.244.36.119:8080/k8s/getServiceApp
this this service app:204
[rootk8s-master ~]# curl http://10.244.36.123:8080/k8s/getServiceApp
this this service app:813
接下来就是重点部分为这3个应用增加一个Service作为统一访问入口。
[rootk8s-master yaml]# cat service-app-sv.yaml
apiVersion: v1
kind: Service
metadata:name: service-app-service
spec:type: ClusterIPselector:app: serviceapp-deployports:- port: 80targetPort: 8080
其中的属性我们稍后再分析先执行下service-app-sv.yaml
[rootk8s-master yaml]# kubectl apply -f service-app-sv.yaml
service/service-app-service created
[rootk8s-master yaml]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 none 443/TCP 133d
service-app-service ClusterIP 10.104.72.224 none 80/TCP 13s
Service正常运行其集权内部访问IP为10.104.72.224访问下该Service
[rootk8s-master yaml]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:400
[rootk8s-master yaml]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:204
[rootk8s-master yaml]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:400
[rootk8s-master yaml]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:400
[rootk8s-master yaml]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:813 可以看到通过Service能成功访问到后端的3个应用且有负载均衡效果。我们再扩容一个新的Pod看看。
[rootk8s-master ~]# kubectl scale deployment/serviceapp-deployment --replicas4
deployment.apps/serviceapp-deployment scaled
[rootk8s-master ~]# kubectl get pod -l appserviceapp-deploy -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
serviceapp-deployment-649c69c89d-2k2hm 1/1 Running 0 12h 10.244.36.78 k8s-node1 none none
serviceapp-deployment-649c69c89d-h5s5g 1/1 Running 0 12h 10.244.36.119 k8s-node1 none none
serviceapp-deployment-649c69c89d-sjv55 1/1 Running 0 12h 10.244.36.123 k8s-node1 none none
serviceapp-deployment-649c69c89d-txlt9 1/1 Running 0 88s 10.244.36.103 k8s-master none none
再访问Service地址
[rootk8s-master ~]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:303
[rootk8s-master ~]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:813
[rootk8s-master ~]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:400
[rootk8s-master ~]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:204
[rootk8s-master ~]# curl http://10.104.72.224:80/k8s/getServiceApp
this this service app:400
可以看到新扩容的应用(appid303)已经加入到集群能通过Service访问到示意图如下 2、service原理分析 通过上面的实例我们了解了Service的具备统一访问入口的功能那么它是如何实现的呢
(1)属性分析
我们分析下Service的主要属性:
type表示Service的类型目前支持ClusterIPNodePortLoadBalancerExternalName四种这四种类型的作用和用法我们在后面具体分析。Selector选择那些后端应用与该Service关联上面的例子如图所示 通过selector属性其值为Pod的label值这样所有标记为该label的Pod与该service关联起来。所以通过Service的标签选择器实现与Pod的关联。
ports即Service访问port以及后端应用的目标Port。
(2)Pod的访问 Service的IP实际上是VIP(虚拟IP)请求是如何转发到后端Pod的呢其流程如下 (1)Pod启动完成后由kubelet将各Pod的ip注册到master节点。
(2)Service发布完成后由Master分配ClusterIP并与后端Pod的ip建立映射关系存储到master节点。
(3)kube-proxy监听到变化后修改本地的iptabels写入clusterIp与Podip的映射关系。
(4)运行时当Client访问Service的ClientIp时由iptabels截获根据映射关系以及负载均衡策略转发到后端应用的Pod。 以上就是Service访问的iptabels的工作模式也是默认的工作模式该机制确保了Pod在扩缩容时通过修改iptabels快速响应服务实例的变化同时由内核区的iptabels进行寻址和负载也大大提升了效率。 在Pod实例扩容和缩容时及时的体现到iptabel的映射表上。
3、Service类型 前面介绍了Service有四种类型我们具体介绍下
(1)ClusterIP K8S为Service分配一个集群内部IP地址该 IP只能在集群内部访问这也是type的默认值。
前面创建的就是ClusterIP类型其示意图如下: 除了前面讲的通过IP访问服务service还默认分配一个域名其格式 为servicename.namespace.svc.clusterdomain上面例子service的域名:service-app-service.default.svc.cluster.local我们登录到集群中某个pod再访问该域名的地址
[rootk8s-master yaml]# kubectl exec -it nginx-deployment-86644697c5-96q8l -- /bin/sh
# curl http://service-app-service.default.svc.cluster.local/k8s/getServiceApp
this this service app:400 可以看到通过Service域名能正确访问应用。 (2)NodePort 如果要对外提供服务(非集群内访问)ClusterIP模式是无法满足此时需要采用NodePort它是ClusterIP的扩展在每个节点的开放一个本地静态端口端口范围:30000-32767该端口代理服务通过节点上的端口可以访问服务。示意图如下: 下面我们改写下service-app-sv.yaml将type修改为NodePort并在ports中添加nodePort:30001
[rootk8s-master yaml]# cat service-app-sv.yaml
apiVersion: v1
kind: Service
metadata:name: service-app-service
spec:type: NodePortselector:app: serviceapp-deployports:- port: 80targetPort: 8080nodePort: 30001
创建Service后查看运行状态
[rootk8s-master yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 none 443/TCP 137d
service-app-service NodePort 10.110.47.22 none 80:30001/TCP 6m11s
此时我们就可以在公网上通过浏览器访问该服务 (3)LoadBalancer 公有云提供商一般提供负载均衡器向外部暴露服务外部负载均衡器可以将流量路由到自动创建的NodePort服务和ClusterIP服务上。示意图如下: 创建一个yaml文件service-app-loadbalancer-sv.yaml
[rootk8s-master yaml]# cat service-app-loadbalancer-sv.yaml
apiVersion: v1
kind: Service
metadata:name: service-app-service
spec:type: LoadBalancer selector:app: serviceapp-deployports:- port: 80targetPort: 8080
执行该文件并查看Service运行状态
[rootk8s-master yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 none 443/TCP 141d
service-app-service LoadBalancer 10.103.95.166 pending 80:32243/TCP 13m 已经自动分配了节点的32243端口并映射到service的80端口但是 EXTERNAL-IP一直处于pending状态这是因为我没有购买共有用的负载均衡服务购买后就会分配个负载均衡ip实现loadbalancer。
(4)ExternalName 这种类型一般是我们在使用外集群的服务时该服务暴露了DNS域名就可以在本集群创建一个Service并映射该域名那么就可以在本集群访问该service从而访问外集群的服务。示意图如下: 创建一个yaml文件映射为百度的域名。
[rootk8s-master yaml]# cat service-app-externalname-sv.yaml
apiVersion: v1
kind: Service
metadata:name: service-app-en-service
spec:type: ExternalNameexternalName: www.baidu.com
执行完成后看下创建结果
[rootk8s-master yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service-app-en-service ExternalName none www.baidu.com none 84m
当访问service-app-en-service.default.svc.cluster.local集群DNS服务返回CNAME记录其值为www.baidu.com。
为了验证下上面的结论我们在集群中部署dns工具pod镜像为dnsutils,其内容如下:
[rootk8s-master yaml]# cat dnsutils-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: dnsutils
spec:containers:- name: dnsutilsimage: mydlqclub/dnsutils:1.3imagePullPolicy: IfNotPresentcommand: [sleep,3600] 执行成功后进入该pod内部使用nslookup命令看下该域名的解析
[rootk8s-master yaml]# kubectl exec -it dnsutils /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # nslookup service-app-en-service.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10#53service-app-en-service.default.svc.cluster.local canonical name www.baidu.com.
www.baidu.com canonical name www.a.shifen.com.
Name: www.a.shifen.com
Address: 110.242.68.4
Name: www.a.shifen.com
Address: 110.242.68.3 再ping下百度的域名
[rootk8s-master yaml]# ping www.baidu.com
PING www.a.shifen.com (110.242.68.3) 56(84) bytes of data.
64 bytes from 110.242.68.3 (110.242.68.3): icmp_seq1 ttl52 time4.47 ms
64 bytes from 110.242.68.3 (110.242.68.3): icmp_seq2 ttl52 time4.45 ms
64 bytes from 110.242.68.3 (110.242.68.3): icmp_seq3 ttl52 time4.37 ms 可以看到上面确实是返回了百度域名的ip。
三、EndPoint 在上面的Pod访问模块中我们提到服务注册自己的ip到master节点在实际的实现过程中这些ip并不是一个物理列表而之后由Endpoint管理Service关联Endpoint。
我们先查下Endpoint列表
[rootk8s-master ~]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.16.4:6443 142d
service-app-service 10.244.36.103:8080,10.244.36.119:8080,10.244.36.123:8080 1 more... 25h k8s集群中已经有了两个endpoint其中一个是和service相同名称其Endpoints就是pod的列表。这个Endpoint我们并没有显性的去创建而是在创建Service时k8s自动创建的。 那这种设计的好处是什么呢其实就是为了解耦Endpoint作为解耦层可以灵活应对pod的变化而Service不感知。 在一些实际工程中部署在K8S集群的应用需要连接外部的数据库或者另一个集群或者Namespace的服务作为服务的后端这种场景下就需要用到Endpoint。
下面我们来看一个Endpoint的使用实例如图所示 集群外部部署了一个mongdb数据库集群内部应用A需要连接该数据库由于集群导致的网络隔离无法直接访问。此时就是可以使用Service手动配置Endpoint实现。
其yaml内容如下:
[rootk8s-master yaml]# cat mongodb_service.yaml
apiVersion: v1
kind: Service
metadata:name: mongodb-svc
spec:ports:- port: 27017targetPort: 27017protocol: TCP
---
kind: Endpoints
apiVersion: v1
metadata:name: mongodb-svc
subsets:- addresses:# 外部 mongodb IP- ip: 192.168.16.4ports:# mongodb 端口- port: 27017 首先我们创建了一个名为 mongodb-svc的service需要注意该service没有selector选择器也可以认为该service没有挂载后端服务其他的和上面的service没有区别。 接着又创建一个Endpoints其名称要为service一致(这里非常关键service与endpoints关联关系依赖name相同)在subsets中我们配置mongodb的ip(也可以是域名这里仅配置master库)和端口。 集群中的应用A就 可以通过访问该服务的域名来访问mongodb数据库了配置如下
spring:data:mongodb:uri: mongodb://ai_admin:123456mongodb-svc:27017/ai
四、Endpointslice
在大型集群中endpoint存在诸多限制
Pod数据限制一个服务对应一个Endpoint资源这意味着它需要为支持相应服务的每个Pod存储IP地址和端口网络端点Endpoint需要存储大量的ip和端口信息而存储在etcd中的对象的默认大小限制为1.5MB也就是最多能存储5000个pod的ip在大多数情况下是满足工程要求。但是在一些大型集群中数量超过这个限制就存在问题。更新代价大kube-proxy 会在每个节点上运行并监控 Endpoint 资源的任何更新如果 Endpoint 资源中有一个端口发生更改那么整个对象都会分发到 kube-proxy 的每个实例。如果service有5000个pod在3000个节点情况下每次更新将会跨节点发送 4.5GB 的数据(1.5M*3000)。再想象下如果5000个pod都滚动更新一次全部被替换那么传输的数据量将超过22TB这个是恐怖的数据。 为了解决以上的Endpoint存在的限制在是 Kubernetes 1.18 中引入的一个新的 API 对象EndpointSlice通过分片管理一组Endpoint这样将数据量以及更新的范围限制在一个分片内来解决以上两个问题。 EndPointSlice根据Endpoint所在Node的拓扑信息进行分片管理分为NodeZoneRegion三个级别如下图所示。 接下来我们看下K8s的EndpointSlice列表
[rootk8s-master ~]# kubectl get endpointslice
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
service-app-service-bf5vr IPv4 8080 10.244.36.78,10.244.36.103,10.244.36.123 1 more... 5d18h 创建了以Endpoint名称为前缀的EndpointSlice。再来看下EndpointSlice的详情。
[rootk8s-master ~]# kubectl describe endpointslice service-app-service-bf5vr
Name: service-app-service-bf5vr
Namespace: default
Labels: endpointslice.kubernetes.io/managed-byendpointslice-controller.k8s.iokubernetes.io/service-nameservice-app-service
Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2023-03-26T10:29:05Z
AddressType: IPv4
Ports:Name Port Protocol---- ---- --------unset 8080 TCP
Endpoints:- Addresses: 10.244.36.78Conditions:Ready: trueHostname: unsetTargetRef: Pod/serviceapp-deployment-649c69c89d-2k2hmNodeName: k8s-node1Zone: unset- Addresses: 10.244.36.103Conditions:Ready: trueHostname: unsetTargetRef: Pod/serviceapp-deployment-649c69c89d-txlt9NodeName: k8s-node1Zone: unset- Addresses: 10.244.36.123Conditions:Ready: trueHostname: unsetTargetRef: Pod/serviceapp-deployment-649c69c89d-sjv55NodeName: k8s-node1Zone: unset- Addresses: 10.244.36.119Conditions:Ready: trueHostname: unsetTargetRef: Pod/serviceapp-deployment-649c69c89d-h5s5gNodeName: k8s-node1Zone: unset
Events: none
我们来看下重要的属性参数
Labels的kubernetes.io/service-name表示关联的service名称。AddressType包括三种取值IPv4,IPv6,FQDN全限定域名Endpoints,列出的每个Endpoint的信息其中包括
AddressesEndpoint的IP地址 ConditionsEndpoint状态信息作为EndpointSlice的查询条件 Hostname在Endpoint中设置的主机名nostname TargetRefEndpoint对应的Pod名称 NodeName:所在的节点名 Zone所在的zone区 Topology拓扑信息为基于拓扑感知的服务路由提供数据。(需要设置服务拓扑key) 总之在大规模集群下EndpointSlice通过对Endpoint进行分片管理来实现降低Master和各Node之间的网络传输数据量及提高整体性能的目标。同时还支持围绕双栈网络和拓扑感知路由等新功能的创新。
五、Headless Service 在某些应用场景中我们仅希望Service实现服务发现即后端服务有改变能反映在端点列表但是不希望使用Service的服务路由功能即由业务获取列表后自定义服务的负载均衡策略决定需要连接具体哪个服务此时就可以使用Headless Service。一般应用在有状态服务中(在后续的Stateful控制器会介绍有状态服务类型)。 比如有一组根据userId字段进行分片的MySql分库当应用A读写用户信息时根据userId的分片策略决定路由到哪个分库。如下图所示 下面我们将前面的service-app-sv.yaml改造成Headless Service其yaml内如如下:
[rootk8s-master yaml]# cat service-app-headless-sv.yaml
apiVersion: v1
kind: Service
metadata:name: service-app-headless-service
spec:# clusterIp为None即为headless serviceclusterIP: Noneselector:app: serviceapp-deployports:- port: 80targetPort: 8080
该yaml中clusterIP:None即表示Headless Service。用前面创建的四个Pod模拟分库。执行完成后我们看下服务列表
[rootk8s-master yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service-app-headless-service ClusterIP None none 80/TCP 7m11s 可以看到其cluster ip为None也就是该Service无法通过ip访问。前面我们介绍过每个Service都有一个默认域名Headless Service也不例外该Service的域名为service-app-headless-service.default.svc.cluster.local通过nslookup指令模拟应用A客户端获取Endpoint列表。
[rootk8s-master yaml]# kubectl exec -it dnsutils /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # nslookup service-app-headless-service.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10#53Name: service-app-headless-service.default.svc.cluster.local
Address: 10.244.36.119
Name: service-app-headless-service.default.svc.cluster.local
Address: 10.244.36.78
Name: service-app-headless-service.default.svc.cluster.local
Address: 10.244.36.103
Name: service-app-headless-service.default.svc.cluster.local
Address: 10.244.36.123可以看到应用A能正确获取后端应用IP列表后续可以自行决策如何负载连接哪个数据库分库。
六、Ingress 前面介绍的Service都是基于IP:Port模式即工作在四层TCP协议层。在工程实践中我们应用更多的是需要工作在七层Http/Https层的网关服务此时Service对象是无法满足。从1.1版本开始K8S提供Ingress对象通过配置转发策略将不同的URL请求转发到后端不同的Service上实现基于HTTP的路由机制。 其示意图如下 Ingress需要配合Ingress控制器一起使用。Ingress主要用来配置规则简单理解就是Ngnix上配置的转发规则抽象成Ingress对象使用yaml文件创建更改时仅更新yaml文件即可。而Ingress Controller是真正实现负载均衡能力它感知集群中Ingress规则变化然后读取他按照他自己模板生成一段 Nginx 配置再写到 Nginx Pod 里。 简单来讲Ingress是负责解决怎么处理的问题Ingress Controller根据处理的策略实现处理方式。 1、Ingress的配置规则
Ingress支持以下几种配置规则
(1)、转发到单个后端服务
这种比较简单对于Ingress Controller IP的访问都会转发到该后端服务上如下:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx
spec:backend:serviceName: nginxservicePort: 8080
2、同一域名下不同URL路径被转发到不同的服务上
yaml内容如下在访问k8s.nginx.cn域名根据后面的path决定路由到对应的服务。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx
spec:rules:- host: k8s.nginx.cnhttp:paths:- path: /imagepathType: Prefixbackend:service:name: imageport:number: 80- path: /apppathType: Prefixbackend:service:name: webappport:number: 80
3、不同域名被转发到不同的服务上
yaml内容如下根据域名不同转发不同的后端Service。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx
spec:rules:- host: k8s.image.cnhttp:paths:- path: /pathType: Prefixbackend:service:name: imageport:number: 80- host: k8s.nginx.cnhttp:paths:- path: /pathType: Prefixbackend:service:name: nginxport:number: 80 4、不使用域名转发
这个实际是第一个的变种其yaml文件如下
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginx
spec:rules:http:paths:- path: /nginxbackend:serviceName: nginxservicePort: 8080
当访问ingress controller ip/nginx路径时转发到后端的nginx服务上。
2、案例实践 通过案例实践看下如何实现Ingres的配置转发功能。
(1)创建Ingress controller 首先我们创建Ingress Controller K8S目前支持AWSGCE和Nginx控制器我们这里使用K8s提供的Ngnix Controller 1.3.1版本 下载yaml文件后修改其中的controller镜像地址(原有的镜像地址国内无法访问)以及增加 hostNetwork: true(打通Cluster和node的网络)demo-1.3.1.yaml文件内容参见附件。
[rootk8s-master yaml]# kubectl apply -f demo-1.3.1.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx unchanged
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx unchanged
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission unchanged
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx unchanged
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission configured
执行该文件成功后可以看到在命名空间ingress-nginx下创建了一系列的对象。
[rootk8s-master yaml]# kubectl get pod,svc,ing,deploy -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create-6sbrv 0/1 Completed 0 3m12s
pod/ingress-nginx-admission-patch-dghkc 0/1 Completed 1 3m12s
pod/ingress-nginx-controller-7dd587ccd5-8xr8j 1/1 Running 0 3m12sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller LoadBalancer 10.96.244.230 pending 80:32148/TCP,443:31937/TCP 3m12s
service/ingress-nginx-controller-admission ClusterIP 10.107.184.217 none 443/TCP 3m12sNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 3m12s 其中Ingress Controller实际是一个Pod实现的这里就是 pod/ingress-nginx-controller-7dd587ccd5-8xr8j。 (2创建Deployment 接着我们创建后端应用Pod通过Nginx的镜像来模拟。 创建 命名空间为ns-ingress-test的NameSpace并创建所属该命名空间的Deploymentyaml内容如下:
[rootk8s-master yaml]# cat ingress-pod.yaml
apiVersion: v1
kind: Namespace
metadata:name: ns-ingress-test
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxnamespace: ns-ingress-testlabels:app: ingress-nginx
spec:selector:matchLabels:app: ingress-nginxreplicas: 2template:metadata:labels:app: ingress-nginxspec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80
执行该文件后查看pod的运行状态完成了2个Pod的运行。
[rootk8s-master yaml]# kubectl get pods -n ns-ingress-test
NAME READY STATUS RESTARTS AGE
nginx-7d8856bf4f-cxnx8 1/1 Running 0 5m1s
nginx-7d8856bf4f-hhk7x 1/1 Running 0 5m1s
(3)创建Service
接下来创建访问该应用Pod的Service对象type为ClusterIP内容如下:
[rootk8s-master yaml]# cat ingress-sv.yaml
apiVersion: v1
kind: Service
metadata:name: nginxnamespace: ns-ingress-test
spec:ports:- port: 80targetPort: 80selector:app: ingress-nginxtype: ClusterIP
执行完成后检查Service状态
[rootk8s-master yaml]# kubectl get svc -n ns-ingress-test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 10.106.13.73 none 80/TCP 20s
到此为止我们通过Service的IP就可以访问下nginx了。
[rootk8s-master yaml]# curl 10.106.13.73:80
!DOCTYPE html
html
head
titleWelcome to nginx!/title
....
可以看到访问正常说明Nginx应用运行正常。
(4)创建Ingress
这也是关键一步通过Ingress配置访问策略其yaml文件内容如下
[rootk8s-master yaml]# cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: nginxnamespace: ns-ingress-testannotations: kubernetes.io/ingress.class: nginx # 指定 Ingress Controller 的类型
spec:ingressClassName: nginxrules:- host: k8s.nginx.cnhttp:paths:- path: /pathType: Prefixbackend:service:name: nginxport:number: 80 这里较简单通过域名k8s.nginx.cn访问后端Service并指定ingressClassName为Ingress controller的名称。执行完成后看下Ingress的状态。
[rootk8s-master yaml]# kubectl get ingress -A
NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE
ns-ingress-test nginx nginx k8s.nginx.cn 80 20m
(5)检测 到此为止我们就可以通过域名在外网访问服务了。在客户端windows的hosts文件中增加域名映射
xx.xx.xx.xx k8s.nginx.cn
xx.xx.xx.xx为所在节点的公网IP配置完成后可以通过浏览器访问 七、总结
本章节介绍网络通讯的实现原理以及Service的相关核心概念
1、介绍了同一Pod内容器间同一节点不同Pod以及不同节点Pod的通讯原理和实现。
2、Service为同一组Pod提供统一的访问入口通过Selector选择同组PodService有四种类型分别为ClusterIP,NodePort,LoadBalancer,ExternalNamed。Service是通过iptabels记录虚拟IP与后端Pod IP的关系并实现流量的四层转发和负载。
3、EndpointEndpoint是管理后端应用的IP列表通过Endpoint实现Service与后端应用的解耦。通过Service手动配置Endpoint实现对集群外应用的访问。
4、Endpointslice在大规模集群中Endpoint存在性能上的限制Endpointslice通过分片管理降低Master和各Node之间的网络传输数据量及提高整体性能。
5、Headless Service是Service的一个变种采用ClusterIP:None标记一般应用于仅需要使用Service服务发现不需要服务路由的场景中。
6、IngressIngress可以实现七层路由的转发Ingress负责规则的配置而真正的流量转发则是由Ingress Controller实现。 附:
K8S初级入门系列之一-概述
K8S初级入门系列之二-集群搭建
K8S初级入门系列之三-Pod的基本概念和操作
K8S初级入门系列之四-Namespace/ConfigMap/Secret
K8S初级入门系列之五-Pod的高级特性
K8S初级入门系列之六-控制器(RC/RS/Deployment)
K8S初级入门系列之七-控制器(Job/CronJob/Daemonset)
K8S初级入门系列之八-网络
K8S初级入门系列之九-共享存储
K8S初级入门系列之十-控制器(StatefulSet)
K8S初级入门系列之十一-安全
K8S初级入门系列之十二-计算资源管理 附件
demo-1.3.1.yaml文件内容 apiVersion: v1 kind: Namespace metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx name: ingress-nginx --- apiVersion: v1 automountServiceAccountToken: true kind: ServiceAccount metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx namespace: ingress-nginx --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx namespace: ingress-nginx rules: - apiGroups: - resources: - namespaces verbs: - get - apiGroups: - resources: - configmaps - pods - secrets - endpoints verbs: - get - list - watch - apiGroups: - resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch - apiGroups: - resourceNames: - ingress-controller-leader resources: - configmaps verbs: - get - update - apiGroups: - resources: - configmaps verbs: - create - apiGroups: - coordination.k8s.io resourceNames: - ingress-controller-leader resources: - leases verbs: - get - update - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - apiGroups: - resources: - events verbs: - create - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission namespace: ingress-nginx rules: - apiGroups: - resources: - secrets verbs: - get - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx rules: - apiGroups: - resources: - configmaps - endpoints - nodes - pods - secrets - namespaces verbs: - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - list - watch - apiGroups: - resources: - nodes verbs: - get - apiGroups: - resources: - services verbs: - get - list - watch - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - apiGroups: - resources: - events verbs: - create - patch - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingressclasses verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission rules: - apiGroups: - admissionregistration.k8s.io resources: - validatingwebhookconfigurations verbs: - get - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx subjects: - kind: ServiceAccount name: ingress-nginx namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ingress-nginx-admission subjects: - kind: ServiceAccount name: ingress-nginx-admission namespace: ingress-nginx --- apiVersion: v1 data: allow-snippet-annotations: true kind: ConfigMap metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-controller namespace: ingress-nginx --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-controller namespace: ingress-nginx spec: externalTrafficPolicy: Local ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http port: 80 protocol: TCP targetPort: http - appProtocol: https name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: LoadBalancer --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: ports: - appProtocol: https name: https-webhook port: 443 targetPort: webhook selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-controller namespace: ingress-nginx spec: minReadySeconds: 0 revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx template: metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx spec: hostNetwork: true containers: - args: - /nginx-ingress-controller - --publish-service$(POD_NAMESPACE)/ingress-nginx-controller - --election-idingress-controller-leader - --controller-classk8s.io/ingress-nginx - --ingress-classnginx - --configmap$(POD_NAMESPACE)/ingress-nginx-controller - --validating-webhook:8443 - --validating-webhook-certificate/usr/local/certificates/cert - --validating-webhook-key/usr/local/certificates/key env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.1 imagePullPolicy: IfNotPresent lifecycle: preStop: exec: command: - /wait-shutdown livenessProbe: failureThreshold: 5 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: controller ports: - containerPort: 80 name: http protocol: TCP - containerPort: 443 name: https protocol: TCP - containerPort: 8443 name: webhook protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: requests: cpu: 100m memory: 90Mi securityContext: allowPrivilegeEscalation: true capabilities: add: - NET_BIND_SERVICE drop: - ALL runAsUser: 101 volumeMounts: - mountPath: /usr/local/certificates/ name: webhook-cert readOnly: true dnsPolicy: ClusterFirst nodeSelector: kubernetes.io/os: linux serviceAccountName: ingress-nginx terminationGracePeriodSeconds: 300 volumes: - name: webhook-cert secret: secretName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission-create namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission-create spec: hostNetwork: true containers: - args: - create - --hostingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc - --namespace$(POD_NAMESPACE) - --secret-nameingress-nginx-admission env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.3.0 imagePullPolicy: IfNotPresent name: create securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 2000 serviceAccountName: ingress-nginx-admission --- apiVersion: batch/v1 kind: Job metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: template: metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission-patch spec: hostNetwork: true containers: - args: - patch - --webhook-nameingress-nginx-admission - --namespace$(POD_NAMESPACE) - --patch-mutatingfalse - --secret-nameingress-nginx-admission - --patch-failure-policyFail env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.3.0 imagePullPolicy: IfNotPresent name: patch securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux restartPolicy: OnFailure securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 2000 serviceAccountName: ingress-nginx-admission --- apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: nginx spec: controller: k8s.io/ingress-nginx --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: labels: app.kubernetes.io/component: admission-webhook app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.3.1 name: ingress-nginx-admission webhooks: - admissionReviewVersions: - v1 clientConfig: service: name: ingress-nginx-controller-admission namespace: ingress-nginx path: /networking/v1/ingresses failurePolicy: Fail matchPolicy: Equivalent name: validate.nginx.ingress.kubernetes.io rules: - apiGroups: - networking.k8s.io apiVersions: - v1 operations: - CREATE - UPDATE resources: - ingresses sideEffects: None