k8s ingress概念和实践

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

什么是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
    
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: k8s