kubernetes Ingress
Service可以实现四层调度,Ingress配合IngressController可以实现七层调度,Ingress就是一组转发规则,IngressController就是一个可以监听套接字的应用。
Ingress Controller:
Ingress Controller与宿主机共享网络名称空间直接监听在宿主机的IP地址上,外部流量可以直接到达Ingress Controller,client --> Ingress Controller --> Pods 这样每个节点只能有一个Ingress Controller,使用DaemonSet 控制器在每个节点上运行一个Ingress Controller。这样外部的均衡器就可以调度到任何一个节点上了。如果节点数很多可以打上污点,只在部分节点上运行Pod。
Ingress Controller 和其他的控制器有些不同,Ingress Controller 就是运行一个Nginx的Pod。而其他的ReplicaSet、deployment、DaemonSet 都是作为Controller-manager 的一部分存在的。
Ingress:
用 service 的 selector 选择相应的Pod并将Pod的IP返回给 Ingress,Ingress 根据这些IP生成配置注入到 Ingress Controller 中。
Ingress策略
Ingress是kubernetes的标准资源类型之一,它其实就是一组基于DNS名称(host)或URL路径把请求转发至指定的Service资源的规则,用于将集群外部的流量转发至集群内部完成服务发布。但是Ingress自身并不能进行流量穿透,还需要监听套接字的功能然后根据Ingress定义的这些规则转发流量。这个套接字的功能需要IngressController来实现。
官方文档:
https://v1-18.docs.kubernetes.io/docs/concepts/services-networking/ingress/
创建Ingress:
annotations 字段必加,多Ingress集群中用来识别Ingress控制器的类别。
rules和backend必须要有一个。
rules类型的Ingress:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: my-ingress annotations: kubernetes.io/ingress.class: "nginx" spec: rules: - host: www.scriptjc.com http: paths: - backend: serviceName: myapp-svc servicePort: 80
service类型的Ingress:
Ingress Controller会分配一个IP接收请求,并转发至 backend.serviceName。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-svc spec: backend: serviceName: myapp-svc servicePort: 80
基于URL路径进行流量转发:
将domain/wap 的转发到名称为 wap 的service。
将domain/api 的转发到名称为 api 的service。
注意:Ingress中path的定义需要与后端真实Service提供的path一致,否者会转发到一个不存在的path上而引发报错。如下例子中的path: /wap 后端提供服务的nginx或tomcat也需要有/wap路径。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-url annotations: ingress.kubernetes.io/rewrite-target: / spec: rules: - host: mywebsite.com http: paths: - path: /wap backend: serviceName: wap servicePort: 80 - path: /api backend: serviceName: api servicePort: 80
基于主机名的虚拟主机:
将 api.scriptjc.com 转发到名称为 api 的service上。
将 wap.scriptjc.com 转发到名称为 wap 的service上。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: virtual-host spec: rules: - host: api.scriptjc.com http: paths: - backend: serviceName: api servicePort: 80 - host: wap.scriptjc.com http: paths: - backend: serviceName: wap servicePort: 80
TLS类型的Ingress资源:
包含一个私钥和证书的Secret对象,并卸载HTTPS。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-tls spec: tls: - secretName: Secret backend: serviceName: myapp servicePort: 80
HTTP强制跳转HTTPS:80强制跳转443
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" labels: serivce: demo name: demo namespace: default spec: rules: - host: www.scriptjc.com http: paths: - backend: serviceName: demo servicePort: 80 path: / tls: - hosts: - www.scriptjc.com secretName: demo
networking.k8s.io/v1
新版的apiVersion 为 networking.k8s.io/v1,旧版的extensions/v1beta1 在k8s 1.22+ 就会彻底删除不能用。
命令行创建:
kubectl create ingress php72 --rule="nginx-php72.demo.com/=php72:80"
新版示例:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: prometheus-k8s namespace: monitoring annotations: kubernetes.io/ingress.class: nginx # 有些版本需要加上有些不用,如1.22版本需要加上 nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: prometheus2.demo.com http: paths: - path: / pathType: Prefix backend: service: name: prometheus-k8s port: number: 9090
设置白名单:
annotations: nginx.ingress.kubernetes.io/service-weight: '' nginx.ingress.kubernetes.io/whitelist-source-range: 220.191.163.50/32, 120.21.21.3
设置黑名单:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/server-snippet: | deny 47.93.48.132; deny 47.94.5.13; allow all;
跨域:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | if ($request_method = 'OPTIONS') { add_header 'Access-Control-Max-Age' 1728008; add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Headers' '*'; add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,PATCH,OPTIONS'; return 200; } nginx.ingress.kubernetes.io/cors-allow-credentials: "true" nginx.ingress.kubernetes.io/cors-allow-headers: DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,token,Cookie nginx.ingress.kubernetes.io/cors-allow-methods: GET, PUT, POST, DELETE, PATCH, OPTIONS nginx.ingress.kubernetes.io/cors-allow-origin: '*' nginx.ingress.kubernetes.io/cors-max-age: "1728008" nginx.ingress.kubernetes.io/enable-cors: "true" generation: 1 name: finstep-gateway namespace: finstep spec: ingressClassName: nginx rules: - host: gateway.xxx.com http: paths: - backend: service: name: gateway port: number: 80 path: / pathType: Prefix tls: - secretName: xxx.com
超时时间:解决504状态码问题
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "300" generation: 1 name: api namespace: default spec: ingressClassName: nginx rules: - host: api.demo.cn http: paths: - backend: service: name: api port: number: 80 path: / pathType: Prefix tls: - secretName: demo.com
aws ingress
aws ingress配置:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-1:011111111:certificate/xxxxxxx-c1ae-xxxxxxxx-xxxxxxxx alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]' alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/ssl-redirect: "443" alb.ingress.kubernetes.io/subnets: subnet-05008fbb31930c7c0, subnet-071e07e83dd5146f5 alb.ingress.kubernetes.io/target-type: ip name: admin-api namespace: prd spec: ingressClassName: alb rules: - host: api.scriptjc.com http: paths: - backend: service: name: api port: number: 80 path: / pathType: Prefix
ingress demo:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip name: uat-proxy-nginx namespace: prd spec: ingressClassName: nginx rules: - http: paths: - backend: service: name: uat-proxy-nginx port: number: 80 path: / pathType: Prefix
创建ingress:aws创建ingress之后会自动分配一个负载均衡地址,将域名用cname解析到这个地址即可。
apiVersion: extensions/v1beta1 kind: Ingress metadata: namespace: prod name: oversea-loan-bi annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: rules: - http: paths: - path: /* backend: serviceName: oversea-loan-bi servicePort: 80 status: # 创建好上面的资源apply后,aws自动分配下面这个地址 loadBalancer: ingress: - hostname: k8s-prod-overseal-1111111111-111111111.ap-southeast-1.elb.amazonaws.com
aws Ingress绑定证书:aws中一个证书只能被一个ingress绑定,证书需要申请,申请完后会给一个arn的值,把arn后面的字符串写上去即可;也就是说这个arn值只能写入一个ingress里,写入多ingress里只会有一个生效。
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: # 绑定ssl证书 alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-southeast-1:00000000839:certificate/0fa69b5c-42ad-4r49-a1a7-4a2896f383a1 alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]' alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip kubernetes.io/ingress.class: alb finalizers: - ingress.k8s.aws/resources name: prod-demo.com namespace: prod spec: rules: - host: rest.demo.com http: paths: - backend: serviceName: sulu-rest servicePort: 80 path: /* pathType: ImplementationSpecific status: loadBalancer: ingress: - hostname: k8s-prod-demo-xxxxxxxx-974373674.ap-southeast-1.elb.amazonaws.com
参考地址:
kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/ingress/annotations/#annotations
websocket
websocket:支持websocket的配置
apiVersion: networking.k8s.io/v1beta1 kind: Ingressmetadata: name: sx-data-server namespace: spot-standard annotations: kubernetes.io/ingress.class: "nginx" # 加入下面这两个指令 nginx.ingress.kubernetes.io/configuration-snippet: | proxy_set_header Upgrade "websocket"; proxy_set_header Connection "Upgrade"; spec: rules: - host: websocket.demo.com http: paths: - path: / backend: serviceName: demo servicePort: 61051
部署IngressController:
https://scriptjc.com/article/927