Kubernetes 对外服务 Ingress

Ingress 简介

service的作用体现在两个方面,对集群内部,它不断跟踪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地址。这种用法仅用于在公有云服务提供商的云平台上设置 Service 的场景。 受限于云平台,且通常在云平台部署LoadBalancer还需要额外的费用。(需要外部负载均衡器)

在service提交后,Kubernetes就会调用CloudProvider在公有云上为你创建一个负载均衡服务,并且把被代理的Pod的IP地址配置给负载均衡服务做后端。

●externalIPs:service允许为其分配外部IP,如果外部IP路由到集群中一个或多个Node上,Service会被暴露给这些externalIPs。通过外部IP进入到集群的流量,将会被路由到Service的Endpoint上。 (由于clusterip只能在集群内访问,若在集群外访问添加externalips)(IP管理麻烦)

service:NodePort LoadBalancer externalIPs 只支持四层反向代理,端口数量有限,如果业务服务应用很多时端口的管理成本会比较高


●Ingress:只需一个或者少量的公网IP和LB,即可同时将多个HTTP服务暴露到外网,七层反向代理。

可以简单理解为service的service,它其实就是一组基于域名和URL路径,把用户的请求转发到一个或多个service的规则。

ingress:支持七层反向代理,可自定义规则根据用户请求的 域名 或 URL路径 转发给指定的 service

Ingress 组成

●ingress ingress资源对象:(规则)

设置转发规则,告诉 ingress控制器应该根据什么域名或URL路径转发给相应的 service 资源

ingress是一个API对象,通过yaml文件来配置,ingress对象的作用是定义请求如何转发到service的规则,可以理解为配置模板。

ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS能力以及基于域名的反向代理。ingress要依靠 ingress-controller 来具体实现以上功能。

●ingress-controller ingress控制器:(实现转发)

根据 ingress 资源配置的转发规则转发用户请求的组件,以 Pod 形式运行的

ingress-controller是具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。

ingress-controller并不是k8s自带的组件,实际上ingress-controller只是一个统称,用户可以选择不同的ingress-controller实现,目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,其他还有很多第三方维护的ingress-controller,具体可以参考官方文档。但是不管哪一种ingress-controller,实现的机制都大同小异,只是在具体配置上有差异。

一般来说,ingress-controller的形式都是一个pod,里面跑着daemon程序和反向代理程序。daemon负责不断监控集群的变化,根据 ingress对象生成配置并应用新配置到反向代理,比如ingress-nginx就是动态生成nginx配置,动态更新upstream,并在需要的时候reload程序应用新配置。为了方便,后面的例子都以k8s官方维护的ingress-nginx为例。

Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx

Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/

总结:ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到 ingress-controller, 而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名、哪些URL要转发到哪些service等等。
Ingress-Nginx 工作原理

(1)ingress-controller通过和 kubernetes APIServer 交互,动态的去感知集群中ingress规则变化,

(2)然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,

(3)再写到nginx-ingress-controller的pod里,这个ingress-controller的pod里运行着一个Nginx服务,控制器会把生成的 nginx配置写入 /etc/nginx.conf文件中,

(4)然后reload一下使配置生效。以此达到域名区分配置和动态更新的作用。
ingress 的配置

bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: 资源名称
spec:
  ingressClassName: ingress控制器类型
  rules:
  - host: 目标域名(可以精确匹配或通配符匹配,比如 *.xue.com 可以匹配www.xue.com或mail.xue.com等,但不能匹配ky22.www.xue.com)
    http:
      paths:
      - path: 目标域名后的URL路径(比如 / 代表网页根路径,或者 /test)
        pathType: Prefix|Exact(Exact用于精确匹配URL路径;Prefix用于前缀匹配,且只能匹配完整的字符串,/abc能匹配/abc/123,但不能匹配/abc123)
        backend:
          service:
            name: 目标service资源的名称
            port:
              number: 目标service的端口

      - path: URL路径2
        ....

  - host: 域名2
    http:
    ....

部署 nginx-ingress-controller

1、部署ingress-controller Pod及相关资源

复制代码
mkdir /opt/ingress
cd /opt/ingress

官方下载地址:

复制代码
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml

上面可能无法下载,可用国内的 gitee

复制代码
wget https://gitee.com/mirrors/ingress-nginx/raw/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml

修改镜像地址为:

复制代码
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.0@sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5

image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660

ingress 暴露服务的方式

●方式一:DaemonSet+HostNetwork+nodeSelector(性能)

用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/443端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。 比较适合大并发的生产环境使用。

●方式二:Deployment+NodePort模式的Service(安全性)

同样用deployment模式部署ingress-controller,并创建对应的service,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口(可手动指定),一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。

NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响。

●方式三:Deployment+LoadBalancer 模式的 Service

如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个 type为 LoadBalancer 的 service 关联这组 pod。 大部分公有云,都会为 LoadBalancer 的 service 自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向该地址,就实现了集群服务的对外暴露

ingress 的使用
方法1 ------ DaemonSet + Host网络模式 部署 ingress-controller
数据流向

客户端 -> 防火墙、前端负载均衡器 -> Node节点的80/443端口进入ingress-controller -> 根据转发规则 -> 业务Pod的service -> 业务Pod

方法2/3 ------ Deployment + NodePort/LoadBalancer类型的service 部署 ingress-controller
数据流向

客户端 -> 防火墙、前端负载均衡器 -> ingress-controller的service(NodeIP:NodePort)-> ingress-controller -> 根据转发规则 -> 业务Pod的service -> 业务Pod

采用方式一:DaemonSet+HostNetwork+nodeSelector

3、指定 nginx-ingress-controller 运行在 node02 节点

复制代码
kubectl label node node02 ingress=true

kubectl get nodes --show-labels

4、修改 Deployment 为 DaemonSet ,指定节点运行,并开启 hostNetwork 网络

上方获取的deploy yaml配置文件还需要进行修改↓

复制代码
vim deploy.yaml
...
apiVersion: apps/v1
# 修改 kind
#kind: Deployment
kind: DaemonSet
......
spec:
  ......
  template:
    ......
    spec:
      # 使用宿主机网络
      hostNetwork: true
      # 修改选择节点选择器
      nodeSelector:
        ingress: "true"
......

5、启动 nginx-ingress-controller

复制代码
kubectl apply -f deploy.yaml

//nginx-ingress-controller 已经运行 node02 节点

复制代码
kubectl get pod -n ingress-nginx -owide

NAME                                        READY   STATUS      RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-vvxjr        0/1     Completed   0          19m   10.244.1.24     node01   <none>           <none>
ingress-nginx-admission-patch-9gmdd         0/1     Completed   0          19m   10.244.1.25     node01   <none>           <none>
ingress-nginx-controller-575585684c-9qbwp   1/1     Running     0          10m   192.168.80.30   node02   <none>           <none>

kubectl get svc -n ingress-nginx

NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.96.3.13      <none>        80:32338/TCP,443:30008/TCP   19m
ingress-nginx-controller-admission   ClusterIP   10.96.175.162   <none>        443/TCP                      19m

//到 node02 节点查看

复制代码
netstat -lntp | grep nginx
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      68911/nginx: master 
tcp        0      0 0.0.0.0:8181            0.0.0.0:*               LISTEN      68911/nginx: master 
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      68911/nginx: master 

由于配置了 hostnetwork,nginx 已经在 node 主机本地监听 80/443/8181 端口。其中 8181 是 nginx-controller 默认配置的一个 default backend(Ingress 资源没有匹配的 rule 对象时,流量就会被导向这个 default backend)。

这样,只要访问 node 主机有公网 IP,就可以直接映射域名来对外网暴露服务了。如果要 nginx 高可用的话,可以在多个 node 上部署,并在前面再搭建一套 LVS+keepalived 做负载均衡。

6、创建 ingress 规则,引用ingressclass,并且设定转发规则

先创建一个 deploy 和 svc,以便测试ingress转发到svc和pod上

复制代码
vim service-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-app-svc
spec:
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80 #service的端口
    targetPort: 80 #容器内端口
  selector:
    app: nginx

//创建 ingress 设置匹配规则,转发到对应service

复制代码
kubectl get ingressclasses

NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       22m

kubectl create ingress nginx-app-ingress --class=nginx --rule="www.xue.com/=nginx-app-svc:80" --dry-run=client -o yaml > ingress-app.yaml 
bash 复制代码
vim ingress-app.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-app-ingress
spec:
  ingressClassName: "nginx" #对应刚刚创建的ingressClass名
  rules:
  - host: www.xue.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-app-svc
            port:
              number: 80 #转发到nginx-app-svc(service)的80端口
...........多路径匹配转发则继续添加...........
#      - path: /abc #这里匹配/abc子路径
#        pathType: Prefix
#        backend:
#          service:
#            name: nginx-app-svc2 #转发到这个svc(根据需求自定义)。如果没有这个svc则先创建(创建pod后expose即可一键创建pod对应的svc)
#            port:
#              number: 8090 #转发到nginx-app-svc2 service的8090端口
-------------------------------------------------------------------------------------------
ingressClassName 指定 IngressClass,用来指定选择的 Ingress Controller

host 主机名可以是精确匹配,或者使用通配符来匹配,但通配符仅覆盖一个 DNS 标签(例如 *.foo.com 不匹配 baz.bar.foo.com)。

pathType 支持的路径类型有三种:
●Exact:精确匹配 URL 路径,且区分大小写。

●Prefix:基于以 / 分隔的 URL 路径前缀匹配。匹配区分大小写。如果路径的最后一个元素是请求路径中最后一个元素的子字符串,则不会匹配 
(例如:/foo/bar 匹配 /foo/bar/baz, 但不匹配 /foo/barbaz)。

●ImplementationSpecific:对于这种路径类型,匹配方法取决于 IngressClass。具体实现可以将其作为单独的 pathType 处理或者与 Prefix 或 Exact 类型作相同处理。
具体可详见:https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/#the-ingress-resource
复制代码
kubectl apply -f service-nginx.yaml
kubectl apply -f ingress-app.yaml

kubectl get pods

NAME                         READY   STATUS    RESTARTS   AGE
nginx-app-7bffc778db-sw2hl   1/1     Running   0          42s
nginx-app-7bffc778db-xsd5q   1/1     Running   0          42s

kubectl get ingress

NAME         CLASS   HOSTS         ADDRESS      PORTS   AGE
ingress-v1   nginx   www.xue.com   10.96.3.13   80      39s

7、测试访问

//本地 host 添加域名解析

复制代码
vim /etc/hosts

192.168.80.101 master
192.168.80.102 node01
192.168.80.103 node02
192.168.80.103 www.xue.com     #nginx-ingress-controller所在的节点(此时为node02)

curl http://www.xue.com

8、查看 nginx-ingress-controller

复制代码
kubectl get pod -n ingress-nginx -o wide

NAME                             READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
nginx-ingress-controller-99h72   1/1     Running   0          93s   192.168.80.15   node02   <none>           <none>

kubectl exec -it nginx-ingress-controller-99h72 -n ingress-nginx /bin/bash
 # more /etc/nginx/nginx.conf

可以看到从 start server www.xue.com 到 end server www.xue.com 之间包含了此域名用于反向代理的配置

采用方式二:Deployment+NodePort模式的Service

1、下载 nginx-ingress-controller 配置文件

复制代码
mkdir /opt/ingress-nodeport
cd /opt/ingress-nodeport

官方下载地址:

复制代码
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml

上面可能无法下载,可用国内的 gitee

复制代码
wget https://gitee.com/mirrors/ingress-nginx/raw/controller-v1.3.0/deploy/static/provider/cloud/deploy.yaml

修改镜像地址为:

复制代码
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.0@sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5

image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660

2、修改下载的deploy.yaml配置文件

bash 复制代码
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  #externalTrafficPolicy: Local      #注释此行,值为Cluster表示流量可以转发到其他节点上的Pod;Local表示:流量只发给本机的Pod
  ports:
    nodePort: 30080 #✨添加 可以指定端口号 若不指定则为随机
  type: NodePort     #Service类型设置为 NodePort 或 LoadBalancer

LOCAL设置区别如下

具体的完整配置

若指定端口号,则可以通过域名(若设置了host映射)/nodeip:30080 30443进行访问

3、启动 nginx-ingress-controller

复制代码
kubectl apply -f deploy.yaml

kubectl get pod,svc -n ingress-nginx

NAME                                            READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-vvxjr        0/1     Completed   0          37m
pod/ingress-nginx-admission-patch-9gmdd         0/1     Completed   0          37m
pod/ingress-nginx-controller-575585684c-9qbwp   1/1     Running     0          29m

NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.96.3.13      <none>        80:30080/TCP,443:30443 TCP   37m
service/ingress-nginx-controller-admission   ClusterIP   10.96.175.162   <none>        443/TCP                      37m

Ingress HTTP 代理访问

复制代码
cd /opt/ingress-nodeport

#创建 deployment、Service、Ingress Yaml 资源

复制代码
vim ingress-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-test
spec:
  ingressClassName: "nginx"
  rules:
  - host: www.benet.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: nginx-svc
            port:
              number: 80

kubectl apply -f ingress-nginx.yaml

kubectl get svc,pods -o wide

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   8h    <none>
service/nginx-svc    ClusterIP   10.96.212.214   <none>        80/TCP    65s   name=nginx
NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
pod/nginx-app-65d7b99f6b-l4g65   1/1     Running   0          65s   10.244.1.8   node01   <none>           <none>
pod/nginx-app-65d7b99f6b-zcqgp   1/1     Running   0          65s   10.244.2.8   node02   <none>           <none>

进入pod写入不同网页文件,以便测试转发

复制代码
kubectl exec -it pod/nginx-app-65d7b99f6b-l4g65 bash
 # cd /usr/share/nginx/html/
 # echo 'this is web1' >> index.html 

kubectl exec -it pod/nginx-app-65d7b99f6b-zcqgp bash
 # cd /usr/share/nginx/html/
 # echo 'this is web2' >> index.html

#测试访问

复制代码
curl 10.96.212.214
bash 复制代码
kubectl get svc -n ingress-nginx

NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.96.67.119   <none>        80:30080/TCP,443:30443/TCP   59m

#本地 host 添加域名解析

复制代码
vim /etc/hosts

192.168.80.101 master
192.168.80.102 node01
192.168.80.103 node02
192.168.80.103 www.xue.com www.benet.com #ip随意,只要在集群中的节点即可。注释掉了local后,可以转发到其他的pod

#外部访问

复制代码
curl http://www.benet.com:30080

30443 30080是方式二Deployment+NodePort模式nginx-ingress-controller的deploy.yaml配置文件中规定的




Ingress HTTP 代理访问虚拟主机(根据不同 域名/目录 转发到不同主机)

复制代码
mkdir /opt/ingress-nodeport/vhost
cd /opt/ingress-nodeport/vhost

#创建虚拟主机1资源

bash 复制代码
vim deployment1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment1
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx1
  template:
    metadata:
      labels:
        name: nginx1
    spec:
      containers:
        - name: nginx1
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-1
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx1
复制代码
kubectl apply -f deployment1.yaml

#创建虚拟主机2资源

bash 复制代码
vim deployment2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment2
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx2
  template:
    metadata:
      labels:
        name: nginx2
    spec:
      containers:
        - name: nginx2
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-2
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx2
复制代码
kubectl apply -f deployment2.yaml

#创建ingress资源 根据不同域名转发到不同主机

bash 复制代码
vim ingress-nginx.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress1
spec:
  ingressClassName: "nginx"
  rules:
    - host: www1.xue.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service: 
              name: svc-1
              port:
                number: 80
---
apiVersion: networking.k8s.io/v1        #根据不同域名转发到不同主机
kind: Ingress
metadata:
  name: ingress2
spec:
  ingressClassName: "nginx"
  rules:
    - host: www2.xue.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service: 
              name: svc-2
              port:
                number: 80
复制代码
kubectl apply -f ingress-nginx.yaml

#测试访问

bash 复制代码
kubectl get svc -n ingress-nginx

NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.96.67.119   <none>        80:30080/TCP,443:30443/TCP   176m

30443 30080是方式二Deployment+NodePort模式nginx-ingress-controller的deploy.yaml配置文件中规定的

bash 复制代码
curl www1.xue.com:30080
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

curl www2.xue.com:30080
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

Ingress HTTPS 代理访问

复制代码
mkdir /opt/ingress-nodeport/https
cd /opt/ingress-nodeport/https

#创建ssl证书(本地使用,互联网中使用会无法验证ca报警)

复制代码
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"

#创建 secret 资源存储证书,稍后在ingress中引用

复制代码
kubectl create secret tls tls-secret --key tls.key --cert tls.crt

kubectl get secret

NAME                  TYPE                                  DATA   AGE
tls-secret            kubernetes.io/tls                     2      2m22s

kubectl describe secret tls-secret

Name:         tls-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1143 bytes
tls.key:  1704 bytes

#创建 deployment、Service、Ingress Yaml 资源

bash 复制代码
vim ingress-https.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress #由于https为七层,使用的证书等信息在Ingress中添加 
metadata:
  name: nginx-https
spec:
  ingressClassName: "nginx"
  tls: #指定使用tls
    - hosts: #什么站点使用https
      - www3.xue.com
      - www33.xue.com
      secretName: tls-secret #绑定刚刚创建的tls secret对象(存储证书等信息)
  rules:
    - host: www3.xue.com #由于上面tls.hosts写了www3.xue.com,所以本站需要用https访问
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service: 
              name: nginx-svc
              port:
                number: 80
    - host: www33.xue.com #域名2  也需要https访问。注意,同一配置文件不能http https混用。若要使用http,请再开个ingress配置文件。
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service: 
              name: nginx-svc33
              port:
                number: 80

注意。同一配置文件不能http https混用。若要使用http,请再单独编写http的ingress配置文件,与https的ingress配置文件分开(区别是指不值定tls字段)。

复制代码
kubectl apply -f ingress-https.yaml
bash 复制代码
kubectl get svc -n ingress-nginx

NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.96.67.119   <none>        80:30080/TCP,443:30443/TCP   3h41m

30443 30080是方式二Deployment+NodePort模式nginx-ingress-controller的deploy.yaml配置文件中规定的

#访问测试

在宿主机的 C:\Windows\System32\drivers\etc\hosts 文件中添加 192.168.80.101 www3.xue.com 记录。

使用谷歌浏览器访问 https://www3.xue.com:30443

Nginx 进行 BasicAuth(跳出密码框认证)

具体详细设置方法可参考官网https://kubernetes.github.io/ingress-nginx/examples/auth/basic/

复制代码
mkdir /opt/ingress-nodeport/basic-auth
cd /opt/ingress-nodeport/basic-auth

#生成用户密码认证文件,创建 secret 资源进行存储

bash 复制代码
yum -y install httpd
#或者更精确 yum -y install httpd-tools

htpasswd -c auth zhangsan #认证文件名必须为 auth
kubectl create secret generic basic-auth --from-file=auth #这里的secret名basic-auth在下面的ingress资源配置文件中引用

#创建 ingress 资源

bash 复制代码
vim ingress-auth.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-auth
  annotations:
    #设置认证类型basic
    nginx.ingress.kubernetes.io/auth-type: basic
    #设置secret资源名称basic-auth 
    nginx.ingress.kubernetes.io/auth-secret: basic-auth #与之前创建的secret名称相对应(basic-auth)
    #设置认证窗口提示信息
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - zhangsan'
spec:
  ingressClassName: "nginx"
  rules:
  - host: auth.xue.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: nginx-svc
            port:
              number: 80
复制代码
kubectl apply -f ingress-auth.yaml

#访问测试

bash 复制代码
kubectl get svc -n ingress-nginx

NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.96.67.119   <none>        80:30080/TCP,443:30443/TCP   8h
复制代码
echo '192.168.80.101 auth.xue.com' >> /etc/hosts

浏览器访问:http://auth.xue.com:30080

Nginx 进行重写

metadata.annotations 配置说明

●nginx.ingress.kubernetes.io/rewrite-target: <字符串> #必须重定向流量的目标URI

●nginx.ingress.kubernetes.io/ssl-redirect: <布尔值> #指示位置部分是否仅可访问SSL(当Ingress包含证书时,默认为true)

●nginx.ingress.kubernetes.io/force-ssl-redirect: <布尔值> #即使Ingress未启用TLS,也强制重定向到HTTPS

●nginx.ingress.kubernetes.io/app-root: <字符串> #定义Controller必须重定向的应用程序根,如果它在'/'上下文中

●nginx.ingress.kubernetes.io/use-regex: <布尔值> #指示Ingress上定义的路径是否使用正则表达式

bash 复制代码
vim ingress-rewrite.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-rewrite
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2 #位置变量。下面的path字段中有做匹配。组合效果类似于 将url中的/something/一级去除,转发到处理后的URL对应的ingress进行处理。
spec:
  ingressClassName: "nginx"
  rules:
  - host: re.xue.com
    http:
      paths:
      - path: /something(/|$)(.*) #匹配规则
#(/|$)为re.xue.com:30080/something后的分隔符,可为 / | $        (.*) 代表任意字符任意次
#并且每个 () 都代表一个位置变量。(.*)即为$2,也可以说$2代表了/something/后的任意字符。
        pathType: Prefix
        backend:
          service:  #此处的service由于在一条转发规则下,规则匹配到的直接转发,所以可以随便定义,并不会用到
            name: nginx-svc
            port:
              number: 80
bash 复制代码
上面是一条转发规则,而转发过的请求还是需要对应的ingress来处理。
可以继续定义一些普通的ingress 处理让转发来的请求 或是根据域名 或是根据路径 再转发到自己绑定的svc上 再转发给pod。
vim ingress-xxx.yaml

  - host:
    http:
      paths:
      - path:
复制代码
kubectl apply -f ingress-rewrite.yaml

echo '192.168.80.101 re.xue.com' >> /etc/hosts

浏览器访问

http://re.xue.com:30080,由于未匹配到/something不做转发

http://re.xue.com/something:30080http://re.xue.com/:30080

匹配到/something字段,进行转发,转发给 http://re.xue.com/:30080对应的ingress进行处理

http://re.xue.com/something/123/abc.txt:30080http://re.xue.com/123/abc.txt:30080

匹配到/something字段,进行转发,转发给http://re.xue.com/123/abc.txt:30080对应的ingress进行处理

注:30080为方式二Deployment+NodePort模式nginx-ingress-controller的deploy.yaml配置文件中规定的,根据nodeip+这个指定的端口访问容器。

总结

ingress是k8s集群的请求入口,可以理解为对多个service的再次抽象

通常说的ingress一般包括ingress资源对象及ingress-controller两部分组成

ingress-controller有多种实现,社区原生的是ingress-nginx,根据具体需求选择

ingress自身的暴露有多种方式,需要根据基础环境及业务类型选择合适的方式

相关推荐
云飞云共享云桌面1 天前
昆山精密机械公司8个Solidworks共用一台服务器
运维·服务器·网络·3d·自动化·制造
恒创科技HK1 天前
中国香港服务器中常提到的双向/全程CN2是什么意思?
运维·服务器
MyCollege19991 天前
win10使用ssh访问vmware虚拟机
linux·运维·centos
a栋栋栋1 天前
wsl 环境下用Docker 安装多版本MySQL
mysql·docker·容器
潮落拾贝1 天前
k8s部署kafka三节点集群
容器·kafka·kubernetes
大霞上仙1 天前
jmeter实现两个接口的同时并发
运维·服务器·jmeter
饱饱要坚持可持续发展观1 天前
docker 拉取本地镜像
docker
我就要用Cx3301 天前
配置docker常见问题
运维·docker·容器
nmxiaocui1 天前
openssl升级
linux·运维·服务器
最小的帆也能远航1 天前
2018年下半年 系统架构设计师 综合知识
linux·运维·服务器