Kubernetes 安装配置ingress controller
对于Kubernetes的Service,无论是Cluster-Ip和NodePort均是四层的负载,集群内的服务如何实现七层的负载均衡,这就需要借助于Ingress,Ingress控制器的实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio。
几种常用的ingress功能对比和选型: https://www.kubernetes.org.cn/5948.html
# 实现逻辑
Ingress-nginx是7层的负载均衡器 ,负责统一管理外部对k8s cluster中Service的请求。主要包含:
ingress-nginx-controller:根据用户编写的ingress规则(创建的ingress的yaml文件),动态的去更改nginx服务的配置文件,并且reload重载使其生效(是自动化的,通过lua脚本来实现);
Ingress资源对象:将Nginx的配置抽象成一个Ingress对象
ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化
然后读取ingress规则(规则就是写明了哪个域名对应哪个service),按照自定义的规则,生成一段nginx配置
再写到nginx-ingress-controller的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器把生成的nginx配置写入/etc/nginx/nginx.conf文件中
然后reload一下使配置生效。以此达到域名分别配置和动态更新的问题。
# 安装
官方文档: https://kubernetes.github.io/ingress-nginx/deploy/
部署文档: https://github.com/kubernetes/ingress-nginx/blob/nginx-0.30.0/docs/deploy/index.md
K8S Annotations文档: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#enable-cors
# Support Versions
官网地址: https://github.com/kubernetes/ingress-nginx
Ingress-NGINX version | k8s supported version | Alpine Version | Nginx Version |
---|---|---|---|
v1.2.1 | 1.23, 1.22, 1.21, 1.20, 1.19 | 3.14.6 | 1.19.10† |
v1.2.0 | 1.23, 1.22, 1.21, 1.20, 1.19 | 3.14.6 | 1.19.10† |
v1.1.3 | 1.23, 1.22, 1.21, 1.20, 1.19 | 3.14.4 | 1.19.10† |
# Helm 部署(推荐)
部署文档: https://github.com/bitnami/charts/tree/master/bitnami/nginx-ingress-controller/#installing-the-chart
# 1.安装helm
#Linux 直接运行curl 命令安装
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
2
# 2.下载Chart
#下载Chart
git clone https://github.com/bitnami/charts.git
cd charts/bitnami/nginx-ingress-controller/
2
3
# 3.配置chart
#为安装ingress的node节点添加label
#高可用模式可以在多个node上打标签,host模式不会调度在同一个机器
kubectl label node k8s-master ingress=true
kubectl label node k8s-node01 ingress=true
#查询包含指定label(ingress=true)的node节点
kubectl get nodes --show-labels -l "ingress=true"
2
3
4
5
6
7
##配置Chart
$ vim values.yaml
##NGINX 的自定义configmap配置选项
##官方文档: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/
##添加下面三行,获取客户端真实IP
#config: {}
config:
compute-full-forwarded-for: "true"
forwarded-for-header: "X-Forwarded-For"
use-forwarded-headers: "true"
##如果使用hostNetwork=true,设置reportNodeInternalIp=true,会将标志“report-node-internal-ip-address”传递给Nginx 入口控制器
reportNodeInternalIp: true
##配置控制器所需的 pod 数量
replicaCount: 2
##添加为host模式,启用主机网络,通过宿主机ip+port访问。
hostNetwork: true
##选择器,决定将ingress部署在哪些机器
#nodeSelector: {}
nodeSelector:
ingress: "true"
##禁用基于 NGINX 的默认后端
defaultBackend:
## @param defaultBackend.enabled Enable a default backend based on NGINX
##
enabled: false ##设置为false
service:
## @param service.type Kubernetes Service type for Controller
##
#type: LoadBalancer
type: NodePort ## 修改服务类型为 NodePort
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
# 4.安装Chart
#添加chart仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm search repo bitnami
#安装Chart
helm upgrade --install -f values.yaml --timeout 20m --create-namespace --namespace nginx-ingress-controller k8s-nginx bitnami/nginx-ingress-controller --wait --wait-for-jobs --debug
2
3
4
5
6
7
# 查看发布版本列表
helm list -n nginx-ingress-controller
# 升级Chart
##因服务类型为 NodePort,需要--set replicaCount=1 将pod数量改为1,否则端口被占用
helm upgrade -f values.yaml --timeout 30m --namespace nginx-ingress-controller k8s-nginx bitnami/nginx-ingress-controller --atomic --wait --wait-for-jobs --debug --set image.tag='1.3.1-debian-11-r0' --set ingressClassResource.name="nginx-new" --set replicaCount=1
##查看deployment信息
[ec2-user@eks ~]$ kubectl get deploy -n nginx-ingress-controller
NAME READY UP-TO-DATE AVAILABLE AGE
k8s-nginx-nginx-ingress-controller 1/1 1 1 39h
##手动对pod进行扩容
kubectl scale --replicas 2 deployment k8s-nginx-nginx-ingress-controller -n nginx-ingress-controller
2
3
4
5
6
7
8
9
10
# 卸载Chart
helm uninstall k8s-nginx -n nginx-ingress-controller
#helm delete k8s-nginx -n nginx-ingress-controller
helm list -n nginx-ingress-controller
2
3
4
# 自定义yaml文件部署
# 安装ingress-controller
hostNetwork: true 修改为host模式,使用node节点ip访问
# 1.下载yaml文件
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml -O ./ingress-nginx.yaml
#wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.1/deploy/static/provider/cloud/deploy.yaml -O ./ingress-nginx.yaml
2
3
- 或者使用myblog/deployment/ingress/mandatory.yaml
# 2.修改yaml配置文件
$ grep -n5 nodeSelector ingress-nginx.yaml
199- replicas: 2 #设置副本数,host模式不会被调度到同一个node
212- spec:
213- hostNetwork: true #添加为host模式
214- # wait up to five minutes for the drain of connections
215- terminationGracePeriodSeconds: 300
216- serviceAccountName: nginx-ingress-serviceaccount
217: nodeSelector:
218- ingress: "true" #替换此处,来决定将ingress部署在哪些机器
219- containers:
220- - name: nginx-ingress-controller
221- image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
222- args:
2
3
4
5
6
7
8
9
10
11
12
13
# 4.为安装ingress的node节点添加label
#为node节点添加label
#可用模式可以在多个node上打标签,host模式不会调度在同一个机器
kubectl label node k8s-master ingress=true
kubectl label node k8s-node01 ingress=true
#查询包含指定label(ingress=true)的node节点
kubectl get nodes --show-labels -l "ingress=true"
2
3
4
5
6
7
# 5.创建ingress-controller
kubectl apply -f ingress-nginx.yaml
# 6.检查运行状态
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-55dd6f8d7b-tkx77 1/1 Running 0 83d
nginx-ingress-controller-55dd6f8d7b-vkvqp 1/1 Running 0 83d
2
3
4
# AWS 中部署
官方文档: https://docs.amazonaws.cn/eks/latest/userguide/alb-ingress.html 在 AWS 中,我们使用网络负载均衡器 (NLB) 在 服务类型 为LoadBalancer 之后暴露 NGINX 入口控制器。
- AWS 负载均衡器 (NLB) 中的 TLS 终止
默认情况下,TLS 在入口控制器中终止。但也可以在负载均衡器中终止 TLS。本节介绍如何使用 NLB 在 AWS 上执行此操作。
# 1.下载 deploy.yaml模板
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.1/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml
# 2.编辑文件并更改 Kubernetes 集群使用的 VPC CIDR
proxy-real-ip-cidr: XXX.XXX.XXX/XX
# 3.同时更改 AWS Certificate Manager (ACM) ID
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-west-2:XXXXXXXX:certificate/XXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX
# 4.部署清单
kubectl apply -f deploy.yaml
# Ingress controller配置
# 透传client源IP
配置X-Forwarded-For 获取客户端真实IP,实现IP白名单和透传client源IP的功能
##查看configmap 信息
[ec2-user@eks ~]$ kubectl get configmap -n nginx-ingress-controller
NAME DATA AGE
k8s-nginx-nginx-ingress-controller 3 19m
##编辑configmap
[ec2-user@eks ~]$ kubectl edit cm/k8s-nginx-nginx-ingress-controller -n nginx-ingress-controller
2
3
4
5
6
7
修改内容如下:
apiVersion: 1
data:
#data里,加入以下配置
#将远程地址附加到 X-Forwarded-For 标头而不是替换它。启用此选项后,上游应用程序负责根据自己的受信任代理列表提取客户端 IP。
compute-full-forwarded-for: "true"
#设置用于标识客户端的原始 IP 地址的标头字段。默认值:X-Forwarded-For
forwarded-for-header: X-Forwarded-For
#如果为真,NGINX 会将传入的 X-Forwarded-* 标头传递给上游。当 NGINX 在设置这些标头的另一个代理/负载均衡器之后使用此选项;如果为 false,NGINX 会忽略传入的 X-Forwarded-* 标头,并用它看到的请求信息填充它们。
use-forwarded-headers: "true"
kind: ConfigMap
2
3
4
5
6
7
8
9
10
验证是否生效:
[ec2-user@eks ~]$ kubectl exec pods/k8-nginx-nginx-ingress-controller-69c99c6c7-hcbd2 -n nginx-ingress-controller /bin/cat /etc/nginx/nginx.conf |grep -b5 'real_ip_header'
... ... ...
##生效后,在 nginx-ingress-controller 中 nginx.conf 增加了以下配置:
2424: real_ip_header X-Forwarded-For;
2462-
2464- real_ip_recursive on;
2489-
2491- set_real_ip_from 0.0.0.0/0;
2523-
2
3
4
5
6
7
8
9
# Ingress配置
# Ingress yml配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wildcard-host
namespace: ops
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: 'false'
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- host: "bar.foo.com"
http:
paths:
- pathType: Prefix
path: "/foo"
backend:
service:
name: service2
port:
number: 80
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
# 检查ingress动态生成的nginx配置
$ kubectl -n ingress-nginx exec -ti nginx-ingress-xxxxxxx bash
# ps aux
# cat /etc/nginx/nginx.conf|grep myblog -A10 -B1
2
3
# 跨域配置
跨域配置1:(直接在ingress 的annation里面加)
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/Access-Control-Allow-Origin: '*'
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: 'PUT, GET, POST, OPTIONS'
nginx.ingress.kubernetes.io/cors-allow-origin: 'https://*.qqq.cn, http://*.qqq.cn, http://localhost:8081'
nginx.ingress.kubernetes.io/enable-cors: 'true'
nginx.ingress.kubernetes.io/cors-max-age: '600'
2
3
4
5
6
7
8
9
10
跨域配置2:(使用configuration-snippet配置)
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($request_method = 'OPTIONS') {
more_set_headers "Access-Control-Allow-Origin: $http_origin";
more_set_headers 'Access-Control-Allow-Credentials: true';
more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS';
more_set_headers 'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
more_set_headers 'Access-Control-Max-Age: 1200';
more_set_headers 'Content-Type: text/plain charset=UTF-8';
more_set_headers 'Content-Length: 0';
return 204;
}
more_set_headers "Access-Control-Allow-Origin: $http_origin";
more_set_headers 'Access-Control-Allow-Credentials' 'true';
more_set_headers 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
more_set_headers 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 白名单限制
nginx.ingress.kubernetes.io/whitelist-source-range您可以通过注解指定允许的客户端 IP 源范围。该值是一个逗号分隔的CIDR列表,例如10.0.0.0/24,172.10.0.1
# 前端没有负载均衡器的情况下
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: '172.21.0.0/16,10.0.0.0/16'
2
3
4
5
# 前端有负载均衡器的情况下(阿里云 SLB,AWS ALB)
Ingress controller配置透传client源IP(需要额外增加下面配置,在data 下添加 use-forwarded-headers)
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
data:
use-forwarded-headers: "true" # 添加
2
3
4
5
6
7
8
9
10
# 重定向配置
官方地址: https://kubernetes.github.io/ingress-nginx/examples/rewrite/
# 域名跳转
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: 'https://ops-bbb.qsh.cn/$1'
generation: 2
name: ops-web
namespace: ops
spec:
rules:
- host: ops-aaa.qsh.cn
http:
paths:
- backend:
service:
name: ops-web
port:
number: 8000
path: /(.*)
pathType: Prefix
status:
loadBalancer: {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 路径跳转
$ echo '
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.bar.com
http:
paths:
- path: /something(/|$)(.*)
pathType: Prefix
backend:
service:
name: http-svc
port:
number: 80
' | kubectl create -f -
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 报错小结
# posthog-ingress-nginx-controller-admission not found
# Error from server (InternalError): error when creating “ingress-nginx-posthog.yaml”: Internal error occurred: failed calling webhook “validate.nginx.ingress.kubernetes.io”: Post “ https://posthog-ingress-nginx-controller-admission.posthog.svc:443/networking/v1/ingresses?timeout=10s”: service “posthog-ingress-nginx-controller-admission” not found
# 原因分析:
类似问题: https://stackoverflow.com/questions/61616203/nginx-ingress-controller-failed-calling-webhook/61681896#61681896
我删除了它创建的命名空间和clusterrole and clusterrolebinding as noted in the documentation,但这并没有删除安装在清单中的ValidatingWebhookConfiguration,但在默认情况下使用helm 时不会删除。
解决方法1:
kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission
解决方法2:
1、检查是否有validation webhook 和服务。
[root@ops ~]# kubectl get -A ValidatingWebhookConfiguration
NAME WEBHOOKS AGE
aws-load-balancer-webhook 2 90d
cert-manager-webhook 1 91d
posthog-ingress-nginx-admission 1 5d1h
vpc-resource-validating-webhook 2 107d
[root@ops ~]# kubectl get svc -n ingress-nginx
No resources found in ingress-nginx namespace.
2
3
4
5
6
7
8
9
10
2、手动删除posthog-ingress-nginx-admission后恢复正常
[root@ops ~]# kubectl get ValidatingWebhookConfiguration/posthog-ingress-nginx-admission -o yaml >posthog-ingress-nginx-admission.yaml
[root@ops ~]# kubectl delete -f posthog-ingress-nginx-admission.yaml
2
3
# no matches for kind “Role” in version “rbac.authorization.k8s.io/v1beta1”
执行异常信息: unable to recognize “ingress-nginx.yaml”: no matches for kind “ClusterRole” in version “rbac.authorization.k8s.io/v1beta1” unable to recognize “ingress-nginx.yaml”: no matches for kind “Role” in version “rbac.authorization.k8s.io/v1beta1” unable to recognize “ingress-nginx.yaml”: no matches for kind “RoleBinding” in version “rbac.authorization.k8s.io/v1beta1” unable to recognize “ingress-nginx.yaml”: no matches for kind “ClusterRoleBinding” in version “rbac.authorization.k8s.io/v1beta1”
原因分析: 自 v1.22 起,Ingress 的 extensions/v1beta1 和networking.k8s.io/v1beta1 API 版本不再提供。 官方文档: https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122
解决方法:
sed -i 's#rbac.authorization.k8s.io/v1beta1#rbac.authorization.k8s.io/v1#' ingress-nginx.yaml
# Unable to continue with install: IngressClass “nginx” in namespace “” exists and cannot be imported into the current release
Error: INSTALLATION FAILED: rendered manifests contain a resource that already exists. Unable to continue with install: IngressClass “nginx” in namespace “” exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error: missing key “meta.helm.sh/release-name”: must be set to “k8s-nginx”; annotation validation error: missing key “meta.helm.sh/release-namespace”: must be set to “nginx-ingress-controller” helm.go:84: [debug] IngressClass “nginx” in namespace “” exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error: missing key “meta.helm.sh/release-name”: must be set to “k8s-nginx”; annotation validation error: missing key “meta.helm.sh/release-namespace”: must be set to “nginx-ingress-controller” rendered manifests contain a resource that already exists. Unable to continue with install
原因分析: 使用 helm 创建nginx-ingress-controller时出错
查看helm chart仓库values.yaml文件
#... ... ...
##查看以下字段
ingressClassResource:
name: nginx ##修改资源名
enabled: true
default: false
controllerClass: "k8s.io/ingress-nginx"
parameters: {}
#... ... ...
2
3
4
5
6
7
8
9
解决方法:
##创建
helm install k8s-nginx bitnami/nginx-ingress-controller -n nginx-ingress-controller --create-namespace --set ingressClassResource.name="nginx-new"
##升级
cd charts/bitnami/nginx-ingress-controller/
helm upgrade --install -f values.yaml --timeout 20m --create-namespace --namespace nginx-ingress-controller k8s-nginx bitnami/nginx-ingress-controller --wait --wait-for-jobs --set ingressClassResource.name="nginx-new" --debug
2
3
4
5
6
如果没生效,使用以下命令:
helm install k8s-nginx bitnami/nginx-ingress-controller -n nginx-ingress-controller --create-namespace --set controller.ingressClassResource.name="nginx-new"
原文链接:Kubernetes 安装配置ingress controller_奔跑在路上的技术博客_51CTO博客 (opens new window)