Ingress 介绍
在前面我们已经知道,Service 对集群之外暴露服务的主要方式有两种:NodePort 和 LoadBalance,但是这两种方式,都有一定的缺点
- NodePort 方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就更加明显
- LoadBalance 的缺点是每个 Service 需要一个 LoadBalance,浪费、麻烦,并且需要 kubernetes 之外设备的支持
基于这种现状,kubernetes 提供了 ingress 资源对象,ingress 只需要一个 NodePort 或者一个 LoadBalance 就可以满足暴露多个 Service 的需要,工作机制大致如下图所示:
实际上,Ingress 相当于一个 7 层的负载均衡器,是 kubernetes 对反向代理的一个抽象,它的工作原理类似于 Nginx,可以理解成在 Ingress 里建立诸多映射规则,Ingress Controller 通过监听这些配置规则并转化成 Nginx 的反向代理配置 , 然后对外部提供服务。在这里有两个核心概念:
- ingress:kubernetes 中的一个对象,作用是定义请求如何转发到 service 的规则
- ingress controller:具体实现反向代理及负载均衡的程序,对 ingress 定义的规则进行解析,根据配置的规则来实现请求转发,实现方式有很多,比如 Nginx, Contour, Haproxy 等等
Ingress(以Nginx为例)的工作原理如下:
- 用户编写 Ingress 规则,说明哪个域名对应 kubernetes 集群中的哪个 Service
- Ingress 控制器动态感知 Ingress 服务规则的变化,然后生成一段对应的 Nginx 反向代理配置
- Ingress 控制器会将生成的 Nginx 配置写入到一个运行着的 Nginx 服务中,并动态更新
- 到此为止,其实真正在工作的就是一个 Nginx 了,内部配置了用户定义的请求转发规则
lngress-nginx可解决的问题
- 动态配置服务:如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的 k8s 服务. 而如果用了 Ingress-nginx, 只需要配置好这个服务, 当服务启动时, 会自动注册到 Ingress 的中, 不需要额外的操作
- 减少不必要的端口映射:配置过 k8s 的都清楚, 第一步是要关闭防火墙的, 主要原因是 k8s 的很多服务会以 NodePort 方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而 Ingress 可以避免这个问题, 除了 Ingress 自身服务可能需要映射出去, 其他服务都不要用 NodePort 方式
ingress-nginx 实战
官网:https://kubernetes.github.io/ingress-nginx/
创建一个命名空间 zouzou
# 创建命名空间 zouzou kubectl create ns zouzou
创建 httpd 服务、Service 资源对象
创建一个 httpd-01.yaml 的文件,内容如下
apiVersion: apps/v1 kind: Deployment # 类型为 Deployment metadata: name: web01 # Deployment 的名称 namespace: zouzou # ns spec: replicas: 3 # 3 个副本数 selector: # 标签选择器 matchLabels: app: httpd01 template: metadata: labels: app: httpd01 spec: containers: - name: httpd image: httpd:2.4 # 镜像 --- apiVersion: v1 kind: Service # 类型为 Service metadata: name: httpd-svc # svc 的名称 namespace: zouzou spec: selector: app: httpd01 # 选择标签为 app=httpd01 的 pod,也就是上面的 ports: - protocol: TCP port: 80 targetPort: 80
运行 yaml 文件
# 创建 Deployment 和 Service [root@dce-10-6-215-215 tmp]# kubectl apply -f httpd-01.yaml deployment.apps/web01 created service/httpd-svc created
运行完等会查看是否正常启动
# 查看 pod、svc、deployment [root@dce-10-6-215-215 tmp]# kubectl get pod,svc,deploy -n zouzou NAME READY STATUS RESTARTS AGE pod/web01-7445cbbd94-hrb2p 1/1 Running 0 7m9s pod/web01-7445cbbd94-qx6np 1/1 Running 0 7m9s pod/web01-7445cbbd94-s5z9v 1/1 Running 0 7m10s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/httpd-svc ClusterIP 172.31.63.225 <none> 80/TCP 7m9s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/web01 3/3 3 3 7m10s
创建 tomcat 服务及 service
创建一个 tomcat-01.yaml 文件,内容如下
apiVersion: apps/v1 kind: Deployment metadata: name: web02 # deployment 的名称 namespace: zouzou spec: replicas: 3 selector: matchLabels: app: tomcat01 template: metadata: labels: app: tomcat01 # label spec: containers: - name: tomcat image: tomcat:8-jdk8 # 镜像 --- apiVersion: v1 kind: Service metadata: name: tomcat-svc # svc 名称 namespace: zouzou spec: selector: app: tomcat01 # 匹配 app=tomcat01 的 pod ports: - protocol: TCP port: 8080 targetPort: 8080
运行 yaml 文件
# 创建 deployment 和 svc [root@dce-10-6-215-215 tmp]# kubectl apply -f tomcat-01.yaml deployment.apps/web02 created service/tomcat-svc created
在来查看 pod 和 svc 是否都正常
# 查看 pod,svc,deployment [root@dce-10-6-215-215 tmp]# kubectl get pod,svc,deploy -n zouzou NAME READY STATUS RESTARTS AGE pod/web01-7445cbbd94-hrb2p 1/1 Running 0 22m pod/web01-7445cbbd94-qx6np 1/1 Running 0 22m pod/web01-7445cbbd94-s5z9v 1/1 Running 0 22m pod/web02-fff958574-9j7cl 1/1 Running 0 57s pod/web02-fff958574-c9hz9 1/1 Running 0 57s pod/web02-fff958574-v77cc 1/1 Running 0 57s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/httpd-svc ClusterIP 172.31.63.225 <none> 80/TCP 22m service/tomcat-svc ClusterIP 172.31.116.87 <none> 8080/TCP 57s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/web01 3/3 3 3 22m deployment.apps/web02 3/3 3 3 57s
使用 cluster-ip 访问 pod 看能否访问成功
# 访问 httpd [root@dce-10-6-215-215 tmp]# curl 172.31.63.225 <html><body><h1>It works!</h1></body></html> # 访问 tomcat,因为没有页面,所以是 404 [root@dce-10-6-215-215 tmp]# curl 172.31.116.87:8080 <!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/8.5.73</h3></body></html>[root@dce-10-6-215-215 tmp]#
创建 Ingress-nginx 资源对象
创建文件夹 ingress-controller 存放 ingress-nginx 的 yaml 文件
# 创建文件夹 [root@dce-10-6-215-215 tmp]# mkdir ingress-controller # 进入到文件夹里面 [root@dce-10-6-215-215 tmp]# cd ingress-controller/ [root@dce-10-6-215-215 ingress-controller]#
获取 ingress-nginx,本次案例使用的是0.30版本
# 获取 ingress-nginx,本次案例使用的是0.30版本 [root@dce-10-6-215-215 ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml [root@dce-10-6-215-215 ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
下载完成之后查看
[root@dce-10-6-215-215 ingress-controller]# ls mandatory.yaml service-nodeport.yaml
修改 mandatory.yaml 文件中的代码
关于上面 yaml 文件中写入的 “hostNetwork: true” 具体解释:如果使用此网络参数,那么 pod 中运行的应用程序可以直接使用 Node 节点端口,这样 node 节点主机所在的网络的其他主机,都可以通过访问到此应用程序。
修改完成之后运行 mandatory.yaml 文件
[root@dce-10-6-215-215 ingress-controller]# kubectl apply -f mandatory.yaml namespace/ingress-nginx created configmap/nginx-configuration created configmap/tcp-services created configmap/udp-services created serviceaccount/nginx-ingress-serviceaccount created clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created role.rbac.authorization.k8s.io/nginx-ingress-role created rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created deployment.apps/nginx-ingress-controller created limitrange/ingress-nginx created
确定 Ingress-nginx 容器运行正常
# 确定 Ingress-nginx 容器运行正常,注意,namespace 是在 ingress-nginx 下 [root@dce-10-6-215-215 ingress-controller]# kubectl get pod -n ingress-nginx NAME READY STATUS RESTARTS AGE nginx-ingress-controller-5fc65f5fd7-tcskb 1/1 Running 0 29m