Capítulo práctico Service Mesh-Istio (Parte 1)

Proceso de preparación y construcción de proyectos

Proceso típico de CI / CD-DevOps

Capítulo práctico Service Mesh-Istio (Parte 1)

Proceso de entrega continua de GitOps

  • GitOps: un método de entrega continua para la administración de clústeres y la distribución de aplicaciones
  • GitOps es diferente de un CI / CD típico. La mayor diferencia radica en el uso de Git como fuente de confianza y preservación de la infraestructura declarativa y las aplicaciones.
  • Con Git como el centro del proceso de entrega (canalización), los archivos de configuración como los archivos yaml de k8s se almacenan en git para su administración
  • Los desarrolladores solo necesitan completar la implementación de la aplicación y las tareas de operación y mantenimiento a través de una solicitud de extracción, y no necesitan usar otras herramientas de CI / CD
  • Ventajas: mayor productividad, experiencia de desarrollo mejorada, consistencia y estandarización, seguridad
    Capítulo práctico Service Mesh-Istio (Parte 1)

Proceso push vs pull (canalización):
Capítulo práctico Service Mesh-Istio (Parte 1)

Cree y publique aplicaciones con Flux

Definición oficial de Flux :

  • El operador de GitOps para Kubernetes
  • Herramienta de implementación automatizada (basada en GitOps)
  • característica:
    • Sincronización automática, implementación automática
    • Declarativo
    • Basado en código (solicitud de extracción), no contenedor
      Capítulo práctico Service Mesh-Istio (Parte 1)

Listo para trabajar

Primero, necesitamos preparar un clúster de Kubernetes:

E instale el entorno de Istio en k8s:

Como se muestra en la figura siguiente, queremos implementar una malla que consta de dos servicios, además de una puerta de enlace y un servicio externo, que se puede decir que está optimizado y completo:
Capítulo práctico Service Mesh-Istio (Parte 1)

  • Se puede ver en el enlace de llamada que dormir es el rol del cliente y httpbin es el rol del servidor.

Prepara un repositorio de Git:
Capítulo práctico Service Mesh-Istio (Parte 1)

Instalar Flux

Documentos oficiales:

Primero, instale la fluxctlherramienta de comando en el repositorio de Github en el archivo ejecutable de descarga. Luego colóquelo en /usr/binel directorio y otorgue permisos ejecutables:

[root@m1 /usr/local/src]# mv fluxctl_linux_amd64 /usr/bin/fluxctl
[root@m1 ~]# chmod a+x /usr/bin/fluxctl 
[root@m1 ~]# fluxctl version
1.21.0
[root@m1 ~]# 

Cree un espacio de nombres para Flux y luego implemente Flux Operator en el clúster k8s:

[root@m1 ~]# kubectl create ns flux
namespace/flux created
[root@m1 ~]# git clone https://github.com/fluxcd/flux.git
[root@m1 ~]# cd flux/

Antes de implementar Flux, debe modificar varias configuraciones relacionadas con Git en el nombre de usuario, correo electrónico, URL, etc. de su almacén de Git:

[root@m1 ~/flux]# vim deploy/flux-deployment.yaml  # 修改如下几个配置项
...
        # Replace the following URL to change the Git repository used by Flux.
        # HTTP basic auth credentials can be supplied using environment variables:
        # https://$(GIT_AUTHUSER):$(GIT_AUTHKEY)@github.com/user/repository.git
        - [email protected]:fluxcd/flux-get-started
        - --git-branch=master
        # Include this if you want to restrict the manifests considered by flux
        # to those under the following relative paths in the git repository
        # - --git-path=subdir1,subdir2
        - --git-label=flux-sync
        - --git-user=Flux automation
        - [email protected]

Una vez completada la modificación, implemente:

[root@m1 ~/flux]# kubectl apply -f deploy
[root@m1 ~/flux]# kubectl get all -n flux
NAME                            READY   STATUS    RESTARTS   AGE
pod/flux-65479fb87-k5zxb        1/1     Running   0          7m20s
pod/memcached-c86cd995d-5gl5p   1/1     Running   0          44m

NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
service/memcached   ClusterIP   10.106.229.44   <none>        11211/TCP   44m

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/flux        1/1     1            1           44m
deployment.apps/memcached   1/1     1            1           44m

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/flux-65479fb87        1         1         1       7m20s
replicaset.apps/memcached-c86cd995d   1         1         1       44m
[root@m1 ~]# 

Además de los métodos anteriores, también puede usar la línea de comando para implementar Flux:

fluxctl install \
--git-user=xxx \
--git-email=xxx@xxx \
[email protected]:xxx/smdemo \
--namespace=flux | kubectl apply -f -

Para el uso del almacén privado, necesitamos que se agregue algún trabajo adicional al ~/.ssh/known_hostsarchivo contenedor de claves del host del demonio Flux . Los pasos específicos son los siguientes:

[root@m1 ~]# kubectl exec -n flux flux-65479fb87-k5zxb -ti -- \
    env GITHOST="gitee.com" GITREPO="[email protected]:demo_focus/service-mesh-demo.git" PS1="container$ " /bin/sh
container$ ssh-keyscan $GITHOST >> ~/.ssh/known_hosts   # 添加host key
container$ git clone $GITREPO   # 测试确保能正常对仓库进行克隆
Cloning into 'service-mesh-demo'...
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 10 (delta 2), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (10/10), done.
Resolving deltas: 100% (2/2), done.
container$ 

Después de completar la implementación de Flux, debemos agregar la clave de implementación generada por Flux al repositorio de git (permiso de lectura / escritura) .El comando para obtener la clave de implementación es el siguiente:

[root@m1 ~]# fluxctl identity --k8s-fwd-ns flux
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDsyfN+x4jen+Ikpff8LszXLFTwXSQviFxCrIx7uMy7LJM5uUEsDdFs/DZL1g9h/YnkfLJlFrxOCJ+tuqPrXuj3ceEFfal4T3YWiDwf1RsGJvJd6ED5APjsxyu5gkj9LvkOB8OlYwPlS8Pygv997n93gtH7rFbocK5EQpbhhBlue3Or2ufI/KBxDCx6xLaH9U/16EEi+BDVSsCetGIQI+TSRqqpN30+Y8paS6iCYajKTubKv7x44WaVFgSDT9Y/OycUq1LupJoVoD8/5Y2leUMaF9dhMbQgoc8zjh8q2HF2n97mAvgYWJosjeIcAKS82C0zPlPupPevNedAhhEb82svPWh7BI4N4XziA06ypAEmfEz3JuUTTeABpF2hEoV4UEagkSyS8T3xhfdjigVcKiBW5AqRsRyx+ffW4WREHjARSC8CKl0Oj00a9FOGoNsDKkFuTbJePMcGdgvjs61UlgUUjdQFfHoZz2UVo2OEynnCpY7hj5SrEudkujRon4HEhJE= root@flux-7f5f7776df-l65lx
[root@m1 ~]# 

Copie el contenido clave y agréguelo al repositorio de Git:
Capítulo práctico Service Mesh-Istio (Parte 1)

Implementar la aplicación

Aplicaciones creadas como un espacio de nombres separado, y para agregar istio-injection=enabledetiquetas, para que el agente pueda inyectarse Istio:

[root@m1 ~]# kubectl create ns demo
namespace/demo created
[root@m1 ~]# kubectl label namespace demo istio-injection=enabled
namespace/demo labeled
[root@m1 ~]# 

El repositorio local de Git para clonar, creado en el configdirectorio del repositorio :

[root@m1 ~]# git clone [email protected]:demo_focus/service-mesh-demo.git
[root@m1 ~]# cd service-mesh-demo/
[root@m1 ~/service-mesh-demo]# mkdir config

Cree el archivo de configuración del servicio en este directorio:

[root@m1 ~/service-mesh-demo]# vim config/httpbin.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
  namespace: demo
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: demo
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  namespace: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80

[root@m1 ~/service-mesh-demo]# vim config/sleep.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sleep
  namespace: demo
---
apiVersion: v1
kind: Service
metadata:
  name: sleep
  namespace: demo
  labels:
    app: sleep
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleep
  namespace: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sleep
  template:
    metadata:
      labels:
        app: sleep
    spec:
      serviceAccountName: sleep
      containers:
      - name: sleep
        image: governmentpaas/curl-ssl
        command: ["/bin/sleep", "3650d"]
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /etc/sleep/tls
          name: secret-volume
      volumes:
      - name: secret-volume
        secret:
          secretName: sleep-secret
          optional: true

Envíe el archivo de configuración al almacén remoto y actualice el repositorio de git:

[root@m1 ~/service-mesh-demo]# git add .
[root@m1 ~/service-mesh-demo]# git commit -m "commit yaml"
[root@m1 ~/service-mesh-demo]# git push origin master

Ejecute el siguiente comando para permitir que Flux sincronice los cambios en el almacén y realice la implementación automática:

[root@m1 ~]# fluxctl sync --k8s-fwd-ns flux
Synchronizing with ssh://[email protected]/demo_focus/service-mesh-demo
Revision of master to apply is 49bc37e
Waiting for 49bc37e to be applied ...
Done.
[root@m1 ~]# 
  • De forma predeterminada, Flux se sincronizará automáticamente cada 5 minutos y no requiere que lo operemos manualmente.

Verifique los recursos en el espacio de nombres de demostración en este momento, puede ver que Flux implementó automáticamente todos los servicios para nosotros:

[root@m1 ~]# kubectl get all -n demo
NAME                           READY   STATUS    RESTARTS   AGE
pod/httpbin-74fb669cc6-v9lc5   2/2     Running   0          36s
pod/sleep-854565cb79-mcmnb     2/2     Running   0          40s

NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/httpbin   ClusterIP   10.105.17.57    <none>        8000/TCP   36s
service/sleep     ClusterIP   10.103.14.114   <none>        80/TCP     40s

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/httpbin   1/1     1            1           36s
deployment.apps/sleep     1/1     1            1           40s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/httpbin-74fb669cc6   1         1         1       36s
replicaset.apps/sleep-854565cb79     1         1         1       40s
[root@m1 ~]# 

Pruebe si la conectividad entre servicios es normal:

[root@m1 ~]# kubectl exec -it -n demo sleep-854565cb79-mcmnb -c sleep -- curl http://httpbin.demo:8000/ip
{
  "origin": "127.0.0.1"
}
[root@m1 ~]# 

Realice la liberación gris automática

Proceso de publicación en escala de grises

Capítulo práctico Service Mesh-Istio (Parte 1)

Marcador de lanzamiento en escala de grises automatizado

El lanzamiento gris es un proceso de migración de un poco de tráfico para una actualización continua. Por lo tanto, si opera este proceso manualmente, obviamente es ineficiente y propenso a errores. Por lo tanto, necesitamos usar una herramienta de lanzamiento gris automático, como Flagger:

  • Marcador : herramienta de publicación automática en escala de grises de código abierto de Weaveworks
  • Admite varios productos Service Mesh: Istio, Linkerd, App AWS Mesh
  • Indicador que supervisa el estado de liberación gris
  • Notificación (holgura, equipo de Microsoft)
    Capítulo práctico Service Mesh-Istio (Parte 1)

Flujo de trabajo del marcador:
Capítulo práctico Service Mesh-Istio (Parte 1)

Instalación de abanderados

Documentos oficiales:

Agregue el repositorio Helm de Flagger:

[root@m1 ~]# helm repo add flagger https://flagger.app
"flagger" has been added to your repositories
[root@m1 ~]# 

Crear crd de Flagger:

[root@m1 ~]# kubectl apply -f https://raw.githubusercontent.com/fluxcd/flagger/main/artifacts/flagger/crd.yaml
[root@m1 ~]# kubectl get crd |grep flagger
alertproviders.flagger.app                            2020-12-23T14:40:00Z
canaries.flagger.app                                  2020-12-23T14:40:00Z
metrictemplates.flagger.app                           2020-12-23T14:40:00Z
[root@m1 ~]# 

Implemente Flagger en el espacio de nombres de istio-system a través de Helm:

[root@m1 ~]# helm upgrade -i flagger flagger/flagger \
--namespace=istio-system \
--set crd.create=false \
--set meshProvider=istio \
--set metricsServer=http://prometheus.istio-system:9090

Agregar un gancho de holgura al abanderado le permite al abanderado enviar notificaciones al canal de holgura. Este paso es opcional:

[root@m1 ~]# helm upgrade -i flagger flagger/flagger \
--namespace=istio-system \
--set crd.create=false \
--set slack.url=https://hooks.slack.com/services/xxxxxx \
--set slack.channel=general \
--set slack.user=flagger

Además de slack, también podemos configurar un grafana para flagger, que integra un panel de control canary, que nos permite ver el progreso del lanzamiento en escala de grises:

[root@m1 ~]# helm upgrade -i flagger-grafana flagger/grafana \
--namespace=istio-system \
--set url=http://prometheus.istio-system:9090 \
--set user=admin \
--set password=admin

Una vez completadas las operaciones anteriores, confirme el despliegue de flagger:

[root@m1 ~]# kubectl get pods -n istio-system 
NAME                                    READY   STATUS    RESTARTS   AGE
flagger-b68b578b-5f8bh                  1/1     Running   0          7m50s
flagger-grafana-77b8c8df65-7vv89        1/1     Running   0          71s
...

Cree una puerta de enlace de entrada para la red:

[root@m1 ~]# kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: public-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - "*"
EOF

Además, también podemos implementar una herramienta de prueba de carga, por supuesto, esto también es opcional:

[root@m1 ~]# kubectl create ns test
namespace/test created
[root@m1 ~]# kubectl apply -k https://github.com/fluxcd/flagger/tree/main/kustomize/tester
[root@m1 ~]# kubectl get pods -n test
NAME                                  READY   STATUS    RESTARTS   AGE
flagger-loadtester-64695f854f-5hsmg   1/1     Running   0          114s
[root@m1 ~]# 

Si el método anterior es lento, puede clonar el almacén e implementar el probador:

[root@m1 ~]# cd /usr/local/src
[root@m1 /usr/local/src]# git clone https://github.com/fluxcd/flagger.git
[root@m1 /usr/local/src]# kubectl apply -k flagger/kustomize/tester/

Configuración de lanzamiento en escala de grises

Configure HAP para el servicio httpbin de modo que admita el escalado dinámico. Esto también es opcional, pero generalmente se recomienda configurar HAP:

[root@m1 ~]# kubectl apply -n demo -f - <<EOF
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: httpbin
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: httpbin
  minReplicas: 2
  maxReplicas: 4
  metrics:
  - type: Resource
    resource:
      name: cpu
      # scale up if usage is above
      # 99% of the requested CPU (100m)
      targetAverageUtilization: 99
EOF

Cree una métrica utilizada para verificar la versión en escala de grises, y falgger migrará gradualmente el tráfico de acuerdo con la métrica:

[root@m1 ~]# kubectl apply -f - <<EOF
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
  name: latency
  namespace: istio-system
spec:
  provider:
    type: prometheus
    address: http://prometheus.istio-system:9090
  query: |
    histogram_quantile(
        0.99,
        sum(
            rate(
                istio_request_duration_milliseconds_bucket{
                    reporter="destination",
                    destination_workload_namespace="{{ namespace }}",
                    destination_workload=~"{{ target }}"
                }[{{ interval }}]
            )
        ) by (le)
    )
EOF

Cree el flagger canary, el contenido de configuración específico es el siguiente, la información de configuración relacionada publicada por Grayscale se define aquí:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: httpbin
  namespace: demo
spec:
  # deployment reference
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: httpbin
  # the maximum time in seconds for the canary deployment
  # to make progress before it is rollback (default 600s)
  progressDeadlineSeconds: 60
  # HPA reference (optional)
  autoscalerRef:
    apiVersion: autoscaling/v2beta1
    kind: HorizontalPodAutoscaler
    name: httpbin
  service:
    # service port number
    port: 8000
    # container port number or name (optional)
    targetPort: 80
    # Istio gateways (optional)
    gateways:
    - public-gateway.istio-system.svc.cluster.local
  analysis:
    # schedule interval (default 60s)
    interval: 30s
    # max number of failed metric checks before rollback
    threshold: 5
    # max traffic percentage routed to canary
    # percentage (0-100)
    maxWeight: 100
    # canary increment step
    # percentage (0-100)
    stepWeight: 20
    metrics:
    - name: request-success-rate
      # minimum req success rate (non 5xx responses)
      # percentage (0-100)
      thresholdRange:
        min: 99
      interval: 1m
    - name: latency
      templateRef:
        name: latency
        namespace: istio-system
      # maximum req duration P99
      # milliseconds
      thresholdRange:
        max: 500
      interval: 30s
    # testing (optional)
    webhooks:
      - name: load-test
        url: http://flagger-loadtester.test/
        timeout: 5s
        metadata:
          cmd: "hey -z 1m -q 10 -c 2 http://httpbin-canary.demo:8000/headers"

Después de crear Canary, encontrará que crea automáticamente algunos recursos denominados principales para httpbin en el clúster, y también crea un Servicio Virtual cuyas reglas de enrutamiento apuntan a los servicios httpbin-primary y httpbin-canary:

[root@m1 ~]# kubectl get pods -n demo
NAME                             READY   STATUS    RESTARTS   AGE
httpbin-74fb669cc6-6ztkg         2/2     Running   0          50s
httpbin-74fb669cc6-vfs4h         2/2     Running   0          38s
httpbin-primary-9cb49747-94s4z   2/2     Running   0          3m3s
httpbin-primary-9cb49747-xhpcg   2/2     Running   0          3m3s
sleep-854565cb79-mcmnb           2/2     Running   0          94m
[root@m1 ~]# kubectl get svc -n demo
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
httpbin           ClusterIP   10.105.17.57    <none>        8000/TCP   86m
httpbin-canary    ClusterIP   10.99.206.196   <none>        8000/TCP   3m14s
httpbin-primary   ClusterIP   10.98.196.235   <none>        8000/TCP   3m14s
sleep             ClusterIP   10.103.14.114   <none>        80/TCP     95m
[root@m1 ~]# kubectl get vs -n demo
NAME      GATEWAYS                                            HOSTS         AGE
httpbin   ["public-gateway.istio-system.svc.cluster.local"]   ["httpbin"]   3m29s
[root@m1 ~]# 

Luego usamos el siguiente comando para activar la escala de grises:

[root@m1 ~]# kubectl -n demo set image deployment/httpbin httpbin=httpbin-v2
deployment.apps/httpbin image updated
[root@m1 ~]# 
  • Consejos: dep, configmap, secret se activarán

Consulta el evento de canary, puedes ver que se ha detectado la nueva versión:

[root@m1 ~]# kubectl describe canary httpbin -n demo
...
Events:
  Type     Reason  Age                  From     Message
  ----     ------  ----                 ----     -------
  ...
  Normal   Synced  2m57s                flagger  New revision detected! Scaling up httpbin.demo
  Warning  Synced  27s (x5 over 2m27s)  flagger  canary deployment httpbin.demo not ready: waiting for rollout to finish: 1 out of 2 new replicas have been updated

Verificando el Servicio Virtual de httpbin en este momento, encontrará que el 20% del tráfico se ha cambiado a la versión de lanzamiento gris:

[root@m1 ~]# kubectl describe vs httpbin -n demo
...
Spec:
  Gateways:
    public-gateway.istio-system.svc.cluster.local
  Hosts:
    httpbin
  Http:
    Route:
      Destination:
        Host:  httpbin-primary
      Weight:  80
      Destination:
        Host:  httpbin-canary
      Weight:  20
Events:        <none>

Luego ingrese al servicio de suspensión y use el script para acceder al servicio httpbin en un bucle:

[root@m1 ~]# kubectl exec -it -n demo sleep-854565cb79-mcmnb -c sleep -- sh
/ # while [ 1 ]; do curl http://httpbin.demo:8000/headers;sleep 2s; done

Si vuelve a mirar el Servicio virtual de httpbin, encontrará que el 60% del tráfico se ha cambiado a la versión de lanzamiento gris:

[root@m1 ~]# kubectl describe vs httpbin -n demo
...
Spec:
  Gateways:
    public-gateway.istio-system.svc.cluster.local
  Hosts:
    httpbin
  Http:
    Route:
      Destination:
        Host:  httpbin-primary
      Weight:  40
      Destination:
        Host:  httpbin-canary
      Weight:  60
Events:        <none>

Podemos abrir Grafana de Flagger:

[root@m1 ~]# kubectl -n istio-system port-forward svc/flagger-grafana 3000:80 --address 192.168.243.138
Forwarding from 192.168.243.138:3000 -> 3000

El siguiente tablero está integrado:
Capítulo práctico Service Mesh-Istio (Parte 1)

El proceso de lanzamiento se puede ver en Istio Canary Dashboard:
Capítulo práctico Service Mesh-Istio (Parte 1)

Finalmente, cambiar el 100% del tráfico a la versión de lanzamiento gris representa la finalización del lanzamiento:

[root@m1 ~]# kubectl describe vs httpbin -n demo
...
Spec:
  Gateways:
    public-gateway.istio-system.svc.cluster.local
  Hosts:
    httpbin
  Http:
    Route:
      Destination:
        Host:  httpbin-primary
      Weight:  0
      Destination:
        Host:  httpbin-canary
      Weight:  100
Events:        <none>

También puede ver el proceso de migración de tráfico desde el registro de eventos de canary httpbin:

[root@m1 ~]# kubectl describe canary httpbin -n demo
  ...
  Normal   Synced  3m44s (x2 over 18m)  flagger  New revision detected! Restarting analysis for httpbin.demo
  Normal   Synced  3m14s (x2 over 18m)  flagger  Starting canary analysis for httpbin.demo
  Normal   Synced  3m14s (x2 over 18m)  flagger  Advance httpbin.demo canary weight 20
  Warning  Synced  2m44s (x2 over 17m)  flagger  Halt advancement no values found for istio metric request-success-rate probably httpbin.demo is not receiving traffic: running query failed: no values found
  Normal   Synced  2m14s                flagger  Advance httpbin.demo canary weight 40
  Normal   Synced  104s                 flagger  Advance httpbin.demo canary weight 60
  Normal   Synced  74s                  flagger  Advance httpbin.demo canary weight 80
  Normal   Synced  44s                  flagger  Advance httpbin.demo canary weight 100

Cuando se complete el lanzamiento, el estado de canary httpbin cambiará a Correcto:

[root@m1 ~]# kubectl get canary -n demo
NAME      STATUS        WEIGHT   LASTTRANSITIONTIME
httpbin   Succeeded   0        2020-12-23T16:03:04Z
[root@m1 ~]# 

Mejorar la flexibilidad del sistema

El diseño flexible es popular actualmente en muchos campos. Por ejemplo, la flexibilidad en el diseño del paisaje ambiental se refiere a la capacidad de recuperarse de un desastre, pero el paisaje puede restaurar rápidamente su estructura y función después de un desastre. En el diseño de productos, la flexibilidad general se refiere a dejar cierto margen de maniobra para facilitar la modificación al diseñar las características morfológicas del producto.

La resiliencia en un sistema distribuido generalmente significa que el sistema tiene cierta tolerancia a fallas y capacidad de respuesta, puede recuperarse rápidamente cuando ocurre una falla y ser capaz de hacer frente a una falla. En esta sección, agregaremos algo de flexibilidad a la aplicación de muestra implementada anteriormente.

Medición de disponibilidad del sistema

Primero comprendamos un concepto: Acuerdo de nivel de servicio (SLA-Acuerdo de nivel de servicio). Un acuerdo de nivel de servicio se refiere a un acuerdo o contrato entre el proveedor de servicios y el cliente sobre la calidad, el nivel y el desempeño del servicio. Por ejemplo, un proveedor de servicios generalmente garantiza a sus clientes qué nivel de disponibilidad de su servicio, que es lo que solemos llamar unos 9 niveles de disponibilidad.

Fórmula de cálculo de disponibilidad del sistema:
Capítulo práctico Service Mesh-Istio (Parte 1)

Los niveles de disponibilidad comunes son los siguientes:
Capítulo práctico Service Mesh-Istio (Parte 1)

Diseño flexible

  • Una forma de lidiar con las fallas es hacer que el sistema sea tolerante a fallas y adaptable
  • Evitar que la falla (falla) se convierta en falla (falla)
  • incluyen principalmente:
    • Tolerancia a fallos: reintento, idempotencia
    • Escalabilidad: expansión horizontal automática (autoescalado)
    • Protección de sobrecarga: tiempo de espera, fusión, degradación, límite de corriente
    • Prueba de resiliencia: inyección de fallas

Flexibilidad proporcionada por Istio:

  • se acabó el tiempo
  • Rever
  • Fusible
  • Inyección de fallas

Proporcionar flexibilidad para aplicaciones de demostración

Primero, creamos un servicio virtual para la aplicación de demostración:

[root@m1 ~]# kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
  namespace: demo
spec:
  hosts:
  - "*"
  gateways:
  - httpbin-gateway
  http:
  - route:
    - destination:
        host: httpbin
        port:
          number: 8000
EOF

Agregue la primera capacidad elástica: configure el tiempo de espera, la configuración es la siguiente:

[root@m1 ~]# kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
  namespace: demo
spec:
  hosts:
  - "*"
  gateways:
  - httpbin-gateway
  http:
  - route:
    - destination:
        host: httpbin
        port:
          number: 8000
    timeout: 1s  # 配置超时
EOF

Reglas de configuración del tiempo de espera:

  • timeout & retries.perTryTimout existen al mismo tiempo
  • Tiempo de espera efectivo = min (timeout, retry.perTryTimout * retry.attempts)

Sobre la base del tiempo de espera, también podemos configurar la estrategia de reintento:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
  namespace: demo
spec:
  hosts:
  - "*"
  gateways:
  - httpbin-gateway
  http:
  - route:
    - destination:
        host: httpbin
        port:
          number: 8000
    retry:  # 配置重试策略
      attempts: 3
      perTryTimeout: 1s
    timeout: 8s

Vuelva a intentar los elementos de configuración:
Capítulo práctico Service Mesh-Istio (Parte 1)

  • x-envoy-retry-on: 5xx, error de puerta de enlace, reinicio, error de conexión ...
  • x-envoy-retry-grpc-on: Cancelado, excedido el plazo, interno, no disponible ...

Fusible de configuración:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
  namespace: demo
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
      outlierDetection:
        consecutiveErrors: 1
        interval: 1s
        baseEjectionTime: 3m
        maxEjectionPercent: 100

Configuración de fusibles:

  • El tamaño del grupo de conexiones TCP y HTTP es 1
  • Permitir solo 1 error
  • 1 recuento de solicitudes por segundo
  • Todos los pods se pueden eliminar del grupo de carga
  • El módulo fallido solo se puede volver a agregar después de eliminar 3 m

Configurar la política de seguridad

Soluciones de seguridad de Istio

Capítulo práctico Service Mesh-Istio (Parte 1)

Arquitectura de seguridad de Istio

Capítulo práctico Service Mesh-Istio (Parte 1)

Combate real

Crear autorización para un servicio específico (httpbin). Tenga en cuenta que no hay ninguna regla configurada, lo que significa denegar el servicio actual:

[root@m1 ~]# kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: httpbin
  namespace: demo
spec:
  selector:
    matchLabels:
      app: httpbin
EOF

La configuración anterior significa que este servicio es completamente inaccesible, podemos probarlo:

# 请求被拒绝
$ kubectl exec -it -n demo ${sleep_pod_name} -c sleep -- curl "http://httpbin.demo:8000/get"
RBAC: access denied  # 响应

# 其他版本可以正常访问
$ kubectl exec -it -n demo ${sleep_pod_name} -c sleep -- curl "http://httpbin-v2.demo:8000/get"

Podemos limitar el origen de la solicitud mediante la siguiente configuración. Por ejemplo, el origen de la solicitud debe ser el espacio de nombres de la demostración:

[root@m1 ~]# kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin
 namespace: demo
spec:
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/demo/sa/sleep"]
   - source:
       namespaces: ["demo"]
EOF

prueba:

# 请求通过
$ kubectl exec -it -n demo ${sleep_pod_name} -c sleep -- curl "http://httpbin.demo:8000/get"

# 请求被拒绝
$ kubectl exec -it -n ${other_namespace} ${sleep_pod_name} -c sleep -- curl "http://httpbin.demo:8000/get"

# 修改service account为${other_namespace}后,通过

Además de limitar el origen de la solicitud, también puede limitar que solo se permita el acceso a interfaces específicas:

[root@m1 ~]# kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin
 namespace: demo
spec:
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/demo/sa/sleep"]
   - source:
       namespaces: ["demo"]
   to:
   - operation:
       methods: ["GET"]
       paths: ["/get"]
EOF

prueba:

# 请求通过
$ kubectl exec -it -n demo ${sleep_pod_name} -c sleep -- curl "http://httpbin.demo:8000/get"

# 请求被拒绝
$ kubectl exec -it -n demo ${sleep_pod_name} -c sleep -- curl "http://httpbin.demo:8000/ip"

También puede configurar otras condiciones específicas, como limitar los encabezados de solicitud, que generalmente se utilizan en escenarios donde necesitamos que el cliente lleve encabezados de solicitud específicos para permitir el acceso a la interfaz:

[root@m1 ~]# kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin
 namespace: demo
spec:
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/demo/sa/sleep"]
   - source:
       namespaces: ["demo"]
   to:
   - operation:
       methods: ["GET"]
       paths: ["/get"]
   when:
   - key: request.headers[x-rfma-token]
     values: ["test*"]
EOF

prueba:

# 请求不通过
$ kubectl exec -it -n demo ${sleep_pod_name} -c sleep -- curl "http://httpbin.demo:8000/get"

# 加token后通过
$ kubectl exec -it -n demo ${sleep_pod_name} -c sleep -- curl "http://httpbin.demo:8000/get" -H x-rfma-token:test1

Supongo que te gusta

Origin blog.51cto.com/zero01/2572820
Recomendado
Clasificación