Kubernetes - 使用Ingress、Ingress控制器(Ingress Controller)转发请求

Kubernetes - 使用Ingress、Ingress控制器(Ingress Controller)转发请求_第1张图片

上图是一个客户端访问k8s集群服务的示意图,本文只讲解ingress控制器、NodePort类型的Service对外暴露端口两部分。Ingress和Ingress控制器的官方定义如下。

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP,Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

Ingress通常负责通过负载均衡器来实现 Ingress。

官方定义看得人云里雾里。我用大白话解释,打个比方Ingress控制器类似于与nginx,Ingress类似于nginx的配置文件。如果我们只安装nginx,不写nginx的配置文件,例如不写转发规则,则此nginx将毫无意义;反过来,若只有nginx的配置文件,但没装nginx,则配置文件无运行载体。所以Ingress和Ingress控制器是配合着使用的。

从上图可以看出Ingress和Ingress控制器是负责对外部请求的管理、转发,并没有对外暴露端口,需要在Ingress前面加一个NodePort类型的Service,通过这个Service对外暴露端口。

在使用Ingress之前,先要把应用pod(上图中的appX-pod-X)和应用的service(上图中的appX-svc)创建好,读者可阅读 kubernetes零宕机部署探索  创建。但有一点要注意, 需要将kubernetes零宕机部署探索 中的Service改成ClusterIP类型,即上图中app1-svc、app2-svc是ClusterIP类型,红色框的Service才是暴露端口的NodePort类型。具体做法如下

将service-nodeport.yaml改名为service-app3.yaml。(需要改名是因为待会儿要下载一个yaml文件,但那个yaml文件名也是service-nodeport.yaml,为避免冲突,先改下名字)

mv service-nodeport.yaml service-app3.yaml

修改service-app3.yaml,使用ClusterIP类型

apiVersion: v1
kind: Service
metadata:
  name: service-app3
spec:
  selector:
    app: app3
  # 使用NodePort方式暴露一个外部端口供调试使用
  # type: NodePort
  type: ClusterIP
  ports:
  - name: http
    port: 10013
    targetPort: 10013
    # 外部端口
    # nodePort: 30013

安装Ingress、Ingress控制器、暴露端口的Service

1、本文选择的控制器是ingress-nginx,使用裸机方式安装。云厂商不同,安装方式也不同,详情 ingress-nginx github。

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/mandatory.yaml
kubectl apply -f mandatory.yaml
kubectl get pod -n ingress-nginx

下载mandatory.yaml文件可能会被墙,请走代理。

2、安装暴露集群端口的Service。注意本地磁盘不要有service-nodeport.yaml同名文件。

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/provider/baremetal/service-nodeport.yaml
可修改此Service的端口绑定,将Service的80端口绑定给宿主机30080,443端口绑定给宿主机30443。修改如下:

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
      # 绑定裸机端口
      nodePort: 30080
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
      # 绑定裸机端口
      nodePort: 30443
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

kubectl apply -f service-nodeport.yaml
kubectl get svc -n ingress-nginx

从service-nodeport.yaml可以看出来,此Service暴露的两个端口80、443,将外部请求转给ingress-nginx控制器。

对比service-nodeport.yaml的selecor和mandatory.yaml的Deployment labels,ingress-nginx控制器的labels就是:

    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
Kubernetes - 使用Ingress、Ingress控制器(Ingress Controller)转发请求_第2张图片

我的k8s集群主节点ip是192.168.3.151,浏览器打开 http://192.168.3.151:30080/ 出现404 not found表明ingress-nginx、暴露服务Service 安装成功。

3、ingress-nginx接收请求后,需要将请求转给pod。我们写一个ingress转发规则。

vim ingress-my.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-my
  annotations:
    # 控制器使用nginx
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    # host不支持IP,必须是域名
  - host: k8s01.com
    http:
      paths:
        # 以app3开头的请求转给service-app3的10013端口
      - path: /app3
        backend:
          serviceName: service-app3
          servicePort: 10013

kubectl apply -f ingress-my.yaml

4、修改电脑的C:\Windows\System32\drivers\etc\hosts文件,添加DNS规则,将k8s01.com的请求转发给k8s集群主节点(主节点ip是192.168.xx.xx)。

192.168.xx.xx k8s01.com

5、请求接口:  http://k8s01.com:30080/app3/test/get

至此,外部环境访问集群内部服务的功能就实现了。

ingress配置https

1、生成私钥
openssl genrsa -out tls.key 2048
2、生成证书
openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=k8s01.com

3、私钥和证书不能直接被ingress控制器使用,需要用到Secret。Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象, 这样的信息被放在 Pod 规约中或者镜像中。

使用私钥和证书创建secret,名称是secret-k8s01
kubectl create secret tls secret-k8s01 --cert=tls.crt --key=tls.key

4、ingress配置tls,使用secret-k8s01

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-my
  annotations:
    # 控制器使用nginx
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    # host不支持IP,必须是域名
  - host: k8s01.com
    http:
      paths:
        # 以app3开头的请求转给service-app3的10013端口
      - path: /app3
        backend:
          serviceName: service-app3
          servicePort: 10013
  tls:
  - hosts:
    - k8s01.com
    secretName: secret-k8s01

kubectl apply -f ingress-my.yaml 

5、使用https访问集群服务:https://k8s01.com:30443/app3/info

注意:暴露端口Service的443端口在宿主机上的映射是30443端口。

ingress-nginx的转发实现

ingress控制器本质上是一个pod,进入ingress-nginx中查看ingress在nginx.conf如何体现。

kubectl get pods -n ingress-nginx

kubectl exec -n ingress-nginx -it nginx-ingress-controller-XXXXXX -- /bin/sh

cat nginx.conf

Kubernetes - 使用Ingress、Ingress控制器(Ingress Controller)转发请求_第3张图片

正如前面所说,ingress规则最终是转化到ingress控制器配置文件中。

 

最后提一点:Ingress控制器不会将请求转给应用的Service,而是直接将请求转给pod。注意看博客开头的图,Ingress控制器到app1-svc、app2-svc的箭头,用的是灰色箭头,其实ingress会将service的endpoint保存起来,接收到请求后,没有将请求转发给service,而是直接转发给service的endpoint。

Kubernetes - 使用Ingress、Ingress控制器(Ingress Controller)转发请求_第4张图片

 

 

你可能感兴趣的:(docker+k8s)