Proceso de preparación y construcción de proyectos
Proceso típico de CI / CD-DevOps
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
Proceso push vs pull (canalización):
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
Listo para trabajar
Primero, necesitamos preparar un clúster de Kubernetes:
- Compile el clúster de alta disponibilidad de k8s basado en kubeadm
- Cree un modo binario de clúster de alta disponibilidad de k8s
- inicio de minikube
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:
- 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:
Instalar Flux
Documentos oficiales:
- https://docs.fluxcd.io/en/latest/tutorials/get-started/
- https://docs.fluxcd.io/en/latest/guides/use-private-git-host/
Primero, instale la fluxctl
herramienta de comando en el repositorio de Github en el archivo ejecutable de descarga. Luego colóquelo en /usr/bin
el 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_hosts
archivo 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:
Implementar la aplicación
Aplicaciones creadas como un espacio de nombres separado, y para agregar istio-injection=enabled
etiquetas, 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 config
directorio 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
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)
Flujo de trabajo del marcador:
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
- El documento de uso de los webhooks slack: https://api.slack.com/messaging/webhooks
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:
El proceso de lanzamiento se puede ver en Istio Canary Dashboard:
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:
Los niveles de disponibilidad comunes son los siguientes:
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:
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
Arquitectura de seguridad de Istio
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