目录
一、Ingress 是什么
1.1Service的作用
1.2Ingress简介
二、Ingress 安装
三、Ingress 代理访问
3.1Ingress HTTP 代理访问
3.2 Ingress: HTTPS 代理访问
3.3Ingress Contronler怎么工作的?
一、Ingress 是什么
1.1Service的作用
- 对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制;
- 对集群外部,他类似负载均衡器,可以在集群外部对pod进行访问。在Kubernetes中,Pod的IP地址和service的ClusterIP仅可以在集群网络内部做用,对于集群外的应用是不可见的。
为了使外部的应用能够访问集群内的服务,Kubernetes目前提供了以下几种方案:
- NodePort:将service暴露在节点网络上,NodePort背后就是Kube-Proxy,Kube-Proxy是沟通service网络、Pod网络和节点网络的桥梁。测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的瑞口管理就是个灾难。因为每个端口只能是一种服务,端口范围只能是 30000-32767。
- LoadBalancer:通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。这种用法仅用于在公有云服务提供商的云平台上设置Servic的场景。受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。
- Ingress:只需一个或者少量的公网IP和LB,即可同时将多个HTTP服务暴露到外网,七层反向代理。可以简单理解为service的service,它其实就是一组基于域名和URL路径,把用户的请求转发到一个或多个service的规则。
NodePort存在的不足:
• 一个端口只能一个服务使用,端口需提前规划
• 只支持4层负载均衡,使用 iptables或IPVS做分流,不支持基于域名或者URL的匹配
1.2Ingress简介
Ingress公开了从集群外部到集群内服务的HTTP和HTTPS路由的规则集合,而具体实现流量路由则是由Ingress Controller负责。
• Ingress:K8s中的一个抽象资源,给管理员提供一个暴露应用的入口定义方法
• Ingress Controller:根据Ingress生成具体的路由规则,并对Pod负载均衡器,提供统一的端口(80/443)
Ingress相当于一个7层的负载均衡器,是k8s对反向代理的一个抽象。大概的工作原理也确实类似于Nginx,可以理解成在 Ingress 里建立一个个映射规则 , ingress Controller 通过监听 Ingress这个api对象里的配置规则并转化成 Nginx 的配置(kubernetes声明式API和控制循环) , 然后对外部提供服务。
Ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。
ingress通过http或https暴露集群内部service,给service提供外部URI、负载均衡、SSL/TLS能力以及基于域名的反向代理。ingress要依靠ingress-controiler来具体实现以上功能。
ingress包括:ingress controller和ingress resources
ingress controller:核心是一个deployment,实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要编写的yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是NodePort或者LoadBalancer。
ingress resources:这个就是一个类型为Ingress的k8s api对象了,这部分则是面向开发人员。
Ingress解决的是新的服务加入后,域名和服务的对应问题,基本上是一个ingress的对象,通过yaml进行创建和更新进行加载。
Ingress Controller是将Ingress这种变化生成一段Nginx的配置,然后将这个配置通过Kubernetes API写到Nginx的Pod中,然后reload.(注意:写入 nginx.conf 的不是service的地址,而是service backend 的 pod 的地址,避免在 service 在增加一层负载均衡转发)(转载)
从上图中可以很清晰的看到,实际上请求进来还是被负载均衡器拦截,比如 nginx,然后 Ingress Controller 通过跟 Ingress 交互得知某个域名对应哪个 service,再通过跟 APIServer 交互得知 service 地址等信息;综合以后生成配置文件实时写入负载均衡器,然后负载均衡器 reload 该规则便可实现服务发现,即动态映射。
了解了以上内容以后,这也就很好的说明了我为什么喜欢把负载均衡器部署为 Daemon Set;因为无论如何请求首先是被负载均衡器拦截的,所以在每个 node 上都部署一下,同时 hostport 方式监听 80 端口;那么就解决了其他方式部署不确定 负载均衡器在哪的问题,同时访问每个 node 的 80 都能正确解析请求;如果前端再 放个 nginx 就又实现了一层负载均衡。
Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。(转载)
二、Ingress 安装
Ingress Controller有很多实现,我们这里采用官方维护的Nginx控制器。
项目地址:GitHub - kubernetes/ingress-nginx: Ingress-NGINX Controller for Kubernetes
注意事项:
• 镜像地址修改成国内的:lizhenliang/nginx-ingress-controller:0.30.0
• 将Ingress Controller暴露,一般使用宿主机网络(hostNetwork: true)或者使用NodePort
其他控制器:Ingress Controllers | Kubernetes
下载 Ingress镜像:
wget --no-check-certificate https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
mandatory.yaml 部署
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
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
---
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: udp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
annotations:
prometheus.io/port: "10254"
prometheus.io/scrape: "true"
spec:
hostNetwork: true
# wait up to five minutes for the drain of connections
terminationGracePeriodSeconds: 300
serviceAccountName: nginx-ingress-serviceaccount
nodeSelector:
kubernetes.io/os: linux
containers:
- name: nginx-ingress-controller
image: lizhenliang/nginx-ingress-controller:0.30.0
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --publish-service=$(POD_NAMESPACE)/ingress-nginx
- --annotations-prefix=nginx.ingress.kubernetes.io
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 101
runAsUser: 101
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
部署 ingress-controller对外提供服务:
kubectl apply -f ingress-controller.yaml
kubectl get pod -n ingress-nginx -o wide
nginx-ingress-controller查看:
三、Ingress 代理访问
3.1Ingress HTTP 代理访问
创建 deployment和 svc :
apiVersion: apps/v1
kind: Deployment
metadata:
name: web1
namespace: default
annotations: # 记录回滚参数
kubernetes.io/change-cause: "web.v1-nginx-1.17" #记录到revision中的内容,记录版本号
spec:
replicas: 3
selector:
matchLabels:
app: web1
template:
metadata:
labels:
app: web1
spec:
containers:
- name: web
image: nginx:1.17
---
apiVersion: v1
kind: Service
metadata:
name: web1
namespace: default
spec:
ports:
- port: 80 # service端口
protocol: TCP # 协议
targetPort: 80 # 容器端口
selector: # 标签选择器
app: nginx # 指定关联Pod的标签
type: ClusterIP # 服务类型
启动 web1 pod 并暴露 ClusterIP 访问端口80
本地电脑绑定hosts记录对应ingress里面配置的域名例:创建 web1 Ingress :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web1
spec:
rules:
- host: web1.ctnrs.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web1
port:
number: 80 ## clusterIP 端口
查看Ingress是否部署成功
windows 服务器主机 C:\Windows\System32\drivers\etc\hosts 添加域名映射关系
192.168.2.118 k8s-node1 web1.ctnrs.com
192.168.2.210 k8s-node2 web1.ctnrs.com
使用域名 web1.ctnrs.com 成功访问
3.2 Ingress: HTTPS 代理访问
配置HTTPS步骤:
1、准备域名证书文件(来自:openssl/cfssl工具自签或者权威机构颁发)
2、将证书文件保存到Secret
kubectl create secret tls blog-ctnrs-com --cert=blog.ctnrs.com.pem -- key=blog.ctnrs.com-key.pem
3、Ingress规则配置tls
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: blog
spec:
tls:
- hosts:
- blog.ctnrs.com
secretName: blog.ctnrs.com
rules:
- host: blog.ctnrs.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web1
port:
number: 80
windows 服务器主机 C:\Windows\System32\drivers\etc\hosts 添加域名映射关系
192.168.2.118 k8s-node1 web1.ctnrs.com blog.ctnrs.com
192.168.2.210 k8s-node2 web1.ctnrs.com blog.ctnrs.com
由于是自签的证书,所以会报不可信证书,继续访问就可以
3.3Ingress Contronler怎么工作的?
下图<>里面代表资源类型,无此符号的部分是这个资源的名字,图中实线部分是实际访问流程,虚线部分是路由规则的维护。
流程分解:
① 企业级应用场景最常用的方式就是用外层4层或7层负载来保证后端服务的可用性,如图是负载nginx这个ingress-controller的svc
② nginx-controller有自己的service,用的是nodeport模式对外暴露端口,关联后端ingress-controller
③ingress-controller拿到请求后转发给后端的service
④service通过标签选择器,找到后面对应的pod
*⑤ingress里面test.k8s.com这个域名的路由规则
*⑥ingress的规则会通过k8s-apiserver对外提供查询
*⑦ingress-controller查询k8s-apiserver拿到ingress路由规则,并更新在自己的配置文件里面
参考原文链接:k8s ingress-controller处理流程及原理_A � 戏 子、Libra的博客-CSDN博客
https://blog.csdn.net/yrx420909/article/details/105724292
https://blog.51cto.com/u_15382481/5205194