什么是Ingress

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP/HTTPS

该特性从1.19版本开始作为stable状态进行发布

Ingress 公开从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。

如下图将所有流量都发送到同一 Service 的简单 Ingress 示例:
Ingress示意图

Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort或 Service.Type=LoadBalancer类型的 Service或者直接共享主机网络。

Ingress控制器

为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。Ingress 控制器 通常负责通过负载均衡器来实现 Ingress,与作为 kube-controller-manager 可执行文件的一部分运行的其他类型的控制器不同, Ingress 控制器不是随集群自动启动的。Kubernetes官方目前支持和维护 AWSGCENginx Ingress 控制器。

应用场景

金丝雀发布:是一种基于流量比例的发布策略,部署一个或者一小批新版本的服务,将少量(比如1%)的请求引流到新版本,逐步调大流量比重,直到所有用户流量都被切换新版本为止。由于这种模式不是非黑即白,所以又称为灰度发布。

那么这里就有一个问题,就是如何把生产流量进行一个转发?

通常呢,开发者会在接口请求的流量上做一个标记,如某些主机接收到应用流量后,对Header进行一个新增标记,来说明这个流量是用于新版本处理的。当这个流量进入k8s集群时,那么会被ingress定义的规则进行处理,将流量转发到新版本的业务的service,再由service转发到pod上面去。

金丝雀(灰度)发布实践

环境准备
nginx-controller安装
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml

启用deployment中的ingress-nginx-controller的容器为共享主机网络,即设置hostNetwork为true

deployments.spec.template.spec.hostNetwork 

查看nginx-controller所在的主机

$ kubectl get pod -n ingress-nginx -o wide
NAME                                        READY   STATUS      RESTARTS   AGE     IP              NODE               NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-s4wn5        0/1     Completed   0          3d14h   10.244.1.104    k8s-node1-ubantu   <none>           <none>
ingress-nginx-admission-patch-v5vh6         0/1     Completed   1          3d14h   10.244.1.105    k8s-node1-ubantu   <none>           <none>
ingress-nginx-controller-54cdc69c44-5tr2m   1/1     Running     0          2d14h   192.168.31.42   k8s-node2-ubantu   <none>           <none>
创建测试工作空间

为了方便演示和测试,避免干扰其他命名空间的资源,我们创建一个ingress-test的命名空间来进行测试,并且切换kubectl config的默认操作命名空间

kubectl create ns ingress-test
kubectl config set-context --current --namespace=ingress-test
实践步骤
  1. 创建两个应用,模拟新老应用版本

    kubectl create deployment old-app --image=nginx:1.19.0
    kubectl create deployment new-app --image=nginx
    

    通过pod network来验证两个app的访问

    kubectl get pods -o wide
    
    NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE               NOMINATED NODE   READINESS GATES
    new-app-69d99d595-vq7lf    1/1     Running   0          54s   10.244.2.72   k8s-node2-ubantu   <none>           <none>
    old-app-788c89d6c7-q2qnp   1/1     Running   0          61s   10.244.2.71   k8s-node2-ubantu   <none>           <none>
    $ curl 10.244.2.71/version
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.19.0</center>
    </body>
    </html>
    $ curl 10.244.2.72/version
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.23.3</center>
    </body>
    </html>
    

    可以看到两个新老应用的nginx版本是不一致的,新版本为1.23.3,而老的版本为1.19.0

  2. 创建两个service,来访问新老应用

    kubectl expose deployment old-app --port=80 --target-port=80
    kubectl expose deployment new-app --port=80 --target-port=80
    

    通过service网路来验证两个app的访问

    kubectl get svc -o wide
    
    $ kubectl get svc -o wide
    NAME      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE   SELECTOR
    new-app   ClusterIP   10.99.150.77   <none>        80/TCP    70s   app=new-app
    old-app   ClusterIP   10.96.98.15    <none>        80/TCP    79s   app=old-app
    $ curl 10.96.98.15/version
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.19.0</center>
    </body>
    </html>
    $ curl 10.99.150.77/version
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.23.3</center>
    </body>
    </html>
    
  3. 创建ingress,设定流量转发规则

    kubectl create ingress old-app --rule=k8s-node2-ubantu/*=old-app:80 --class=nginx
    kubectl create ingress new-app --rule=k8s-node2-ubantu/*=new-app:80 --annotation=nginx.ingress.kubernetes.io/canary="true" --annotation=nginx.ingress.kubernetes.io/canary-by-header="app" --annotation=nginx.ingress.kubernetes.io/canary-by-header-value="new" --class=nginx
    
  4. 验证访问

    正常流量访问

    $ curl  http://k8s-node2-ubantu/version
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.19.0</center>
    </body>
    </html>
    

    新版本流量访问,即在http请求头加入app=new,那么这部分的流量就会到new-app的应用上进行处理

    $ curl -H 'app:new'  http://k8s-node2-ubantu/version
    <html>
    <head><title>404 Not Found</title></head>
    <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.23.3</center>
    </body>
    </html>
    
    nginx-controller原理

    nginx-controller通过监听k8s集群ingress对象的创建/修改情况,同步更新内部的nginx的配置文件,来达到负载均衡/虚拟主机的能力,我们可以通过查看ingress-nginx-controller的容器日志来诊断流量分发的相关问题

    kubectl logs -n ingress-nginx ingress-nginx-controller-54cdc69c44-5tr2m
    

    日志示例

    I0115 04:06:37.459568       6 admission.go:149] processed ingress via admission controller {testedIngressLength:4 testedIngressTime:0.023s renderingIngressLength:4 renderingIngressTime:0s admissionTime:40.9kBs testedConfigurationSize:0.023}
    I0115 04:06:37.459591       6 main.go:100] "successfully validated configuration, accepting" ingress="ingress-test/old-app"
    I0115 04:06:37.462976       6 store.go:430] "Found valid IngressClass" ingress="ingress-test/old-app" ingressclass="nginx"
    I0115 04:06:37.463137       6 event.go:285] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"ingress-test", Name:"old-app", UID:"1a3a9c15-a7a9-4914-b4ac-d0821486df11", APIVersion:"networking.k8s.io/v1", ResourceVersion:"1935618", FieldPath:""}): type: 'Normal' reason: 'Sync' Scheduled for sync
    I0115 04:06:37.463244       6 controller.go:168] "Configuration changes detected, backend reload required"
    I0115 04:06:37.512904       6 controller.go:185] "Backend successfully reloaded"
    

    查看nginx-controller的nginx配置文件

    kubectl exec  -n ingress-nginx ingress-nginx-controller-54cdc69c44-5tr2m -- cat nginx.conf
    
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐