51K8S-流量调度-IngressIngress-nginxDashboard

Posted 小粉优化大师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51K8S-流量调度-IngressIngress-nginxDashboard相关的知识,希望对你有一定的参考价值。

Kubernetes学习目录

1、Ingress基础

1.1、简介

在实际的应用中,kubenetes接受的不仅仅有内部的流量,还有外部流量,我们可以通过两种方式实现将集群外部的流量引入到集群的内部中来,从而实现外部客户的正常访问。
service方式:
   nodePort、externalIP 等service对象方式,借助于 namespace、iptables、ipvs 等代理模式实现流量的转发。
Host方式:
   通过node节点的 hostNetwork 与 hostPort 及配套的port映射,以间接的方式实现service的效果

1.2、k8s网络流程图

 

1.3、关于网络流向的问题

1、在实际的应用中,虽然我们可以基于service或host等多种方式实现集群内外的网络通信,但是这些
内容都是基于四层协议来进行调度的,而且服务级别的健康检查功能很难实现。

2、而对于外部流量的接入,一般都是http(s)协议的数据,四层协议是无法实现的。尤其是涉及到各种 ssl会话的管理,由于其位于osi七层模型的会话层,要高于传输层的四层,service和host是无法正常实现的。
3、虽然service能够实现将外部流量引入到集群内部,但是其本质上,是通过网络规则方式来进行转发 的,形象的说法就是在墙上打洞,将集群内部的服务暴露到外部。甚至这些洞和洞之间根本没有关联关系。

1.4、解决方案

 为了解决上述的问题,就引入了一种新的解决方法ingress,简单来说,它可以解决上面提出的三个问题:
 1、可以基于https的方式,将集群外部的流量统一的引入到集群内部
 2、通过一个统一的流量入口,避免将集群内部大量的""暴露给外部。
 Ingress这种利用应用层协议来进行流量的负载均衡效果,它可以实现让用户通过域名来访问相应的service就可以了,无需关心Node IP及Port是什么,避免了信息的泄露。

 

1.5、什么是Ingress

Ingress 是k8s上的一种标准化资源格式,它为了剥离与特定负载均衡功能实现软件的相关性,而抽象
出来的一种公共的统一的声明式配置格式。然后借助于特定的ingress controller功能负责将其加载并转换成k8s集群内部的配置信息。
Ingress的特点符合我们之前对于CRD的学习
- ingress + controller,所以,其具备了动态更新 并加载新配置的特性。而且ingress本身是不具备实现集群内外流量通信的功能的,这个功能是通过controller来实现的。

2、Ingress原理解析

2.1、Ingress组成

Ingress由任何具有反向代理功能的程序实现,如Nginx、Traefik、Envoy、HAProxy、Vulcand等,Ingress本身是运行于集群中的Pod资源对象。
ingress 主要包含两个组件Ingress Controller和Ingress。

2.2、Ingress组件

2.2.1、Ingress

将Nginx的配置抽象成一个Ingress对象,每个服务对应一个ingress的yaml配置文件

2.2.2、Ingress Controller

将新加入的Ingress转化成Nginx的配置文件并使之生效

2.3、问题梳理

如果我们将ingress以pod的方式部署到k8s集群内部,那么就会遇到多个问题:
 1、ingress的pod如何引入外部流量
   - 通过一个专用的service就可以实现了
2、ingress的pod如何把流量负载均衡到其他pod - 关于pod负载均衡的流量,直接通过controller转发给后端pod即可。
3、后端应用的pod很多,如何知道谁是我们要转发的目标? - 通过k8s的server对所有的pod进行分组管理,借助于controller内部的负载均衡配置,找到对应的目标。

2.4、Ingress原理解析

2.4.1、Ingress流程说明

Ingress是授权入站连接到达集群服务的规则集合。
从外部流量调度到nodeport上的service
从service调度到ingress-controller
ingress-controller根据ingress[Pod]中的定义(虚拟主机或者后端的url)
根据虚拟主机名直接调度到后端的一组应用pod中

2.4.2、Ingress流程图

注意:
 整个流程中涉及到了两处service内容service ingress-nginx 是帮ingress controller接入外部流量,虚线表示service对后端的应用进行分组,实现是ingress实际的访问流程

2.5、Ingress-常见的解决方案

对于ingress controller的软件实现,其实没有特殊的要求,只要能够实现七层的负载均衡功能效果即可,各种组织对于ingress的controller虽然实现方式不同,
但是功能基本上一样,常见的实现方式有:
Ingress-Nginx: Kong
HAProxy:性能相对于nginx来说,较稳定。
Envoy: 基于C++语言开发,本身就为动态环境设计的,支持配置动态加载的XDS API不能像ingress-nginx一样,直接加载配置文件并动态加载转换成对应的应用配置,所以需要借助于其他控制平面工具来实现。
常见解决方案:Contour, Gloo、Traefik

注意:ingress 自从 1.6版本引入后,在1.19 正式进入了一个稳定版本状态。

3、Ingress-Nginx

3.1、Ingress-属性解析

apiVersion: networking.k8s.io/v1   # 资源所属的API群组和版本
kind: Ingress                      # 资源类型标识符
metadata:                          # 元数据
  name <string>                    # 资源名称
  annotations:                     # 资源注解,v1beta1使用下面的注解来指定要解析该资源的控制器类型
    kubernetes.io/ingress.class: <string> # 适配的Ingress控制器类别,便于多ingress组件场景下,挑选针对的类型
  namespace <string>       # 名称空间
spec:
  rules <[]Object>         # Ingress规则列表,也就是http转发时候用到的url关键字
  - host <string>          # 虚拟主机的FQDN,支持“*”前缀通配,不支持IP,不支持指定端口
    http <Object>
      paths <[]Object>     # 虚拟主机PATH定义的列表,由path和backend组成
      - path <string>      # 流量匹配的HTTP PATH,必须以/开头
      pathType <string>    # 支持Exact、Prefix和ImplementationSpecific,必选
      backend <Object>     # 匹配到的流量转发到的目标后端
        resource <Object>     # 引用的同一名称空间下的资源,与下面两个字段互斥
        service <object>      # 关联的后端Service对象
          name <string>       # 后端Service的名称
          port <object>       # 后端Service上的端口对象
            name <string>     # 端口名称
            number <integer>  # 端口号
  tls <[]Object>              # TLS配置,用于指定上rules中定义的哪些host需要工作HTTPS模式
  - hosts <[]string>          # 使用同一组证书的主机名称列表
   secretName <string>        # 保存于数字证书和私钥信息的secret资源名称,用于主机认证
  backend <Object>            # 默认backend的定义,可嵌套字段及使用格式跟rules字段中的相同
  ingressClassName <string>   # ingress类名称,用于指定适配的控制器,类似于注解的功能

3.2、Ingress-nginx布署

3.2.1、官方参考文档

参考资料:https://github.com/kubernetes/ingress-nginx
安装文档:https://kubernetes.github.io/ingress-nginx/deploy/

3.2.2、下载软件

当前版本:ingress-nginx-controller-v1.7.0.tar.gz

地址:https://github.com/kubernetes/ingress-nginx/releases/tag/controller-v1.7.0

3.2.3、获取安装的yaml

# 获取安装的yaml文件
压缩文件位置:ingress-nginx-controller-v1.7.0.tar.gz\\ingress-nginx-controller-v1.7.0\\deploy\\static\\provider\\baremetal\\deploy.yaml

3.2.4、提前准备镜像

# 准备离线镜像,加快安装速度
master1 ingress-nginx]# grep \'image\' deploy.yaml | grep -iv \'pull\' | uniq
        image: registry.k8s.io/ingress-nginx/controller:v1.7.0@sha256:7612338342a1e7b8090bef78f2a04fffcadd548ccaabe8a47bf7758ff549a5f7
        image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f

# 如果有外网代理的话,可以使用docker代理下载
参考文章:https://www.cnblogs.com/ygbh/p/17295746.html

# 下载好的镜像上传至私有仓库
docker tag 0d4c0564c465 192.168.10.33:80/k8s/ingress-nginx/controller:v1.7.0
docker push 192.168.10.33:80/k8s/ingress-nginx/controller:v1.7.0

docker tag 5a86b03a88d2 192.168.10.33:80/k8s/ingress-nginx/kube-webhook-certgen:v1.7.0
docker push 192.168.10.33:80/k8s/ingress-nginx/kube-webhook-certgen:v1.7.0

3.2.5、修改deploy.yaml【修改下载镜像的地址】

sed -i \'s#registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f#192.168.10.33:80/k8s/ingress-nginx/kube-webhook-certgen:v1.7.0#\'g deploy.yaml
sed -i \'s#registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f#192.168.10.33:80/k8s/ingress-nginx/kube-webhook-certgen:v1.7.0#\'g deploy.yaml

master1 ~]# grep \'image\' ingress-nginx/deploy.yaml | grep -iv \'pull\' | uniq
        image: 192.168.10.33:80/k8s/ingress-nginx/controller:v1.7.0
        image: 192.168.10.33:80/k8s/ingress-nginx/kube-webhook-certgen:v1.7.0

3.2.6、修改deploy.yaml【增加一个外网访问的入口ip】

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.7.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - appProtocol: http
    name: http
    port: 80
    protocol: TCP
    targetPort: http
  - appProtocol: https
    name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: NodePort
  externalIPs: [\'192.168.10.222\']  # 增加此行,这个IP地址不是一个物理IP地址,虚拟IP来的

注意:如果需要被宿主机访问到的话,就要在主机上增加多一个虚拟网口,并且IP地址与externalIPs保持一致。创建方法如下:
ifconfig ens33:1 192.168.10.222 netmask 255.255.255.0

3.2.7、应用资源配置清单

master1 ~]# kubectl apply -f ingress-nginx/deploy.yaml 
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created

3.2.8、查看运行状态

# Pod
master1 ~]# kubectl -n ingress-nginx get pods
NAME                                       READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-zcm9b       0/1     Completed   0          7m39s
ingress-nginx-admission-patch-jtlj5        0/1     Completed   1          7m39s
ingress-nginx-controller-89c678f9f-j59ll   1/1     Running     0          7m39s

# SVC
master1 ~]# kubectl -n ingress-nginx get svc
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.111.40.152   192.168.10.222   80:30565/TCP,443:30073/TCP   8m47s
ingress-nginx-controller-admission   ClusterIP   10.97.213.211   <none>           443/TCP                      8m47s

# Job
master1 ~]# kubectl -n ingress-nginx get job
NAME                             COMPLETIONS   DURATION   AGE
ingress-nginx-admission-create   1/1           4s         8m51s
ingress-nginx-admission-patch    1/1           6s         8m51s

 3.2.9、测试访问svc

master1 ~]# curl 192.168.10.222
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

master1 ~]# curl -I -o /dev/null -s -w %http_code"\\n" 192.168.10.222
404

3.2.10、安装成功

目前为止已经安装成功

4、Ingress-nginx-入门实践

4.1、创建deployment、svc资源

4.1.1、定义资源配置清单且应用

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-test
spec:
  replicas: 4
  selector:
    matchLabels:
      app: pod-test
  template:
    metadata:
      labels:
        app: pod-test
    spec:
      containers:
      - name: pod-test
        image: 192.168.10.33:80/k8s/pod_test:v0.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: http
---
apiVersion: v1
kind: Service
metadata:
  name: deployment-service
spec:
  selector:
    app: pod-test
  ports:
    - name: http
      port: 80
      targetPort: 80
EOF

4.1.2、查询资源运行状态

master1 ~]# kubectl get pod
NAME                              READY   STATUS    RESTARTS   AGE
deployment-test-d6756dd79-7njmq   1/1     Running   0          61s
deployment-test-d6756dd79-ds84h   1/1     Running   0          61s
deployment-test-d6756dd79-f5k6j   1/1     Running   0          61s
deployment-test-d6756dd79-kmqv8   1/1     Running   0          61s

master1 ~]# kubectl get svc
NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
deployment-service   ClusterIP   10.99.121.115   <none>        80/TCP    63s
kubernetes           ClusterIP   10.96.0.1       <none>        443/TCP   4d14h

master1 ~]# kubectl get deployments.apps 
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
deployment-test   4/4     4            4           114s

4.2、创建ingress-nginx资源

4.2.1、定义资源配置清单且应用

kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: cyc.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: deployment-service
            port: 
              number: 80
EOF

属性解析:
1、annotations注释,ingress实现类为nginx
2、对于ingress来说,最终要的就是rules了,hosts是一个自定义的域名,backend指向svc name

4.2.2、查询资源运行状态

master1 ~]# kubectl get ingress
NAME           CLASS    HOSTS             ADDRESS         PORTS   AGE
ingress-test   <none>   cyc.example.com   192.168.10.29   80      63s

master1 ~]# kubectl describe ingress ingress-test 
Name:             ingress-test
Labels:           <none>
Namespace:        default
Address:          192.168.10.29
Ingress Class:    <none>
Default backend:  <default>
Rules:
  Host             Path  Backends
  ----             ----  --------
  cyc.example.com  
                   /   deployment-service:80 (10.244.3.81:80,10.244.3.82:80,10.244.4.114:80 + 1 more...)
Annotations:       kubernetes.io/ingress.class: nginx
Events:
  Type    Reason  Age                From                      Message
  ----    ------  ----               ----                      -------
  Normal  Sync    54s (x2 over 95s)  nginx-ingress-controller  Scheduled for sync
  

ingress将后端的deployment-service:80 的样式自动与 ingress 的 url(/) 关联在一起了

4.3、访问测试

4.3.1、配置hosts

echo \'192.168.10.222 cyc.example.com\' >> /etc/hosts

4.3.2、访问配置的域名

master1 ~]# curl cyc.example.com
kubernetes pod-test v0.1!! ClientIP: 10.244.3.80, ServerName: deployment-test-d6756dd79-f5k6j, ServerIP: 10.244.3.82!

master1 ~]# curl cyc.example.com
kubernetes pod-test v0.1!! ClientIP: 10.244.3.80, ServerName: deployment-test-d6756dd79-7njmq, ServerIP: 10.244.3.81!

master1 ~]# curl cyc.example.com
kubernetes pod-test v0.1!! ClientIP: 10.244.3.80, ServerName: deployment-test-d6756dd79-ds84h, ServerIP: 10.244.4.115!

master1 ~]# curl cyc.example.com
kubernetes pod-test v0.1!! ClientIP: 10.244.3.80, ServerName: deployment-test-d6756dd79-kmqv8, ServerIP: 10.244.4.114!

# 通过自定义携带域名的方式可以正常访问。

4.4.、原理解析

master1 ~]# kubectl -n ingress-nginx exec -it ingress-nginx-controller-89c678f9f-xlstd -- /bin/bash -c \'grep cyc nginx.conf\'
        ## start server cyc.example.com
                server_name cyc.example.com ;
        ## end server cyc.example.com
        
nginx配置文件,定义好域名信息作为信息的入口。

5、Ingress-nginx-多域名、多URL访问-实践

5.1、需求

nginx controller的功能远不止我们所说的主机域名的管理,在实际的工作需求中,肯定会遇到,不同的功能服务以子路径的方式来进行访问,以及与https相关的访问。

5.2、准备pod和svc资源

5.2.1、创建nginx pod和svc资源

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx-test
  template:
    metadata:
      labels:
        app: nginx-test
    spec:
      containers:
      - name: nginx-test
        image: 192.168.10.33:80/k8s/my_nginx:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx-test
  ports:
    - name: nginx
      port: 80
      targetPort: 80
EOF

注意:这里面有两个主机访问的地址是同一个后端端口,如果还用number的话,就无法正常的识别导致同一个地址访问不同的后端效果。

5.2.2、创建flask pod和svc资源

上一小节已经创建过的,可以忽略。
如果没有创建请看小节:4.1.1、定义资源配置清单且应用

5.2.3、查询资源创建情况

master1 ~]# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-5c4b6689f6-6dfkn   1/1     Running   0          105s
deployment-nginx-5c4b6689f6-74k2w   1/1     Running   0          105s
deployment-nginx-5c4b6689f6-jmzjw   1/1     Running   0          105s
deployment-nginx-5c4b6689f6-rprfp   1/1     Running   0          105s
deployment-test-d6756dd79-7njmq     1/1     Running   0          40m
deployment-test-d6756dd79-ds84h     1/1     Running   0          40m
deployment-test-d6756dd79-f5k6j     1/1     Running   0          40m
deployment-test-d6756dd79-kmqv8     1/1     Running   0          40m

5.2、不同主机域名访问-实践

5.2.1、需求

访问 flask.example.com/的时候,返回flask的结果
访问 nginx.example.com/的时候,返回nginx的结果

5.2.2、创建ingress-nginx资源

kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-mul-url
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: flask.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: deployment-service
            port:
              name: http
              #number: 80
  - host: nginx.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              name: nginx
EOF

配置解析:
 这里面有两个主机访问的地址是同一个后端端口,如果还用number的话,就无法正常的识别导致同一个
 地址访问不同的后端效果

5.2.3、查询资源运行状态

master1 ~]# kubectl get ingress
NAME              CLASS    HOSTS                                 ADDRESS         PORTS   AGE
ingress-mul-url   <none>   flask.example.com,nginx.example.com                   80      4s
ingress-test      <none>   cyc.example.com                       192.168.10.29   80      35m

master1 ~]# kubectl describe ingress ingress-mul-url 
Name:             ingress-mul-url
Labels:           <none>
Namespace:        default
Address:          192.168.10.29
Ingress Class:    <none>
Default backend:  <default>
Rules:
  Host               Path  Backends
  ----               ----  --------
  flask.example.com  
                     /   deployment-service:http (10.244.3.81:80,10.244.3.82:80,10.244.4.114:80 + 1 more...)
  nginx.example.com  
                     /   nginx-service:nginx (10.244.3.83:80,10.244.3.84:80,10.244.4.116:80 + 1 more...)
Annotations:         kubernetes.io/ingress.class: nginx
Events:
  Type    Reason  Age                   From                      Message
  ----    ------  ----                  ----                      -------
  Normal  Sync    117s (x2 over 2m37s)  nginx-ingress-controller  Scheduled for sync

5.2.4、配置hosts

echo \'192.168.10.222 flask.example.com nginx.example.com\' >> /etc/hosts

5.2.5、访问测试

master1 ~]# curl nginx.example.com
nginx v1版本
master1
~]# curl flask.example.com kubernetes pod-test v0.1!! ClientIP: 10.244.3.80, ServerName: deployment-test-d6756dd79-f5k6j, ServerIP: 10.244.3.82!

5.3、单域名多URL访问-实践

5.3.1、需求

访问 www.example.com/flask的时候,返回flask的结果
访问 www.example.com/nginx的时候,返回nginx的结果
注意事项:
 由于这里涉及到了域名的url转发,而后端服务有可能不存在,我们需要在后端url转发的时候,取消转发关键字。
 解决方法:在annotation中添加一个重写的规则nginx.ingress.kubernetes.io/rewrite-target: /(即所有的请求,把ingress匹配到的url关键字清除掉)

5.3.2、创建ingress-nginx资源

kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-mul-url
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: www.example.com
    http:
      paths:
      - path: /flask
        pathType: Prefix
        backend:
          service:
            name: deployment-service
            port:
              name: http
              #number: 80
      - path: /nginx
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              name: nginx
              #number: 80
EOF

5.3.3、查询资源运行状态

master1 ~]# kubectl get ingress
NAME              CLASS    HOSTS             ADDRESS         PORTS   AGE
ingress-mul-url   <none>   www.example.com   192.168.10.29   80      9m27s
ingress-test      <none>   cyc.example.com   192.168.10.29   80      44m

master1 ~]# kubectl describe ingress ingress-mul-url 
Name:             ingress-mul-url
Labels:           <none>
Namespace:        default
Address:          192.168.10.29
Ingress Class:    <none>
Default backend:  <default>
Rules:
  Host             Path  Backends
  ----             ----  --------
  www.example.com  
                   /flask   deployment-service:http (10.244.3.81:80,10.244.3.82:80,10.244.4.114:80 + 1 more...)
                   /nginx   nginx-service:nginx (10.244.3.83:80,10.244.3.84:80,10.244.4.116:80 + 1 more...)
Annotations:       kubernetes.io/ingress.class: nginx
                   nginx.ingress.kubernetes.io/rewrite-target: /
Events:
  Type    Reason  Age                  From                      Message
  ----    ------  ----                 ----                      -------
  Normal  Sync    20s (x3 over 9m44s)  nginx-ingress-controller  Scheduled for sync
  

5.3.4、配置hosts

echo "192.168.10.222 www.example.com" >>/etc/hosts

5.3.5、访问测试

master1 ~]# curl www.example.com/nginx
nginx v1版本
master1
~]# curl www.example.com/flask kubernetes pod-test v0.1!! ClientIP: 10.244.3.80, ServerName: deployment-test-d6756dd79-f5k6j, ServerIP: 10.244.3.82!

6、Ingress-nginx-https-实践

6.1、需求

我们准备对基础的flask应用进行https方式来进行访问。
方法:Ingress的tls规则就可以帮助我们实现对http应用进行https升级

6.2、准备CA证书

6.2.1、创建CA证书

mkdir tls && cd tls
(umask 077;openssl genrsa -out tls.key 2048)
openssl req -new -x509 -key tls.key -out tls.crt -subj \'/CN=www.example.com\' -days 10000

6.2.2、将证书导入secret配置资源

kubectl create secret tls ingress-tls --cert=./tls.crt  --key=./tls.key 

[root@master1 tls]# kubectl get secrets 
NAME          TYPE                DATA   AGE
ingress-tls   kubernetes.io/tls   2      11s

6.3、创建ingress-nginx资源

6.3.1、定义资源配置清单并且应用

kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: www.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: deployment-service
            port:
              number: 80
  tls:
  - hosts:
    - www.example.com
    secretName: ingress-tls
EOF

6.3.2、查询资源运行状态

master1 ~]# kubectl get ingress
NAME           CLASS    HOSTS             ADDRESS         PORTS     AGE
ingress-test   <none>   www.example.com   192.168.10.29   80, 443   60m

6.3.3、配置hosts

echo "192.168.10.222 www.example.com" >>/etc/hosts

# 如果配置过,就忽略

6.3.4、访问测试

master1 ~]# curl -k https://www.example.com
kubernetes pod-test v0.1!! ClientIP: 10.244.3.80, ServerName: deployment-test-d6756dd79-kmqv8, ServerIP: 10.244.4.114!

master1 ~]# curl www.example.com
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx</center>
</body>
</html>

7、Dashboard、Ingress-nginx-实践

7.1、需求

7.1.1、问题点

我们知道,对于k8s的dashboard来说,它所实现的功能还是比较多的,而且原则上要求必须是https方式来
进行访问。我们之前是通过service的方式实现正常的请求访问。有了ingress,我们也可以自由的访问
dashboard了。比如我们访问k8s的dashboard的首页地址是
https://10.0.0.12:30443/#/login

7.1.2、解决dashboard的方法

除了我们之前所说的动态url的方式之外,就需要tls认证了。关于对集群内部的ingress的tls访问方式,可以借助于ingress controller的annotation的方式向nginx中传递一些属性,从而上nginx支持相应的功能。

这与我们上一节的方式有所不同通过两个annotation中的规则
ingress.kubernetes.io/ssl-passthrough: "true"
- 以为后面的dashboard本身就做了tls功能,所以这里进行tls代理即可

nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- 对后端直接启动https协议访问即可。

参考资料:https://kubernetes.github.io/ingress-nginx/user-guide/nginxconfiguration/annotations/

7.2、创建Ingress资源

7.2.1、定义资源配置清单且应用

echo \'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-dashboard
  namespace: kubernetes-dashboard
  annotations:
    ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: dashboard.example.com
    http:
      paths:
      - path: /dashboard(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard
            port: 
              number: 443
\' | kubectl apply -f - 

7.2.2、查询资源运行状态

master1 ~]# kubectl get  ingress -n kubernetes-dashboard
NAME                CLASS   HOSTS                   ADDRESS         PORTS   AGE
ingress-dashboard   nginx   dashboard.example.com   192.168.10.29   80      41m

master1 ~]# kubectl get ingress -n kubernetes-dashboard 
[root@master1 ~]# kubectl describe ingress -n kubernetes-dashboard ingress-dashboard 
Name:             ingress-dashboard
Labels:           <none>
Namespace:        kubernetes-dashboard
Address:          192.168.10.29
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host                   Path  Backends
  ----                   ----  --------
  dashboard.example.com  
                         /dashboard(/|$)(.*)   kubernetes-dashboard:443 (10.244.4.118:8443)
Annotations:             ingress.kubernetes.io/ssl-passthrough: true
                         nginx.ingress.kubernetes.io/backend-protocol: HTTPS
                         nginx.ingress.kubernetes.io/rewrite-target: /$2
                         nginx.ingress.kubernetes.io/use-regex: true
Events:
  Type    Reason  Age                 From                      Message
  ----    ------  ----                ----                      -------
  Normal  Sync    43s (x17 over 41m)  nginx-ingress-controller  Scheduled for sync

7.2.3、配置hosts

192.168.10.222 dashboard.example.com
# 这里的IP地址,是我们配置externalIP地址

7.2.4、访问测试

https://dashboard.example.com/dashboard/#/login

 

流量调度微服务可寻址性和注册中心

前言

现代计算机基于计算、存储和调度的体系, 于是现代架构都是围绕这三大话题不断演进。

在基础架构部, 也是主要为了解决这三个难题,为业务事业部提供透明的、高可用、可快速伸缩的 三大能力, 我们组主要负责 [流量调度] 这个话题,下面是一些宏观的技术笔记。



在单体结构, 流量调度是直观且无感的(DNS+Nginx就可以完成一次流量调度)。
演进到 微服务结构(服务粒度变得更细、服务伸缩更灵活(上下线更加频繁),团队松耦合),流量调度并没有消失,而是变得更加复杂。

关键名词解释

1. 控制平面/数据平面

控制平面: 内含路由表、负责路由控制, 引导流量的走向,注重“引导”, 属于旁路业务(核心)。  

数据平面:根据控制平面的路由逻辑,业务流量的实际走向。

控制面很多属于[核心]旁路业务:要求一致性=> raft协议。

2. 东西/南北流量

南北流量: 业务客户端--->服务器;
东西流量: 数据中心内或者数据中心之间的服务间调用;

东西/南北流量都属于数据平面流量。



服务治理的演进

服务治理的基石是动态服务发现, 阿里云服务治理的演进 大而全,这里只记录我的理解。

阶段 目标 手段
孵化期 动态服务发现 客户端/服务端服务发现,负载均衡
成长期 提高开发和迭代效率 规范API、 统一配置、 版本管理
成熟期 部署边界、链路追踪,弹性伸缩 服务预热、优雅下线、监控追踪、限流,熔断, 回退

核心的技能点

1. 为什么需要注册中心?

并不是微服务催生了 注册中心,而是微服务强化了注册中心。

早期DNS+nginx 就能完成单体的 流量调度,但是不管是DNS解析出ip, 还是nginx解析出upstream ,底层都有注册中心的影子。

这里面有一个addressability的概念,也即服务可寻址性, 服务必须有一个唯一的可寻址的名字,这个名字不依赖于部署环境,表征一组可以处理流量的实例资源。

对于资源,必定存在CRUD交互,这便是部署平台和服务发现,与此同时当实例出现故障时,注册中心必须能够指示服务现在在何处运行。

很多时候除了在部署层面,存在健康探测告知业务方目前的应用就绪情况; 实际在接流的时候,负载层还会有自己的主动健康检查探测。

2. 规范API接口, 统一配置

提高开发迭代效率,统一使用一种method、body payload形式的API接口(规避错误格式的传参导致的撕逼)、不用上n台实例修改配置。

各个团队是松耦合的关系,上下游的变更并不会主动通知,故需要版本管理(低版本不能直接下线)、提供给开发团队的版本调试接口。

3. 服务发现

服务发现是服务治理的基石,三板斧: 注册、心跳、寻址。

  • 部署系统做[注册]动作。
  • 微服务客户端寻址
  • 主动上报心跳/注册中心主动探活: 维护实例资源状态。

存在两种模式: 客户端服务发现、服务器服务发现, 核心区别在于 : 客户端是否保存服务列表信息。

4. 负载均衡

  • 随机
  • 轮询
  • 带权轮询
  • 根据后端实例服务质量动态调度

最近思考了一个问题,负载均衡不仅是拿到服务的可用实例列表,然后做流量均分; 其实负载均衡的存在也为我们无损切流提供了契机。

5. 飞机起飞和降落最容易出事故

  • 服务预热: 服务进程启动,等待业务配置/缓存就绪,再向注册中心通报实例资源就绪,可以接流。
  • 优雅下线: 下线时设置服务终止时间(30s),处理在途流量, 不再接收新的请求流量。

6. 限流 熔断

链路上部分服务的状态会影响整个链路(雪崩), 故需要保障微服务链路的高可用 => 服务的熔断、限流

熔断: 熔断掉对于下游的调用; 限流: 限制进入本应用的流量。

不管是客户端服务发现,还是服务器服务发现,都存在注册中心,也可以叫名字服务,是流量调度的基石,统一了流量调度的入口。




现代互联网结构,流量在打到应用之前,都会以对应的姿势接入某种负载层。

大多数时候,流量其实不care某个特定的应用实例,更在意的是服务的可用性;

服务端服务发现,在客户端和接流应用之间形成了一个负载层,除了负载均衡外,还提供了故障转移和无损扩缩容、无损切流的契机,这些都涉及动态上下线实例, 不同负载层有不同的接流姿势。

基于nginx7层负载的动态服务发现

我们着重聊一聊基于nginx主机名字的动态服务发现(服务端服务发现)。

nginx做反向代理,负载均衡的时候,我们关注nginx [http配置节]的上下文[server配置节][upstream配置节]。

上面这个配置,nginx会匹配请求的Host头server_name指令,决定该请求转发给哪一个upstream虚拟主机。

相关知识,请关注Host请求头在虚拟主机服务多网域服务中的关键作用

利用nginx的第三方组件nginx_http_dyups_module,可以做到动态修改upstream的配置。

This module can be used to update your upstream-list without reloadding Nginx.

daemon off;
error_log logs/error.log debug;

events 


http 
    upstream test_upstream 
         server 127.0.0.1:8088;
         server 127.0.0.1:8089;
     

    server 
        listen   80;

        location / 
            # The upstream here must be a nginx variable
             set $up test_upstream ;
             proxy_pass http://$up;
        
    

    server 
        listen 8088;
        location / 
            return 200 "8088";
        
    

    server 
        listen 8089;
        location / 
            return 200 "8089";
        
    

    server 
        listen  8090;
        location / 
           return 200  "8090" ;
       
    

    server 
        listen 8081;
        location / 
            dyups_interface;
        
    



1. 该组件默认不被编译进tengine(淘宝开源的具备强特性的nginx分发版),请使用--with-http_dyups_module配置参数启用。

./configure --add-module=./modules/ngx_http_upstream_dyups_module              // 配置成静态组件
 make             // 编译
 make install     // 安装

2. 需要添加dyups_interface指令激活[动态修改upstream配置]能力

3. 演示利用dyups api在不重启nginx的情况下修改upstream配置。

查询upstream和server:localhost:8081/detail

test_upstream
server 127.0.0.1:8088 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0
server 127.0.0.1:8089 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0

// 实际请求`curl 127.0.0.1`,轮询返回8088或者8089

更新upstream配置:
curl -d "server 127.0.0.1:8090;" 127.0.0.1:8081/upstream/test_upstream

// 再次调用`localhost:8081/detail`
test_upstream
server 127.0.0.1:8090 weight=1 max_conns=0 max_fails=1 fail_timeout=10 backup=0 down=0
// 实际请求`curl 127.0.0.1`,轮询返回8090

以上是对于流量调度这个大的topic的理解,限于篇幅,战术性动作没有展开,路漫漫其修远兮,文辞拙劣,如果错误或者不同见解,欢迎留言探讨。

以上是关于51K8S-流量调度-IngressIngress-nginxDashboard的主要内容,如果未能解决你的问题,请参考以下文章

k8s学习-Ingress

k8s学习-Ingress

Kubernetes(k8s)亲和性调度

k8s 让master主节点也参与调度

k8s 指定调度节点

[k8s]k8s的控制层kubelet+docker配合调度机制(k8架构)