[TOC]
0x00 Ingress-Nginx 快速安装配置实践 描述: 此节,作为上一章的扩展补充,主要因为ingress-nginx迭代较快,加入了很多新得特性导致原来某些配置被弃用,当前时间节点【2022年3月8日 17:24:28】针对现有Ingress-nginx版本(v1.1.1)进行快速安装配置,与上一章中的安装是存在一定的不同,安装时都可以作为参考。
知识复习 Q: 什么是Ingress? A: Ingress 是管理对集群中服务的提供外部访问的 API 对象,Ingress 控制器负责实现 Ingress,通常使用负载均衡器,但它也可以配置边缘路由器或其他前端来帮助处理流量,它可以将来自集群外部的 HTTP 和 HTTPS 路由转发到集群内部的 Service 中。
Ingress 只是一个统称,其由 Ingress 和 Ingress Controller 两部分组成。
Ingress 用作将原来需要手动配置的规则抽象成一个 Ingress 对象,使用 YAML 格式的文件来创建和管理。
Ingress Controller 用作通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化。
使用 Ingress 控制器可以轻松实现外部URL访问集群内部服务、负载均衡、代理转发、支持配置SSL/TLS并提供基于名称的虚拟主机,值得注意的是 Ingress 不会暴露任意端口或协议,通过使用 Service.Type=NodePort
或 Service.Type=LoadBalancer
类型的服务向向 Internet 公开 HTTP 和 HTTPS 的访问服务
Q: 常用 Ingress 控制器有那些? 其它更多适用于Kubernetes的ingress控制器可以参考地址[https://kubernetes.io/zh/docs/concepts/services-networking/ingress-controllers/#%E5%85%B6%E4%BB%96%E6%8E%A7%E5%88%B6%E5%99%A8]
温馨提示: 理想情况下所有 Ingress 控制器都应符合参考规范。实际上各种 Ingress 控制器的操作略有不同,请参考相应Ingress的控制器官方文档。
如下图所示的一个简单的示例,客户端请求访问外部URL地址, Ingress 将其所有流量发送到一个Service中, 后端 Pod 提供服务端响应通过路由进行返回给客户端。
weiyigeek.top-Ingress
Q: Ingress 规则有哪些?
host : 虚拟主机名称, 主机名通配符主机可以是精确匹配(例如”foo.bar.com”)或通配符(例如“ *.foo.com”)
paths : URL访问路径。
pathType : Ingress 中的每个路径都需要有对应的路径类型(Path Type)
backend : 是 Service 文档中所述的服务和端口名称的组合与规则的 host 和 path 匹配的对 Ingress 的 HTTP(和 HTTPS )请求将发送到列出的 backend, 一般情况可以单独为路径设置Backend以及未匹配的url默认访问的后端defaultBackend。
Ingress 中的每个路径都需要有对应的路径类型(Path Type),未明确设置 pathType 的路径无法通过合法性检查,当前支持的路径类型有三种:
Exact:精确匹配 URL 路径,且区分大小写。
Prefix:基于以/
分隔的URL路径前缀匹配, 且区分大小写,并且对路径中的元素逐个完成。
ImplementationSpecific:此路径类型匹配方法取决于 IngressClass, 具体实现可以将其作为单独的 pathType 处理或者与 Prefix 、 Exact 类型作相同处理。
说明: 如果路径的最后一个元素是请求路径中最后一个元素的子字符串,则不会匹配 (例如:/foo/bar 匹配 /foo/bar/baz, 但不匹配 /foo/barbaz)。
温馨提示: defaultBackend 通常在 Ingress 控制器中配置,以服务与规范中的路径不匹配的任何请求。
[TOC]
0x00 Ingress-Nginx 快速安装配置实践 描述: 此节,作为上一章的扩展补充,主要因为ingress-nginx迭代较快,加入了很多新得特性导致原来某些配置被弃用,当前时间节点【2022年3月8日 17:24:28】针对现有Ingress-nginx版本(v1.1.1)进行快速安装配置,与上一章中的安装是存在一定的不同,安装时都可以作为参考。
知识复习 Q: 什么是Ingress? A: Ingress 是管理对集群中服务的提供外部访问的 API 对象,Ingress 控制器负责实现 Ingress,通常使用负载均衡器,但它也可以配置边缘路由器或其他前端来帮助处理流量,它可以将来自集群外部的 HTTP 和 HTTPS 路由转发到集群内部的 Service 中。
Ingress 只是一个统称,其由 Ingress 和 Ingress Controller 两部分组成。
Ingress 用作将原来需要手动配置的规则抽象成一个 Ingress 对象,使用 YAML 格式的文件来创建和管理。
Ingress Controller 用作通过与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化。
使用 Ingress 控制器可以轻松实现外部URL访问集群内部服务、负载均衡、代理转发、支持配置SSL/TLS并提供基于名称的虚拟主机,值得注意的是 Ingress 不会暴露任意端口或协议,通过使用 Service.Type=NodePort
或 Service.Type=LoadBalancer
类型的服务向向 Internet 公开 HTTP 和 HTTPS 的访问服务
Q: 常用 Ingress 控制器有那些? 其它更多适用于Kubernetes的ingress控制器可以参考地址[https://kubernetes.io/zh/docs/concepts/services-networking/ingress-controllers/#%E5%85%B6%E4%BB%96%E6%8E%A7%E5%88%B6%E5%99%A8]
温馨提示: 理想情况下所有 Ingress 控制器都应符合参考规范。实际上各种 Ingress 控制器的操作略有不同,请参考相应Ingress的控制器官方文档。
如下图所示的一个简单的示例,客户端请求访问外部URL地址, Ingress 将其所有流量发送到一个Service中, 后端 Pod 提供服务端响应通过路由进行返回给客户端。
weiyigeek.top-Ingress
Q: Ingress 规则有哪些?
host : 虚拟主机名称, 主机名通配符主机可以是精确匹配(例如”foo.bar.com”)或通配符(例如“ *.foo.com”)
paths : URL访问路径。
pathType : Ingress 中的每个路径都需要有对应的路径类型(Path Type)
backend : 是 Service 文档中所述的服务和端口名称的组合与规则的 host 和 path 匹配的对 Ingress 的 HTTP(和 HTTPS )请求将发送到列出的 backend, 一般情况可以单独为路径设置Backend以及未匹配的url默认访问的后端defaultBackend。
Ingress 中的每个路径都需要有对应的路径类型(Path Type),未明确设置 pathType 的路径无法通过合法性检查,当前支持的路径类型有三种:
Exact:精确匹配 URL 路径,且区分大小写。
Prefix:基于以/
分隔的URL路径前缀匹配, 且区分大小写,并且对路径中的元素逐个完成。
ImplementationSpecific:此路径类型匹配方法取决于 IngressClass, 具体实现可以将其作为单独的 pathType 处理或者与 Prefix 、 Exact 类型作相同处理。
说明: 如果路径的最后一个元素是请求路径中最后一个元素的子字符串,则不会匹配 (例如:/foo/bar 匹配 /foo/bar/baz, 但不匹配 /foo/barbaz)。
温馨提示: defaultBackend 通常在 Ingress 控制器中配置,以服务与规范中的路径不匹配的任何请求。1 2 3 4 5 6 7 8 9 10 11 12 13 tee > test.yaml << 'EOF' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: test-ingress spec: defaultBackend: service: name: test port: number: 80 EOF kubectl apply -f
注意, 入口控制器和负载平衡器可能需要一两分钟才能分配 IP 地址。 在此之前,你通常会看到地址字段的值被设定为<pending>
。
1.快速安装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 $ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/cloud/deploy.yaml $ sed -i -r 's#k8s.gcr.io/ingress-nginx/controller:(.*)@.*$#registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:\1#g' ingress-nginx-deploy.yaml $ sed -i -r 's#k8s.gcr.io/ingress-nginx/(.*)@.*$#registry.cn-hangzhou.aliyuncs.com/google_containers/\1#g' ingress-nginx-deploy.yaml $ kubectl apply -f ingress-nginx-deploy.yaml $ kubectl wait --namespace ingress-nginx \ --for =condition=ready pod \ --selector=app.kubernetes.io/component=controller \ --timeout=120s $ kubectl get pods --namespace=ingress-nginx $ kubectl create deployment default-backend --image=nginx:latest --namespace ingress-nginx $ kubectl create service clusterip default-backend --namespace ingress-nginx --tcp=80 tee default-backend.yaml <<'EOF' apiVersion: v1 kind: Service metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "80" prometheus.io/scheme: http labels: app: weiyigeek.top ref: default-backend name: default-backend namespace: ingress-nginx spec: ports: - name: http port: 80 protocol: TCP targetPort: 80 selector: app: weiyigeek.top ref: default-backend type : ClusterIP EOF $ kubectl get ingressclasses.networking.k8s.io ~$ kubectl scale deployment -n ingress-nginx ingress-nginx-controller --replicas=4
2.服务验证 描述: 创建使用指定的名称Ingress入口,此处可以采用两种方式进行创建,第一种方式是通过命令行方式,第二种是通过Ingress资源清单方式。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 kubectl create ingress demo-myweb-blog --class=nginx --rule="demo.weiyigeek.top/=web-blog:80" --namespace devtest cat > www-myweb-blog.ingress <<'EOF' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: www-blog namespace: devtest annotations: kubernetes.io/ingress.class: "nginx" ingressclass.kubernetes.io/is-default-class: true nginx.ingress.kubernetes.io/ssl-redirect : false nginx.ingress.kubernetes.io/rewrite-target: / labels: app: blog spec: ingressClassName: nginx defaultBackend: service: name: default-http port: number: 80 rules: - host: "www.weiyigeek.top" http: paths: - pathType: Prefix path: "/" backend: service: name: www-blog port: number: 80 - host: "web.weiyigeek.top" http: paths: - pathType: ImplementationSpecific path: "/" backend: service: name: web-blog port: number: 80 tls: - hosts: - www.weiyigeek.top secretName: testsecret-tls EOF kubectl apply -f www-myweb-blog.ingress kubectl get ingress -n devtest kubectl describe ingress -n devtest kubectl replace -f www-myweb-blog.ingress 192.168.12.222 www.weiyigeek.top demo.weiyigeek.top
weiyigeek.top-describe ingress
3.配置虚拟主机证书 描述: 通过设定包含 TLS 私钥和证书的 Secret 来保护 Ingress, TLS Secret 必须包含名为 tls.crt (证书)
和 tls.key (私钥)
的键名1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 apiVersion: v1 kind: Secret metadata: name: www.weiyigeek.top namespace: devtest data: tls.crt: `base64 编码的 cert` tls.key: `base64 编码的 key` type : kubernetes.io/tlskubectl create secret tls www.weiyigeek.top --cert=server.crt --key=server.key -n devtest apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tls-example-ingress spec: tls: - hosts: - www.weiyigeek.top secretName: testsecret-tls
温馨提示: 在 Ingress 中引用此 Secret 将会告诉 Ingress 控制器使用 TLS 加密从客户端到负载均衡器的通道。
4.使用hostNetwork网络方式 描述: 定义后Ingress-controller
的IP就与宿主机IP一样。
步骤 01.编辑 Ingress-controller 的 deploy 资源控制器内容,添加hostNetWork为true
的键值对,。
1 2 3 4 5 6 $ kubectl edit deployments.apps -n ingress-nginx ingress-nginx-controller spec: hostNetwork: true containers: - args: - /nginx-ingress-controller
步骤 02.查看Pod的IP地址,此时你会发现其地址为节点主机地址
。1 2 3 4 5 6 7 8 ~$ kubectl get pod -n ingress-nginx -o wide | grep "ingress-nginx-controller" ingress-nginx-controller-6b8bd48548-dfnvc 1/1 Running 0 4m26s 192.168.12.224 weiyigeek-224 ingress-nginx-controller-6b8bd48548-r9kpl 1/1 Running 0 5m 192.168.12.226 weiyigeek-226 ingress-nginx-controller-6b8bd48548-x9w9j 1/1 Running 0 5m33s 192.168.12.225 weiyigeek-225 ingress-nginx-controller-6b8bd48548-xqpcc 1/1 Running 0 5m33s 192.168.12.223 weiyigeek-223 ~$ curl 192.168.12.225 Hello ingress-Nginx , Index /
步骤 03.让Pod均衡的分别运行在work节点,我们需要执行以下两步,1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ~$ kubectl label nodes weiyigeek-223 weiyigeek-224 weiyigeek-225 weiyigeek-226 node=work ~$ kubectl edit deployments.apps -n ingress-nginx ingress-nginx-controller spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: node operator: In values: - work podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: ingress operator: In values: - nginx topologyKey: kubernetes.io/hostname weight: 100
5.使用externalIP网络方式 描述: 前面我们使用了 hostNetwork 方式,知道了可以使用 controller.hostNetwork=true
参数进行设置, 此处我们采用采用 externalIP
的方式进行服务暴露。
温馨提示:默认的控制器类型是Deployment,不过为其稳定性建议使用 DaemonSet 类型的控制器, 设置 hostNetwork 为 true、设置 dnsPolicy 为 ClusterFirstWithHostNet,也建议为要部署到的节点上打上ingress标签, 然后使用NodeSelector
添加ingress: "true"
部署至指定节点。
安装部署 1 2 $ helm install --name nginx-ingress --set "rbac.create=true,controller.service.externalIPs[0]=192.168.12.211,controller.service.externalIPs[1]=192.168.12.212,controller.service.externalIPs[2]=192.168.12.213" stable/nginx-ingress
部署完成后我们可以看到 Kubernetes 服务中增加了 nginx-ingress-controller
和 nginx-ingress-default-backend
两个服务。nginx-ingress-controller 为 Ingress Controller,主要做为一个七层的负载均衡器来提供 HTTP 路由、粘性会话、SSL 终止、SSL直通、TCP 和 UDP 负载平衡等功能。nginx-ingress-default-backend 为默认的后端,当集群外部的请求通过 Ingress 进入到集群内部时,如果无法负载到相应后端的 Service 上时,这种未知的请求将会被负载到这个默认的后端上。
由于我们采用了 externalIP 方式对外暴露服务, 所以 nginx-ingress-controller 会在 192.168.12.211、192.168.12.212、192.168.12.213 三台节点宿主机上的 暴露 80/443 端口。
1 2 $ kubectl get svc | grep "nginx-ingress-controller" nginx-ingress-controller LoadBalancer 10.254.84.72 192.168.12.211,192.168.12.212,192.168.12.213 80:8410/TCP,443:8948/TCP 46s
访问 Nginx Ingress Controller , 我们可以使用以下命令来获取 Nginx 的 HTTP 和 HTTPS 地址。1 $ kubectl --namespace default get services -o wide -w nginx-ingress-controller
访问验证: 1 2 3 $ curl -I http://192.168.12.211 $ curl -I --insecure http://192.168.12.211
在几台节点宿主机上查看,我们可以看到 ExternalIP 的 Service 是通过 Kube-Proxy对外暴露的,这里的 192.168.12.211、192.168.12.212、192.168.12.213 是三个内网 IP。 实际生产应用中是需要通过边缘路由器或全局统一接入层的负载均衡器将到达公网 IP 的外网流量转发到这几个内网 IP 上,外部用户再通过域名访问集群中以 Ingress 暴露的所有服务。
1 2 3 4 5 6 7 8 9 10 11 $ sudo netstat -tlunp|grep kube-proxy|grep -E '80|443' tcp 0 0 192.168.12.211:80 0.0.0.0:* LISTEN 714/kube-proxy tcp 0 0 192.168.12.211:443 0.0.0.0:* LISTEN 714/kube-proxy $ sudo netstat -tlunp|grep kube-proxy|grep -E '80|443' tcp 0 0 192.168.12.212:80 0.0.0.0:* LISTEN 690/kube-proxy tcp 0 0 192.168.12.212:443 0.0.0.0:* LISTEN 690/kube-proxy $ sudo netstat -tlunp|grep kube-proxy|grep -E '80|443' tcp 0 0 192.168.12.213:80 0.0.0.0:* LISTEN 748/kube-proxy tcp 0 0 192.168.12.213:443 0.0.0.0:* LISTEN 748/kube-proxy
6.对外暴露端口配置 描述: 默认的 Ingress 配置是暴露 http(80) 、https(443) 端口, 但需要注意的是创建的 Ingress 必须要和对外暴露的 Service 在同一命名空间下!
除此之外其实还可通过 Ingress controller 来实现TCP 和 UDP 服务端口的暴露,下面进行一一讲解。
1) http/https端口 描述: 缺少ingress支持http与https协议的后端应用。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 cat ' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 name: rewrite namespace: default spec: ingressClassName: nginx rules: - host: rewrite.weiyigeek.top http: paths: - path: /something(/|$)(.*) pathType: Prefix backend: service: name: http-svc port: number: 80 ' | kubectl create -f -
2) 暴露TCP/UDP端口 描述: 我们可以通过 tcp-services-configmap.yaml 设置映射tcp, 通过 udp-services-configmap.yaml 映射udp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 cat > tcp-services-configmap.yaml <<EOF apiVersion: v1 kind: ConfigMap metadata: name: tcp-services namespace: ingress-nginx data: 2181: "kafka/kafka-zookeeper:2181" 50000: "devops/jenkins:50000" EOF cat tcp-services-configmap.yaml | kubectl create -f - tee udp-services-configmap.yaml <<'EOF' apiVersion: v1 kind: ConfigMap metadata: name: udp-services namespace: ingress-nginx data: 53: "kube-system/kube-dns:53" EOF cat udp-services-configmap.yaml | kubectl create -f -
查看 ConfigMap 资源1 2 3 ~$ kubectl get cm -n ingress-nginx | grep "services" tcp-services 2 15h udp-services 1 15h
验证暴露的 TCP/UDP 服务:1 2 3 4 5 6 ~$ telnet 192.168.12.225 50000 Trying 192.168.12.225... Connected to 192.168.12.225. Escape character is '^]' . ~$ dig -x jenkins.devops.svc @192.168.12.225
3) 通过helm更新公开端口 描述: 通过helm chart
图表中的deployment-tcp-udp-values.yaml
或者deployment-tcp-udp-configMapNamespace-values.yaml文件
进行暴露TCP/UDP (如果你使用采用helm方式部署的ingress,此种方式是推荐的。), 注意此种方式1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 controller: image: repository: ingress-controller/controller tag: 1.0.0-dev digest: null admissionWebhooks: enabled: false service: type : ClusterIP tcp: 9000: "default/test:8080" udp: 9001: "default/test:8080" helm upgrade nginx-ingress stable/nginx-ingress \ -f ./ci/deployment-tcp-udp-values.yaml
7.节点与Pod亲和性设置 描述: 为 deployments.apps 资源控制器部署的 ingress 设置节点亲和。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 sepc: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: node operator: In values: - app - ali - www podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: kubernetes.io/os operator: In values: - linux topologyKey: kubernetes.io/hostname weight: 100 nodeSelector: k8s.io/ingress-nginx: "true"
8.基于 auth-url 模块认证方式实践 1.使用auth-url模块配置ldap登录 描述: 在 K8s 中我们可以使用 nginx Ingress
的 auth-url
模块配置ldap登录验证。
前置需求已经有部署自己的ldap server
, 然后还要在要配置ldap验证的服务ingress 上添加以下annotation:
1 2 3 4 5 apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/auth-url: https://{server_domain}/auth/ldap/$remote_user/$http_authorization
温馨提示: 此处 {server_domain}
是你的 ldap-auth-server
域名或IP地址, 其实现原理也是非常简单的即用你的程序去ldap server校验用户名密码是否正确即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 from ldap3 import Server, Connection, ALL, SUBTREE, ALL_ATTRIBUTES, MODIFY_REPLACE, MODIFY_ADD, MODIFY_DELETEfrom ldap3.utils.hashed import hashedfrom ldap3 import ( HASHED_SALTED_SHA, MODIFY_REPLACE ) import json,osimport base64from flask import ( Flask, Response, request, render_template, redirect, jsonify, make_response, url_for, abort, ) from helpers import ( status_code ) app = Flask(__name__) class LdapUtils (object) : def __init__ (self, ldap_host=None, port=None, base_dn=None, user=None, password=None) : self.base_dn = base_dn try : server = Server(ldap_host, port, get_info=ALL) self.ldapconn = Connection(server, user=None , password=None , auto_bind='NONE' , version=3 , authentication='SIMPLE' , client_strategy='SYNC' , auto_referrals=True , check_names=True , read_only=False , lazy=False , raise_exceptions=False ) self.ldapconn.rebind(user=user, password=password) except Exception as e: print(e) def ldap_search_dn (self, uid=None) : obj = self.ldapconn search_base = self.base_dn search_scope = SUBTREE search_filter = "(cn={0})" .format(uid) try : obj.search(search_base, search_filter, search_scope, attributes=['cn' ], paged_size=1 ) if len(obj.response) == 1 : return obj.response[0 ]['dn' ] else : return None except Exception as e: print(e) def ldap_update_pass (self, uid=None, oldpass=None, newpass=None) : target_cn = self.ldap_search_dn(uid) try : hashed_password = hashed(HASHED_SALTED_SHA, newpass) print("password:" + hashed_password) changes = { 'userPassword' : [(MODIFY_REPLACE, [hashed_password])] } return self.ldapconn.modify(target_cn, changes=changes) except Exception as e: print(e) return False def ldap_get_vaild (self, uid=None, passwd=None) : if not uid or not passwd: return False obj = self.ldapconn dn = "uid={0},ou=Users,dc=xxxxx,dc=com" .format(uid) try : if obj.rebind(dn, passwd): return True else : return False except Exception as e: print('e:' + str(e)) ldap_host = os.getenv("host" ) port = os.getenv("port" ) base_dn = os.getenv("base_dn" ) user = os.getenv("admin_user" ) password = os.getenv("password" ) ldap = LdapUtils(ldap_host, int(port), base_dn, user,password) @app.route('/auth/<user>/<passwd>') def auth_user (user="user" , passwd="passwd" ) : if not ldap.ldap_get_vaild(uid=user,passwd=passwd): return status_code(401 ) return jsonify(authenticated=True , user=user) @app.route('/auth/<qop>/<user>/<passwd>') def auth_qop_user (qop=None, user="user" , passwd="passwd" ) : temp = base64.b64decode(passwd.split(" " )[1 ]).decode() if not ldap.ldap_get_vaild(uid=user,passwd=temp.split(":" )[1 ]): return status_code(401 ) return jsonify(authenticated=True , user=user) @app.route('/', defaults={'path': ''}) @app.route('/<path:path>') def catch_all (path) : auth = request.headers.get('Authorization' ) if auth is not None : uid = base64.b64decode(auth.split(" " )[1 ]).decode().split(":" )[0 ] passwd = base64.b64decode(auth.split(" " )[1 ]).decode().split(":" )[1 ] if not ldap.ldap_get_vaild(uid=uid,passwd=passwd): return status_code(401 ) return render_template('password.html' ,uid=uid) return status_code(401 ) if __name__ == '__main__' : app.run(host = '0.0.0.0' )
0x01 入坑出坑 问题1.K8s Nginx Ingress Controller 转发 X-Forwarded-Proto 请求头的问题 问题说明: 在 Kubernetes 集群上部署了 Nginx Ingress Controller 最前端用的是阿里云七层负载均衡,部署后发现不能正确转发 X-Forwarded-Proto 请求头,造成 http 重定向到 https 无法正常工作,请问如何解决?
1 2 3 4 5 6 kubectl exec -it daemonset/nginx-ingress -n nginx-ingress cat /etc/nginx/conf.d/production-cnblogs-ingress.conf proxy_set_header X-Forwarded-Proto $scheme ;
问题解决: 终于在 Nginx Ingress Controller 的官方帮助文档 Advanced Configuration with Annotations 中找到一个注解(annotation)解决了这个问题,它就是 nginx.org/redirect-to-https: "true"
1 2 3 4 Annotation: nginx.org/redirect-to-https ConfigMap Key redirect-to-https Description Sets the 301 redirect rule based on the value of the http_x_forwarded_proto header on the server block to force incoming traffic to be over HTTPS. Useful when terminating SSL in a load balancer in front of the Ingress controller
操作步骤: 1)在 cnblogs-ingress.yaml 中 annotations 下面添加 nginx.org/redirect-to-https: “true”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: cnblogs-ingress annotations: kubernetes.io/ingress.class: nginx nginx.org/redirect-to-https: "true" spec: rules: - host: q.cnblogs.com http: paths: - backend: serviceName: q-web servicePort: 80
2) 更新 ingress 配置
1 kubectl apply -f cnblogs-ingress.yaml
3) 更新 nginx-ingress
1 2 kubectl rollout restart daemonset/nginx-ingress -n nginx-ingress && \ kubectl rollout status daemonset/nginx-ingress -n nginx-ingress
4)查看 inginx 容器中的配置
1 2 3 4 5 6 7 kubectl exec -it daemonset/nginx-ingress -n nginx-ingress cat /etc/nginx/conf.d/production-cnblogs-ingress.conf if ($http_x_forwarded_proto = 'http' ) { return 301 https://$host $request_uri ; }
nginx-ingress 自己完成了基于X-Forwarded-Proto
的 http 重定向到 https 的操作,应用都不需要自己处理了。
Tips :建议采用 kubernetes/ingress-nginx 而非 nginxinc/kubernetes-ingress : https://github.com/kubernetes/ingress-nginx
问题2:extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress 解决办法:根据当前 Kubernetes 版本中资源组与版本进行选择即可;
1 2 3 4 5 6 ~/K8s/Day7/demo1$ kubectl api-resources | grep "ingresses" ingresses ing extensions true Ingress ingresses ing networking.k8s.io true Ingress apiVersion: networking.k8s.io/v1
问题3.Error from server (InternalError): error when applying patch: 错误信息:
1 2 3 4 5 6 7 8 9 10 11 12 $ kubectl apply -f demo-ingress.yaml {"metadata" :{"annotations" :{"kubectl.kubernetes.io/last-applied-configuration" :"{\"apiVersion\":\"networking.k8s.io/v1\",\"kind\":\"Ingress\",\"metadata\":{\"annotations\":{\"kubernetes.io/ingress.class\":\"nginx\"},\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"rules\":[{\"host\":\"nginx.ieasou.cn\",\"http\":{\"paths\":[{\"backend\":{\"service\":{\"name\":\"nginx\",\"port\":{\"number\":80}}},\"path\":\"/\",\"pathType\":\"Prefix\"}]}}]}}\n" ,"kubernetes.io/ingress.class" :"nginx" }},"spec" :{"rules" :[{"host" :"nginx.ieasou.cn" ,"http" :{"paths" :[{"backend" :{"service" :{"name" :"nginx" ,"port" :{"number" :80}}},"path" :"/" ,"pathType" :"Prefix" }]}}]}} to: Resource: "networking.k8s.io/v1, Resource=ingresses" , GroupVersionKind: "networking.k8s.io/v1, Kind=Ingress" Name: "nginx" , Namespace: "default" for : "demo-ingress.yaml" : Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io" : Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/extensions/v1beta1/ingresses?timeout=30s" : x509: certificate is valid for k8s-master002, kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local, not ingress-nginx-controller-admission.ingress-nginx.svc kubectl create -f ingress-nginx-http-v1.yaml
解决办法: Webhook 删除后重新构建 ingress-nginx-http-v1.yaml 资源清单即可
1 2 3 4 5 weiyigeek@ubuntu:~/K8s/Day7/demo2$ kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission weiyigeek@ubuntu:~/K8s/Day7/demo2$ kubectl create -f ingress-nginx-http-v1.yaml
问题4.查看ingress规则时提示kubernetes之ingress error: endpoints "default-http-backend" not found
警告
1 2 $ kubectl describe ing Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
问题原因: 注意:根据您正在使用的Ingress控制器,您可能需要创建一个default-http-backend服务。没有规则的入口将所有流量发送到一个默认后端。默认后端通常是Ingress控制器的一个配置选项,在您的Ingress资源中没有指定。如果Ingress对象中的主机或路径都不匹配HTTP请求,则流量将被路由到默认后端。
解决办法:
1 2 3 4 5 6 7 spec: defaultbackend: service: name: nginx-ingress-v1-svc port: number: 80
问题5.设置了ingress无法正常显示页面,由于没有在资源清单中指定设置ingressclass名称 问题描述: 由于没有给ingress规则设置默认的ClassName,此时带有虚拟主机头的响应为默认default-http后端。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 ~$ kubectl get deployments.apps -n ingress-nginx ingress-nginx-controller -o yaml | grep " --controller-class" - --controller-class=k8s.io/ingress-nginx ~$ kubectl get ingressclasses.networking.k8s.io ~$ kubectl get ingressclasses.networking.k8s.io apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: nginx labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: ingress-nginx app.kubernetes.io/version: 1.1.1 helm.sh/chart: ingress-nginx-4.0.15 spec: controller: k8s.io/ingress-nginx parameters: apiGroup: k8s.example.com kind: IngressParameters name: external-lb namespace: external-configuration scope: Namespace apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: blog namespace: devtest annotations: nginx.ingress.kubernetes.io/rewrite-target: / ingressclass.kubernetes.io/is-default-class: true spec: ingressClassName: nginx rules: - host: "www.weiyigeek.top" http: paths: - pathType: Prefix path: "/" backend: service: name: myweb-blog port: number: 80
温馨提示: ingressclass API 资源对象中, 在 sepc.parameters 字段中有一个 scope 和 namespace 字段,可用来引用特定于名字空间的资源,对 Ingress 类进行配置。(FEATURE STATE: Kubernetes v1.22 [beta]
)
scope 字段默认为 Cluster,表示默认是集群作用域的资源。
scope 设置为 Namespace 并设置 namespace 字段就可以引用某特定名字空间中的参数资源。
温馨提示: 当前 ingress 1.1.1 版本中使用 ingressClassName
字段来替代kubernetes.io/ingress.class
注解, 两则区别在于该注解通常用于引用实现该 Ingress 的控制器的名称, 而这个新的字段则是对一个包含额外 Ingress 配置的 IngressClass 资源的引用, 包括 Ingress 控制器的名称。
温馨提示: 我们也可以将一个 IngressClass 资源的 ingressclass.kubernetes.io/is-default-class
注解设置为 true ,以确保在未指定 ingressClassName 字段的情况下,Ingress 也能够分配为这个默认的 IngressClass.
问题6.在节点中启动ingress-nginx-control pod时报Using the inClusterConfig. This might not work.
解决办法 错误信息: 1 2 3 $ kubectl logs -f --tail 50 -n ingress-nginx ingress-nginx-controller-859d6d9d5c-z555v W1028 02:37:29.974413 8 client_config.go:552] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work. I1028 02:37:29.974836 8 main.go:196] Creating API client for https://10.96.0.1:443
解决办法: 在 ingress-nginx 编辑 ingress-nginx-controller 配置清单将hostNetwork设置为true1 2 3 4 5 $ kubectl edit deployments.apps -n ingress-nginx ingress-nginx-controller spec: hostNetwork: true