第一节 Ingress 介绍

前面已经提到,Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但是这两种方式,都有一定的缺点:

  • NodePort方式的缺点是占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就会愈发明显
  • LB方式的缺点是每个service需要一个LB,浪费、麻烦,并且需要kubernetes之外设备的支持。

基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个service的需求。工作机制如下:
 
实际上,Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在Ingress 里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx

  • ingress: kubernetes中的一个对象,作用是定义请求如何转发到service的规则
  • ingress controller: 具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现方式很多,比如Nginx,Contour,Haproxy等

Ingress(以Nginx为例)的工作原理如下

1、 用户编写Ingress规则,说明哪些域名对应kubernetes集群中的哪些service;
2、 Ingress控制器动态感知Ingress服务规则的变化,然后生成一段对应的Nginx配置;
3、 Ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新;
4、 到此为止,其实真正在工作的就是一个Nginx了,内部配置了用户定义的请求转发规则;

 

第二节 Ingress 使用

1. 环境准备

# 创建文件夹
[root@master ~]# mkdir ingress-controller
[root@master ~]# cd ingress-controller/

# 获取ingress-nginx
[root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
[root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
[root@master ingress-controller]# ls
mandatory.yaml  service-nodeport.yaml
[root@master ingress-controller]#

# 创建ingress-nginx
[root@master ingress-controller]# kubectl apply -f ./
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
service/ingress-nginx created

# 查看ingress-nginx
[root@master ingress-controller]# kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-7f74f657bd-c2zwl   1/1     Running   0          3m16s
# 查看service
# 这里可以看到80对应的http端口(外部是30692), 443对应的https端口(外部是30254)
[root@master ingress-controller]# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.97.146.1   <none>        80:31586/TCP,443:32714/TCP   4m6s

2. 准备service和pod

为例后面的实验方便,创建如下图所示的模型
 

创建tomcat-nginx.yaml

---
apiVersion: apps/v1  版本号
kind: Deployment   类型
metadata:  元数据
  name: nginx-deployment   rs名称
  namespace: dev  所属命名空间
spec: 详情
  replicas: 3副本数量3
  selector:选择器,通过它指定该控制器管理哪些pod
    matchLabels:labels匹配规则,用于匹配template
      app: nginx-pod
  template: 模板,当副本数量不足时,会根据模板创建pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
        - name: nginx
          image: nginx:1.17.1
          ports:
            - containerPort: 80

---
apiVersion: apps/v1  版本号
kind: Deployment   类型
metadata:  元数据
  name: tomcat-deployment   rs名称
  namespace: dev  所属命名空间
spec: 详情
  replicas: 3副本数量3
  selector:选择器,通过它指定该控制器管理哪些pod
    matchLabels:labels匹配规则,用于匹配template
      app: tomcat-pod
  template: 模板,当副本数量不足时,会根据模板创建pod副本
    metadata:
      labels:
        app: tomcat-pod
    spec:
      containers:
        - name: tomcat
          image: tomcat:8.5-jre10-slim
          ports:
            - containerPort: 8080

---
apiVersion: v1  版本号
kind: Service   类型
metadata:  元数据
  name: nginx-service   svc名称
  namespace: dev  所属命名空间
spec: 详情
  selector:选择器,通过它指定该控制器管理哪些pod
    app: nginx-pod
  clusterIP: None 将clusterIP设置为None,即可创建headliness Service
  type: ClusterIP
  ports:
    - port: 80   Service端口
      targetPort: 80pod端口

---
apiVersion: v1  版本号
kind: Service   类型
metadata:  元数据
  name: tomcat-service   svc名称
  namespace: dev  所属命名空间
spec: 详情
  selector:选择器,通过它指定该控制器管理哪些pod
    app: tomcat-pod
  clusterIP: None 将clusterIP设置为None,即可创建headliness Service
  type: ClusterIP
  ports:
    - port: 8080   Service端口
      targetPort: 8080
# 创建 pod和service
[root@master ~]# kubectl create -f tomcat-nginx.yaml 
deployment.apps/nginx-deployment created
deployment.apps/tomcat-deployment created
service/nginx-service created
service/tomcat-service created

# 查看service
[root@master ~]# kubectl get svc -n dev
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
nginx-service    ClusterIP   None         <none>        80/TCP     13s
tomcat-service   ClusterIP   None         <none>        8080/TCP   13s

3. http代理

创建ingress-http.yaml

apiVersion: extensions/v1beta1  版本号
kind: Ingress   类型
metadata:  元数据
  name: ingress-http   svc名称
  namespace: dev  所属命名空间
spec: 详情
  rules:
    - host: nginx.abc.com
      http:
        paths:
          - path: /
            backend:
              serviceName: nginx-service
              servicePort: 80
    - host: tomcat.abc.com
      http:
        paths:
          - path: /
            backend:
              serviceName: tomcat-service
              servicePort: 8080

# 创建ingress
[root@master ~]# kubectl create -f ingress-http.yaml 
ingress.extensions/ingress-http created

# 查看ingress
[root@master ~]# kubectl get ing ingress-http -n dev
NAME           HOSTS                          ADDRESS   PORTS   AGE
ingress-http   nginx.abc.com,tomcat.abc.com             80      17s

# 查看ingress详情
[root@master ~]# kubectl  describe ing ingress-http -n dev
Name:             ingress-http
Namespace:        dev
Address:          
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host            Path  Backends
  ----            ----  --------
  nginx.abc.com   
                  /   nginx-service:80 (10.244.1.108:80,10.244.2.178:80,10.244.2.179:80)
  tomcat.abc.com  
                  /   tomcat-service:8080 (10.244.1.107:8080,10.244.1.109:8080,10.244.2.180:8080)
Annotations:
Events:  <none>
[root@master ~]# 

配置host域名

192.168.88.100  nginx.abc.com
192.168.88.100  tomcat.abc.com

 

打开浏览器访问http://nginx.abc.com:31586/和http://tomcat.abc.com:31586/,(端口请查看ingress-nginx的80对应的端口)

[root@master ~]# kubectl get svc ingress-nginx -n ingress-nginx
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.97.146.1   <none>        80:31586/TCP,443:32714/TCP   12m
[root@master ~]#

 

4. https代理

# 生成证书
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=abc.com"

# 创建密钥
kubectl create secret tls tls-secret --key tls.key --cert tls.crt

创建ingress-https.yaml

apiVersion: extensions/v1beta1  版本号
kind: Ingress   类型
metadata:  元数据
  name: ingress-https   svc名称
  namespace: dev  所属命名空间
spec: 详情
  tls:
    - hosts:
        - nginx.abc.com
        - tomcat.abc.com
      secretName: tls-secret指定密钥
  rules:
    - host: nginx.abc.com
      http:
        paths:
          - path: /
            backend:
              serviceName: nginx-service
              servicePort: 80
    - host: tomcat.abc.com
      http:
        paths:
          - path: /
            backend:
              serviceName: tomcat-service
              servicePort: 8080

# 生成证书
[root@master ~]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=abc.com"
Generating a 2048 bit RSA private key
.....................................................................................+++
.............+++
writing new private key to 'tls.key'
-----

# 创建密钥
[root@master ~]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created

[root@master ~]# vim ingress-https.yaml

# 创建sevice
[root@master ~]# kubectl create -f ingress-https.yaml 
ingress.extensions/ingress-https created

# 查看ingress
[root@master ~]# kubectl get ing ingress-https -n dev
NAME            HOSTS                          ADDRESS   PORTS     AGE
ingress-https   nginx.abc.com,tomcat.abc.com             80, 443   15s

# 查看ingress详情,可以看到describe有一个TLS,表示https配置成功
[root@master ~]# kubectl describe ing ingress-https -n dev
Name:             ingress-https
Namespace:        dev
Address:          
Default backend:  default-http-backend:80 (<none>)
TLS:
  tls-secret terminates nginx.abc.com,tomcat.abc.com
Rules:
  Host            Path  Backends
  ----            ----  --------
  nginx.abc.com   
                  /   nginx-service:80 (10.244.1.118:80,10.244.2.195:80,10.244.2.197:80)
  tomcat.abc.com  
                  /   tomcat-service:8080 (10.244.1.116:8080,10.244.1.117:8080,10.244.2.196:8080)
Annotations:
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  30s   nginx-ingress-controller  Ingress dev/ingress-https
[root@master ~]# 

打开浏览器访问https://nginx.abc.com:32714/和https://tomcat.abc.com:32714/,(端口请查看ingress-nginx的443对应的端口)

[root@master ~]# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.97.146.1   <none>        80:31586/TCP,443:32714/TCP   38m
[root@master ~]# 

 

问题 遇到的问题

1. 最后打开浏览器无法访问

浏览器一直空转
排查发现ingress-http的镜像下载失败,使用官方镜像即可。
 
 
如果七牛的镜像无法下载,请使用官方镜像。

# 七牛镜像(可能不可靠)
quay-mirror.qiniu.com/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0

修改使用官方镜像:

# 官方镜像(默认)
quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0