
El CD es reconocido como una práctica de desarrollo de software empresarial; es el resultado de una evolución natural de los principios de CI establecidos. Sin embargo, el CD sigue siendo una ocurrencia bastante rara, posiblemente debido a la complejidad de la administración y al temor de implementaciones fallidas que afectan la disponibilidad del sistema.
Flagger es un operador de código abierto de Kubernetes que tiene como objetivo eliminar las relaciones confusas. Automatiza la promoción de implementaciones canarias utilizando las compensaciones de tráfico de Istio y las métricas de Prometheus para analizar el comportamiento de la aplicación durante el despliegue administrado.
A continuación hay una guía paso a paso sobre cómo configurar y usar Flagger en Google Kubernetes Engine (GKE).
Configurar el clúster de Kubernetes
Comienza creando un clúster GKE con un complemento Istio (si no tiene una cuenta GCP, puede registrarse aquí para recibir créditos gratuitos).
Inicie sesión en Google Cloud, cree un proyecto y habilite la facturación. Instale la utilidad de línea de comandos gcloud y personalice su proyecto con gcloud init
.
Establezca el proyecto predeterminado, el área de cálculo y la zona (reemplace PROJECT_ID
con su proyecto):
gcloud config set project PROJECT_ID gcloud config set compute/region us-central1 gcloud config set compute/zone us-central1-a
Habilite el servicio GKE y cree un clúster con los complementos HPA e Istio:
gcloud services enable container.googleapis.com K8S_VERSION=$(gcloud beta container get-server-config --format=json | jq -r '.validMasterVersions[0]') gcloud beta container clusters create istio \ --cluster-version=${K8S_VERSION} \ --zone=us-central1-a \ --num-nodes=2 \ --machine-type=n1-standard-2 \ --disk-size=30 \ --enable-autorepair \ --no-enable-cloud-logging \ --no-enable-cloud-monitoring \ --addons=HorizontalPodAutoscaling,Istio \ --istio-config=auth=MTLS_PERMISSIVE
El comando anterior creará un grupo de nodos predeterminado que incluye dos máquinas virtuales n1-standard-2
(vCPU: 2, RAM 7.5 GB, disco: 30 GB). Idealmente, debe aislar los componentes de Istio de sus cargas de trabajo, pero no hay una manera fácil de ejecutar los pods de Istio en un grupo de nodos dedicado. Los manifiestos de Istio se consideran de solo lectura, y GKE deshacerá cualquier cambio, como vincular a un nodo o desconectarse de un hogar.
Configure las credenciales para kubectl
:
gcloud container clusters get-credentials istio
Cree el enlace del rol de administrador del clúster:
kubectl create clusterrolebinding "cluster-admin-$(whoami)" \ --clusterrole=cluster-admin \ --user="$(gcloud config get-value core/account)"
Instale la herramienta de línea de comando Helm :
brew install kubernetes-helm
Homebrew 2.0 ahora también está disponible para Linux .
Cree una cuenta de servicio y enlace de rol de clúster para Tiller:
kubectl -n kube-system create sa tiller && \ kubectl create clusterrolebinding tiller-cluster-rule \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:tiller
Expanda Tiller en el kube-system
:
helm init --service-account tiller
Debería considerar usar SSL entre Helm y Tiller. Para obtener más información sobre cómo asegurar una instalación de Helm, consulte docs.helm.sh
Confirmar configuración:
kubectl -n istio-system get svc
Después de unos segundos, GCP debería asignar una dirección IP externa para el servicio de istio-ingressgateway
.
Istio Input Gateway Setup
Cree una dirección IP estática llamada istio-gateway
utilizando la dirección IP de la puerta de enlace Istio:
export GATEWAY_IP=$(kubectl -n istio-system get svc/istio-ingressgateway -ojson | jq -r .status.loadBalancer.ingress[0].ip) gcloud compute addresses create istio-gateway --addresses ${GATEWAY_IP} --region us-central1
Ahora necesita un dominio de Internet y acceso a su registrador DNS. Agregue dos entradas A (reemplace example.com
con su dominio):
istio.example.com A ${GATEWAY_IP} *.istio.example.com A ${GATEWAY_IP}
Verifique que el comodín DNS esté funcionando:
watch host test.istio.example.com
Cree una puerta de enlace común Istio para proporcionar servicios fuera de la malla de servicios a través de HTTP:
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: - "*"
Guarde el recurso anterior como public-gateway.yaml y luego aplíquelo:
kubectl apply -f ./public-gateway.yaml
Ningún sistema de producción debe proporcionar servicios en Internet sin SSL. Para proteger la puerta de enlace Istio con cert-manager, CloudDNS y Let's Encrypt, lea la documentación de Flagger GKE.
Instalación de abanderado
El complemento GKE Istio no incluye la instancia de Prometheus, que limpia el servicio de telemetría de Istio. Dado que Flagger utiliza las métricas HTTP de Istio para realizar el análisis canario, debe implementar la siguiente configuración de Prometheus similar a la que se proporciona con el esquema oficial de Istio Helm.
REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master kubectl apply -f ${REPO}/artifacts/gke/istio-prometheus.yaml
Agregue el repositorio de Flagger Helm:
helm repo add flagger https://flagger.app
Expanda Flagger en el istio-system
del sistema istio-system
habilitando las notificaciones Slack:
helm upgrade -i flagger flagger/flagger \ --namespace=istio-system \ --set metricsServer=http://prometheus.istio-system:9090 \ --set slack.url=https://hooks.slack.com/services/YOUR-WEBHOOK-ID \ --set slack.channel=general \ --set slack.user=flagger
Puede instalar Flagger en cualquier espacio de nombres si puede comunicarse con el servicio Istio Prometheus a través del puerto 9090.
Flagger tiene un tablero de Grafana para el análisis canario. Instale Grafana en el istio-system
:
helm upgrade -i flagger-grafana flagger/grafana \ --namespace=istio-system \ --set url=http://prometheus.istio-system:9090 \ --set user=admin \ --set password=change-me
Expanda Grafana a través de una puerta de enlace abierta creando un servicio virtual (reemplace example.com
con su dominio):
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: grafana namespace: istio-system spec: hosts: - "grafana.istio.example.com" gateways: - public-gateway.istio-system.svc.cluster.local http: - route: - destination: host: flagger-grafana
Guarde el recurso anterior como grafana-virtual-service.yaml y luego aplíquelo:
kubectl apply -f ./grafana-virtual-service.yaml
Cuando vaya a http://grafana.istio.example.com
en un navegador, debería ser dirigido a la página de inicio de sesión de Grafana.
Implementación de aplicaciones web con Flagger
Flagger implementa Kubernetes y, si es necesario, escala automática horizontal (HPA), luego crea una serie de objetos (implementaciones de Kubernetes, servicios ClusterIP y servicios virtuales Istio). Estos objetos abren la aplicación en la malla de servicios y gestionan el análisis y la promoción canarios.

Cree un espacio de nombres de prueba con la implementación de Istio Sidecar habilitada:
REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master kubectl apply -f ${REPO}/artifacts/namespaces/test.yaml
Cree una herramienta de escala horizontal automática de despliegue y hogar:
kubectl apply -f ${REPO}/artifacts/canaries/deployment.yaml kubectl apply -f ${REPO}/artifacts/canaries/hpa.yaml
Implemente un servicio de carga de prueba para generar tráfico durante el análisis canario:
helm upgrade -i flagger-loadtester flagger/loadtester \ --namepace=test
Cree un recurso canario personalizado (reemplace example.com
con su dominio):
apiVersion: flagger.app/v1alpha3 kind: Canary metadata: name: podinfo namespace: test spec: targetRef: apiVersion: apps/v1 kind: Deployment name: podinfo progressDeadlineSeconds: 60 autoscalerRef: apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler name: podinfo service: port: 9898 gateways: - public-gateway.istio-system.svc.cluster.local hosts: - app.istio.example.com canaryAnalysis: interval: 30s threshold: 10 maxWeight: 50 stepWeight: 5 metrics: - name: istio_requests_total threshold: 99 interval: 30s - name: istio_request_duration_seconds_bucket threshold: 500 interval: 30s webhooks: - name: load-test url: http://flagger-loadtester.test/ timeout: 5s metadata: cmd: "hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"
Guarde el recurso anterior como podinfo-canary.yaml y luego aplíquelo:
kubectl apply -f ./podinfo-canary.yaml
El análisis anterior, si tiene éxito, se realizará dentro de cinco minutos, con métricas HTTP verificadas cada medio minuto. Puede determinar el tiempo mínimo requerido para verificar y promover una implementación canaria utilizando la siguiente fórmula: interval * (maxWeight / stepWeight)
. Los campos de Canary CRD se documentan aquí .
En un par de segundos, Flagger creará objetos canarios:
# applied deployment.apps/podinfo horizontalpodautoscaler.autoscaling/podinfo canary.flagger.app/podinfo # generated deployment.apps/podinfo-primary horizontalpodautoscaler.autoscaling/podinfo-primary service/podinfo service/podinfo-canary service/podinfo-primary virtualservice.networking.istio.io/podinfo
Abra un navegador y vaya a app.istio.example.com
, debería ver el número de versión de la aplicación de demostración .
Análisis automático canario y promoción
Flagger implementa un bucle de control que gradualmente mueve el tráfico a canario, mientras mide indicadores clave de rendimiento, por ejemplo, la tasa de éxito de las solicitudes HTTP, la duración promedio de las solicitudes y el rendimiento del hogar. Según el análisis, el KPI canario progresa o se interrumpe, y los resultados del análisis se publican en Slack.

La implementación de Canary comienza cuando cambia uno de los siguientes objetos:
- Implemente PodSpec (imagen del contenedor, comando, puertos, env, etc.)
- ConfigMaps se montan como volúmenes o se convierten en variables de entorno
- Los secretos se montan como volúmenes o se convierten en variables de entorno.
Lanzamiento de una implementación canaria al actualizar una imagen de contenedor:
kubectl -n test set image deployment/podinfo \ podinfod=quay.io/stefanprodan/podinfo:1.4.1
Flagger descubre que la versión de implementación ha cambiado y comienza a analizarla:
kubectl -n test describe canary/podinfo Events: New revision detected podinfo.test Scaling up podinfo.test Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available Advance podinfo.test canary weight 5 Advance podinfo.test canary weight 10 Advance podinfo.test canary weight 15 Advance podinfo.test canary weight 20 Advance podinfo.test canary weight 25 Advance podinfo.test canary weight 30 Advance podinfo.test canary weight 35 Advance podinfo.test canary weight 40 Advance podinfo.test canary weight 45 Advance podinfo.test canary weight 50 Copying podinfo.test template spec to podinfo-primary.test Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available Promotion completed! Scaling down podinfo.test
Durante el análisis, los resultados canarios se pueden rastrear usando Grafana:

Tenga en cuenta: si se aplican nuevos cambios a la implementación durante el análisis canario, Flagger reiniciará la fase de análisis.
Haga una lista de todos los "canarios" en su grupo:
watch kubectl get canaries --all-namespaces NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME test podinfo Progressing 15 2019-01-16T14:05:07Z prod frontend Succeeded 0 2019-01-15T16:15:07Z prod backend Failed 0 2019-01-14T17:05:07Z
Si ha habilitado las notificaciones de Slack, recibirá los siguientes mensajes:

Retroceso automático
Durante el análisis canario, puede generar errores sintéticos HTTP 500 y un alto retraso de respuesta para verificar si Flagger detendrá la implementación.
Cree un sub de prueba y haga lo siguiente en él:
kubectl -n test run tester \ --image=quay.io/stefanprodan/podinfo:1.2.1 \ -- ./podinfo --port=9898 kubectl -n test exec -it tester-xx-xx sh
HTTP 500 Error Generation:
watch curl http://podinfo-canary:9898/status/500
Generación de retraso:
watch curl http://podinfo-canary:9898/delay/1
Cuando el número de comprobaciones sin éxito alcanza el valor umbral, el tráfico se enruta de nuevo al canal primario, el canario se escala a cero y la implementación se marca como no exitosa.
Los errores de Canary y los picos de retraso se registran como eventos de Kubernetes y Flagger los registra en formato JSON:
kubectl -n istio-system logs deployment/flagger -f | jq .msg Starting canary deployment for podinfo.test Advance podinfo.test canary weight 5 Advance podinfo.test canary weight 10 Advance podinfo.test canary weight 15 Halt podinfo.test advancement success rate 69.17% < 99% Halt podinfo.test advancement success rate 61.39% < 99% Halt podinfo.test advancement success rate 55.06% < 99% Halt podinfo.test advancement success rate 47.00% < 99% Halt podinfo.test advancement success rate 37.00% < 99% Halt podinfo.test advancement request duration 1.515s > 500ms Halt podinfo.test advancement request duration 1.600s > 500ms Halt podinfo.test advancement request duration 1.915s > 500ms Halt podinfo.test advancement request duration 2.050s > 500ms Halt podinfo.test advancement request duration 2.515s > 500ms Rolling back podinfo.test failed checks threshold reached 10 Canary failed! Scaling down podinfo.test
Si ha habilitado las notificaciones de Slack, recibirá un mensaje cuando se alcance el plazo o cuando se alcance el número máximo de cheques fallidos durante el análisis:

En conclusión
El lanzamiento de una malla de servicios, como Istio, además de Kubernetes proporcionará métricas, registros y protocolos automáticos, pero la implementación de cargas de trabajo aún depende de herramientas externas. Flagger busca cambiar esto agregando las capacidades de entrega progresiva de Istio.
Flagger es compatible con cualquier solución Kubernetes CI / CD, y el análisis canario puede ampliarse fácilmente utilizando webhooks para realizar pruebas de integración / aceptación del sistema, pruebas de estrés o cualquier otra prueba de usuario. Debido a que Flagger es declarativo y responde a los eventos de Kubernetes, se puede usar en tuberías de GitOps con Weave Flux o JenkinsX . Si está utilizando JenkinsX, puede instalar Flagger con complementos jx.
Flagger es compatible con Weaveworks y proporciona implementaciones canarias en Weave Cloud . El proyecto se prueba en GKE, EX y metal desnudo con kubeadm.
Si tiene alguna sugerencia para mejorar Flagger, envíe una pregunta o relaciones públicas a GitHub en stefanprodan / flagger . ¡Las contribuciones son más que bienvenidas!
Gracias Ray Tsang .