{"id":10574,"date":"2021-07-07T13:02:10","date_gmt":"2021-07-07T13:02:10","guid":{"rendered":"https:\/\/bluetab.net\/?p=10574"},"modified":"2021-07-07T13:02:10","modified_gmt":"2021-07-07T13:02:10","slug":"workshop-chaos-engineering-sobre-kubernetes-con-litmus","status":"publish","type":"post","link":"https:\/\/bluetab.es\/en\/2021\/07\/workshop-chaos-engineering-sobre-kubernetes-con-litmus\/","title":{"rendered":"Workshop Ingenier\u00eda del caos sobre Kubernetes con Litmus"},"content":{"rendered":"<h1>Workshop Ingenier\u00eda del caos sobre Kubernetes con Litmus<\/h1>\n<figure><a href=\"https:\/\/www.linkedin.com\/in\/%C3%A1ngel-maroco-85a0807b\/\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-150x150.jpg\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-150x150.jpg 150w, https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-300x300.jpg 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-768x768.jpg 768w, https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-75x75.jpg 75w, https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco.jpg 800w\" sizes=\"(max-width: 150px) 100vw, 150px\"><\/a><\/figure>\n<h4><a href=\"https:\/\/www.linkedin.com\/in\/%C3%A1ngel-maroco-85a0807b\/\" target=\"_blank\" rel=\"noopener\">\u00c1ngel Maroco<\/a><\/h4>\n<p>AWS Cloud Architect<\/p>\n<p>Share on twitter<br \/>\nShare on linkedin<\/p>\n<p>LitmusChaos nace con el objetivo de ayudar a desarrolladores y SREs (Site Reliability Engineering ) de Kubernetes a identificar puntos d\u00e9biles y mejorar la resiliencia de sus aplicaciones\/plataformas proporcionando un marco de trabajo completo.<\/p>\n<p>Sus principales ventajas respecto a otras herramientas son:<\/p>\n<ul>\n<li><strong>Experimentos declarativos mediante K8S CRDs (Custom Resource Definition): <\/strong>todos los componentes (planificaci\u00f3n, ejecuci\u00f3n, parametrizaci\u00f3n, etc.) de un experimento se definen dentro del \u00e1mbito de kubernetes haciendo uso de YAML.<\/li>\n<li><strong>M\u00faltiples experimentos predefinidos:<\/strong> dispone de un conjunto de experimentos suficientemente amplio para dar cobertura a los principales recursos de K8s.<\/li>\n<li><strong>SDK en Go\/Python\/Ansible para desarrollar tus propios experimentos:<\/strong>&nbsp;dispone de un metodolog\u00eda de desarrollo bien definida para construir experimentos que se adapten a tus necesidades particulares.<\/li>\n<li><strong>Creaci\u00f3n de workflows a trav\u00e9s de GUI:<\/strong>&nbsp;con Litmus UI Portal puedes crear workflows complejos utilizando todos los experimentos predefinidos mediante interfaz web.<\/li>\n<li><strong>F\u00e1cil integraci\u00f3n en pipelines CI\/CD:<\/strong>&nbsp;invocar y obtener el resultado de un experimento es extremadamente f\u00e1cil.<\/li>\n<li><strong>Exportaci\u00f3n de m\u00e9tricas:<\/strong>&nbsp;puedes exportar distintas m\u00e9tricas de tus experimentos directamente a Prometheus.<\/li>\n<\/ul>\n<p>El producto est\u00e1 liberado bajo licencia Apache-2.0, dispone de una amplia comunidad de desarrolladores y desde 2020 pertenece a Cloud Native Computing Foundation.<\/p>\n<h2>Objetivos del workshop<\/h2>\n<ol>\n<li>Conocer los principales componentes de un experimento y realizar su despliegue<\/li>\n<li>Analizar detalladamente la ejecuci\u00f3n de tres experimentos (criterios de entrada, hip\u00f3tesis, observaciones y resultados)<\/li>\n<li>Ver las m\u00faltiples opciones referentes a planificaci\u00f3n de experimentos.<\/li>\n<li>Visualizar los resultados mediante Prometheus\/Grafana.<\/li>\n<li>Analizar un caso de pruebas de resiliencia + test de rendimiento con JMeter.<\/li>\n<li>Principales funcionalidades de Litmus UI Portal<\/li>\n<\/ol>\n<h2>Preparaci\u00f3n de consola<\/h2>\n<p>Recomendamos abrir una consola y crear 4 paneles:<\/p>\n<ol>\n<li>Panel principal (ejecutaremos todo el contenido del workshop)<\/li>\n<li>Monitorizaci\u00f3n de la aplicaci\u00f3n de test<\/li>\n<li>Monitorizaci\u00f3n de pods<\/li>\n<li>Monitorizaci\u00f3n de eventos<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/console-tabs.png\" title=\"\" alt=\"\"><\/p>\n<h2>Clonaci\u00f3n de repositorio<\/h2>\n<pre><code class=\"language-python\">git clone https:\/\/github.com\/angelmaroco\/litmus-chaos-engineering-workshop.git\ncd litmus-chaos-engineering-workshop <\/code><\/pre>\n<h2>Creaci\u00f3n de entorno de pruebas K8s con minikube<\/h2>\n<p>Para este workshop vamos a utilizar minikube pero Litmus puede ser desplegado en cualquier servicio gestionado tipo EKS\/AKS\/GKE.<\/p>\n<p>Minikube requiere de un gestor de contenedores o m\u00e1quinas virtuales (Docker, Hyperkit, Hyper-V, KVM, Parallels, Podman, VirtualBox, or VMWare).<\/p>\n<p>Recomendamos hacer uso de docker. En el caso de no estar disponible en el sistema, puedes realizar la instalaci\u00f3n con los siguientes comandos:<\/p>\n<pre><code class=\"language-python\">if ! [ -x \"$(command -v docker)\" ]; then\n    curl -fsSL https:\/\/get.docker.com -o \/tmp\/get-docker.sh\n    sh \/tmp\/get-docker.sh\nfi <\/code><\/pre>\n<pre><code class=\"language-python\"># install kubectl\ncurl -Ls \"https:\/\/dl.k8s.io\/release\/$(curl -L -s https:\/\/dl.k8s.io\/release\/stable.txt)\/bin\/linux\/amd64\/kubectl\" --output \/tmp\/kubectl\nsudo install \/tmp\/kubectl \/usr\/local\/bin\/kubectl\nkubectl version --client\n# install minikube\ncurl -Ls https:\/\/storage.googleapis.com\/minikube\/releases\/latest\/minikube-linux-amd64 --output \/tmp\/minikube-linux-amd64\nsudo install \/tmp\/minikube-linux-amd64 \/usr\/local\/bin\/minikube\nminikube version\n# starting minikube\nminikube start --cpus 2 --memory 4096\n# enabled ingress &amp; metrics servers\nminikube addons enable ingress\nminikube addons enable metrics-server\n# enabled tunnel &amp; dashboard\nminikube tunnel &gt; \/dev\/null &amp;\nminikube dashboard &gt; \/dev\/null &amp;\n <\/code><\/pre>\n<h2>Creaci\u00f3n de namespaces K8s<\/h2>\n<pre><code class=\"language-python\"># create namespace testing\nkubectl apply -f src\/base\/testing-ns.yaml\n# create namespace litmus\nkubectl apply -f src\/base\/litmus-ns.yaml\n# create namespace monitoring (prometheus + grafana)\nkubectl apply -f src\/base\/monitoring-ns.yaml\nTESTING_NAMESPACE=\"testing\"\nLITMUS_NAMESPACE=\"litmus\"\nMONITORING_NAMESPACE=\"monitoring\"\n <\/code><\/pre>\n<h2>Despliegue de aplicaci\u00f3n de test<\/h2>\n<p>Desplegamos una aplicaci\u00f3n de test para poder ejecutar los experimentos de litmus.<\/p>\n<ul>\n<li><strong>nginx-deployment.yaml<\/strong>: creaci\u00f3n de despliegue &#8220;app-sample&#8221;, con recursos de cpu\/memoria &#8220;limits&#8221;\/&#8221;request&#8221; y configuraci\u00f3n de &#8220;readinessProbe&#8221;. Exponemos el servicio en el puerto 80 a trav\u00e9s de un balanceador.<\/li>\n<li><strong>nginx-hpa.yaml<\/strong>: creaci\u00f3n de&nbsp;<em>Horizontal Pod Autoscaler<\/em>&nbsp;(min 2 r\u00e9plicas \/ max 10 r\u00e9plicas)<\/li>\n<\/ul>\n<pre><code class=\"language-python\"># deployment\nkubectl apply -f src\/nginx\/nginx-deployment.yaml --namespace=\"${TESTING_NAMESPACE}\"\n# enable hpa\nkubectl apply -f src\/nginx\/nginx-hpa.yaml --namespace=\"${TESTING_NAMESPACE}\"\n# expose service \nkubectl expose deployment app-sample --type=LoadBalancer --port=80  -n \"${TESTING_NAMESPACE}\"\n# wait deployment\nkubectl wait --for=condition=available --timeout=60s deployment\/app-sample -n \"${TESTING_NAMESPACE}\"\n# get pods\nkubectl get pods -n \"${TESTING_NAMESPACE}\"\n#-----------------------------------------\nNAME                          READY   STATUS    RESTARTS   AGE\napp-sample-7ff489dbd5-82ppw   1\/1     Running   0          45m\napp-sample-7ff489dbd5-jg9vh   1\/1     Running   0          45m\n# get service\nkubectl get services -n \"${TESTING_NAMESPACE}\"\n# -----------------------------------------\nNAME         TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE\napp-sample   LoadBalancer   10.109.196.239   10.109.196.239   80:30020\/TCP   3m54s\n <\/code><\/pre>\n<h3>\n\t\t\t\t\t En PANEL 2 ejecutar:<\/h3>\n<pre><code class=\"language-python\">TESTING_NAMESPACE='testing'\nURL_SERVICE=$(minikube service app-sample --url -n \"${TESTING_NAMESPACE}\")\nwhile true; do sleep 5; curl --connect-timeout 2 -s -o \/dev\/null -w \"Response code %{http_code}\"  ${URL_SERVICE}; echo -e ' - '$(date);done\n <\/code><\/pre>\n<h3>\n\t\t\t\t\tEn PANEL 3 ejecutar:<\/h3>\n<pre><code class=\"language-python\">TESTING_NAMESPACE='testing'\nwatch -n 1 kubectl get pods -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<h3>\n\t\t\t\t\tEn PANEL 4 ejecutar:<\/h3>\n<pre><code class=\"language-python\">kubectl get events -A -w <\/code><\/pre>\n<h2>Despliegue Chaos Experiments<\/h2>\n<pre><code class=\"language-python\"># litmus operator &amp; experiments\nkubectl apply -f https:\/\/litmuschaos.github.io\/litmus\/litmus-operator-v1.13.0.yaml -n \"${LITMUS_NAMESPACE}\"\nkubectl apply -f https:\/\/hub.litmuschaos.io\/api\/chaos\/1.13.0?file=charts\/generic\/experiments.yaml -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<pre><code class=\"language-python\">kubectl get chaosexperiments -n \"${TESTING_NAMESPACE}\"\n# ----------------------------------------------------\nNAME                      AGE\ncontainer-kill            6s\ndisk-fill                 6s\ndisk-loss                 6s\ndocker-service-kill       6s\nk8-pod-delete             6s\nk8-service-kill           6s\nkubelet-service-kill      6s\nnode-cpu-hog              6s\nnode-drain                6s\nnode-io-stress            6s\nnode-memory-hog           6s\nnode-poweroff             6s\nnode-restart              6s\nnode-taint                6s\npod-autoscaler            6s\npod-cpu-hog               6s\npod-delete                6s\npod-io-stress             6s\npod-memory-hog            6s\npod-network-corruption    6s\npod-network-duplication   6s\npod-network-latency       6s\npod-network-loss          6s\n <\/code><\/pre>\n<h2>Despliegue servicios monitorizaci\u00f3n: Prometheus + Grafana<\/h2>\n<p>Litmus permite exportar las m\u00e9tricas de los experimentos a Prometheus a trav\u00e9s de&nbsp;<em>chaos-exporter<\/em>.<\/p>\n<pre><code class=\"language-python\">kubectl -n ${MONITORING_NAMESPACE} apply -f src\/litmus\/monitoring\/utils\/prometheus\/prometheus-operator\/\nkubectl -n ${MONITORING_NAMESPACE} apply -f src\/litmus\/monitoring\/utils\/metrics-exporters-with-service-monitors\/kube-state-metrics\/\nkubectl -n ${MONITORING_NAMESPACE} apply -f src\/litmus\/monitoring\/utils\/alert-manager-with-service-monitor\/\nkubectl -n ${LITMUS_NAMESPACE} apply -f src\/litmus\/monitoring\/utils\/metrics-exporters-with-service-monitors\/litmus-metrics\/chaos-exporter\/\nkubectl -n ${MONITORING_NAMESPACE} apply -f src\/litmus\/monitoring\/utils\/prometheus\/prometheus-configuration\/\nkubectl -n ${MONITORING_NAMESPACE} apply -f src\/litmus\/monitoring\/utils\/grafana\/\nkubectl -n ${MONITORING_NAMESPACE} apply -f src\/litmus\/monitoring\/utils\/metrics-exporters-with-service-monitors\/node-exporter\/\n# wait deployment\nkubectl wait --for=condition=available --timeout=60s deployment\/grafana -n ${MONITORING_NAMESPACE}\nkubectl wait --for=condition=available --timeout=60s deployment\/prometheus-operator -n ${MONITORING_NAMESPACE}\necho \"Acceso dashboard --&gt; $(minikube service grafana -n ${MONITORING_NAMESPACE} --url)\/d\/nodepodmetrics\/node-and-pod-chaos-metrics?orgId=1&amp;refresh=5s\"\n <\/code><\/pre>\n<p>Para este workshop hemos personalizado un dashboard de grafana donde visualizaremos:<\/p>\n<ul>\n<li>Timelime de experimentos ejecutados<\/li>\n<li>4 gr\u00e1ficas tipo &#8220;Gauge&#8221; con n\u00famero de total de experimentos, estado Pass, estado Fail y estado Awaited.<\/li>\n<li>Consumo de CPU nivel nodo<\/li>\n<li>Consumo de CPU a nivel POD (app-sample)<\/li>\n<li>Consumo de memoria nivel nodo<\/li>\n<li>Consumo de memoria a nivel POD (app-sample)<\/li>\n<li>Tr\u00e1fico red (IN\/OUT) nivel nodo<\/li>\n<li>Tr\u00e1fico red (IN\/OUT) nivel POD (app-sample)<\/li>\n<\/ul>\n<p>Datos acceso grafana:<\/p>\n<ul>\n<li>usuario: admin<\/li>\n<li>password: admin<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/grafana-main.png\" title=\"\" alt=\"\"><\/p>\n<h2>Creaci\u00f3n de anotaci\u00f3n &#8220;litmuschaos&#8221;<\/h2>\n<p>Para habilitar la ejecuci\u00f3n de experimentos contra nuestro deployment, necesitamos a\u00f1adir la anotaci\u00f3n <em>litmuschaos.io\/chaos=<\/em>\u201c<em>true<\/em>\u201c.&nbsp;Como veremos m\u00e1s adelante, todos los experimentos tienen la propiedad&nbsp;<em>annotationCheck: \u201ctrue\u201d.<\/em><\/p>\n<pre><code class=\"language-python\"># add annotate (enable chaos)\nkubectl annotate deploy\/app-sample litmuschaos.io\/chaos=\"true\" -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<pre><code class=\"language-python\">kubectl describe deploy\/app-sample -n \"${TESTING_NAMESPACE}\"\n# -----------------------------------------------------------\nName:                   app-sample\nNamespace:              testing\nCreationTimestamp:      Mon, 29 Mar 2021 09:35:53 +0200\nLabels:                 app=app-sample\n                        app.kubernetes.io\/name=app-sample\nAnnotations:            deployment.kubernetes.io\/revision: 1\n                        litmuschaos.io\/chaos: true # &lt;-- HABILITAMOS EXPERIMENTOS\nSelector:               app.kubernetes.io\/name=app-sample\nReplicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable\nStrategyType:           RollingUpdate\n <\/code><\/pre>\n<h2>Detalle componentes de un experimento<\/h2>\n<h4><strong>Service Account, Role y RoleBinding<\/strong><\/h4>\n<p>Cada experimento debe tener asociado un ServiceAccount, un Role para definir permisos y un RoleBinding para relacionar el ServiceAccount\/Role.<\/p>\n<p>Pod\u00e9is encontrar todas las definiciones dentro de&nbsp;<em>src\/litmus\/nombre-experimento\/nombre-experimento-sa.yaml<\/em><\/p>\n<pre><code class=\"language-python\">apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: container-kill-sa\n  namespace: testing\n  labels:\n    name: container-kill-sa\n    app.kubernetes.io\/part-of: litmus\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: Role\nmetadata:\n  name: container-kill-sa\n  namespace: testing\n  labels:\n    name: container-kill-sa\n    app.kubernetes.io\/part-of: litmus\nrules:\n  - apiGroups: [\"\"]\n    resources:\n      [\"pods\", \"pods\/exec\", \"pods\/log\", \"events\", \"replicationcontrollers\"]\n    verbs:\n      [\"create\", \"list\", \"get\", \"patch\", \"update\", \"delete\", \"deletecollection\"]\n  - apiGroups: [\"batch\"]\n    resources: [\"jobs\"]\n    verbs: [\"create\", \"list\", \"get\", \"delete\", \"deletecollection\"]\n  - apiGroups: [\"apps\"]\n    resources: [\"deployments\", \"statefulsets\", \"daemonsets\", \"replicasets\"]\n    verbs: [\"list\", \"get\"]\n  - apiGroups: [\"apps.openshift.io\"]\n    resources: [\"deploymentconfigs\"]\n    verbs: [\"list\", \"get\"]\n  - apiGroups: [\"argoproj.io\"]\n    resources: [\"rollouts\"]\n    verbs: [\"list\", \"get\"]\n  - apiGroups: [\"litmuschaos.io\"]\n    resources: [\"chaosengines\", \"chaosexperiments\", \"chaosresults\"]\n    verbs: [\"create\", \"list\", \"get\", \"patch\", \"update\"]\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: RoleBinding\nmetadata:\n  name: container-kill-sa\n  namespace: testing\n  labels:\n    name: container-kill-sa\n    app.kubernetes.io\/part-of: litmus\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: container-kill-sa\nsubjects:\n  - kind: ServiceAccount\n    name: container-kill-sa\n    namespace: testing <\/code><\/pre>\n<h4><strong>Definici\u00f3n ChaosEngine<\/strong><\/h4>\n<p>Para facilitar la comprensi\u00f3n, hemos dividido en 3 secciones el contenido de un experimento. Pod\u00e9is encontrar todas las definiciones dentro de&nbsp;<em>src\/litmus\/nombre-experimento\/chaos-engine-<\/em>.<em>yaml<\/em><\/p>\n<h5><a id=\"user-content-especificaciones-generales\" href=\"https:\/\/github.com\/angelmaroco\/litmus-chaos-engineering-workshop\/blob\/master\/README.md#especificaciones-generales\" aria-hidden=\"true\"><\/a><strong>Especificaciones generales<\/strong><\/h5>\n<p>En esta secci\u00f3n especificaremos atributos comunes a todos los experimentos. Para este workshop, debido a que estamos realizando los experimentos contra un \u00fanico deployment, el \u00fanico atributo que cambiar\u00e1 entre experimentos es &#8220;chaosServiceAccount&#8221;.<\/p>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosEngine\nmetadata:\n  name: app-sample-chaos # Nombre del chaos-engine\n  namespace: testing     # Namespace de testing\nspec:\n  annotationCheck: \"true\" # Hemos creado una anotaci\u00f3n en nuestro deployment app-sample. Con la propiedad marcada a \"true\" indicamos que aplicarmeos el experimento a este despliegue.\n  engineState: \"active\"   # Activaci\u00f3n\/desactivaci\u00f3n de experimento\n  appinfo:                # En esta secci\u00f3n proporcionamos la informaci\u00f3n de nuestro deployment.\n    appns: \"testing\"      # Namespace donde se localiza\n    applabel: \"app.kubernetes.io\/name=app-sample\" # Etiqueta asociada a nuestro deployment\n    appkind: \"deployment\" # Tipo de recurso (s\u00f3lo admite deployment, lo que afectar\u00e1 a todos los pods)\n  chaosServiceAccount: container-kill-sa # Nombre del service account (creado en el paso anterior)\n  monitoring: true       # si queremos activar la monitorizaci\u00f3n (prometheus o similares)\n  jobCleanUpPolicy: \"delete\" # Permite controlar la limpieza de recursos tras la ejecuci\u00f3n. Especificar \"retain\" para debug.\n <\/code><\/pre>\n<h5><strong>Especificaciones de componentes<\/strong><\/h5>\n<p>En esta secci\u00f3n definiremos las variables de entorno propias de cada experimento. Las variables &#8220;CHAOS_INTERVAL&#8221; y &#8220;TOTAL_CHAOS_DURATION&#8221; son comunes a todos los experimentos.<\/p>\n<pre><code class=\"language-python\">  experiments:\n    - name: container-kill # Nombre del experimento\n      spec:\n        components:\n          env:\n            # Intervalo (segundos) por cada iteraci\u00f3n\n            - name: CHAOS_INTERVAL\n              value: \"10\"\n            # Tiempo total (segundos) que durar\u00e1 el experimento\n            - name: TOTAL_CHAOS_DURATION\n              value: \"60\"\n <\/code><\/pre>\n<h5><strong>Especificaciones de pruebas<\/strong><\/h5>\n<p>En esta secci\u00f3n se informan los atributos para las pruebas de validaci\u00f3n. El resultado del experimento depender\u00e1 del cumplimiento de la validaci\u00f3n especificada.<\/p>\n<p>En el siguiente&nbsp;<a href=\"https:\/\/docs.litmuschaos.io\/docs\/litmus-probe\/\" rel=\"nofollow\">enlace<\/a>&nbsp;podeis consultar los tipos de pruebas disponibles.<\/p>\n<pre><code class=\"language-python\">        probe:\n          - name: \"check-frontend-access-url\" # Nombre de prueba\n            type: \"httpProbe\"                 # Petici\u00f3n de tipo HTTP(S). Alternativas: cmdProbe, k8sProbe, promProbe.\n            httpProbe\/inputs:                  \n              url: \"http:\/\/app-sample.testing.svc.cluster.local\" # URL a validar\n              insecureSkipVerify: false                               # Permitir HTTP sin TLS\n              method:\n                get:                          # Petici\u00f3n tipo GET\n                  criteria: ==                # Criterio a evaluar\n                  responseCode: \"200\"         # Respuesta a evaluar\n            mode: \"Continuous\"                # La prueba se ejecuta de forma continua (alternativas: SoT, EoT, Edge, OnChaos)\n            runProperties:\n              probeTimeout: 5                 # N\u00famero de segundos para timeout en la petici\u00f3n\n              interval: 5                     # Intervalo (segundos) entre re-intentos\n              retry: 1                        # N\u00famero de re-intento antes de dar por fallida la validaci\u00f3n   \n              probePollingInterval: 2         # Intervalo (segundos) entre peticiones\n <\/code><\/pre>\n<h5><strong>Gesti\u00f3n de experimentos<\/strong><\/h5>\n<p>Una de las principales ventajas de litmus es poder definir los experimentos de forma declarativa, lo que nos permite incluir f\u00e1cilmente nuestros gestores de plantillas. Recomendamos el uso de&nbsp;<a href=\"https:\/\/kustomize.io\/\" rel=\"nofollow\">kustomize<\/a>.<\/p>\n<h2>Ejecuci\u00f3n de experimentos<\/h2>\n<h4><strong>Container Kill<\/strong><\/h4>\n<ul>\n<li><strong>Descripci\u00f3n:<\/strong>&nbsp;Aborta la ejecuci\u00f3n del servicio docker dentro de un pod. La selecci\u00f3n del pod es aleatoria.<\/li>\n<li><strong>Informaci\u00f3n oficial del experimento:<\/strong>&nbsp;<a href=\"https:\/\/docs.litmuschaos.io\/docs\/container-kill\/\" rel=\"nofollow\">enlace<\/a><\/li>\n<li><strong>Criterio de entrada:<\/strong>&nbsp;2 pods de app-sample en estado &#8220;Running&#8221;\n<pre>  kubectl get pods -n \"${TESTING_NAMESPACE}\"<\/pre>\n<\/li>\n<\/ul>\n<pre><code class=\"language-python\">  kubectl get pods -n \"${TESTING_NAMESPACE}\"\n  # -----------------------------------------\n  NAME                          READY   STATUS    RESTARTS   AGE\n  app-sample-7ff489dbd5-82ppw   1\/1     Running   0          9h\n  app-sample-7ff489dbd5-jg9vh   1\/1     Running   0          9h\n <\/code><\/pre>\n<ul>\n<li><strong>Par\u00e1metros de entrada experimento:<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">experiments:\n    - name: container-kill\n    spec:\n        components:\n        env:\n            # provide the chaos interval\n            - name: CHAOS_INTERVAL\n            value: \"10\"\n            # provide the total chaos duration\n            - name: TOTAL_CHAOS_DURATION\n            value: \"20\"\n            - name: CONTAINER_RUNTIME\n            value: \"docker\"\n            - name: SOCKET_PATH\n            value: \"\/var\/run\/docker.sock\"\n <\/code><\/pre>\n<ul>\n<li><strong>Hip\u00f3tesis:<\/strong>&nbsp;Tenemos dos pods escuchando por el 80 tras un balanceador. Nuestro deployment tiene readinessProbe con periodSeconds=1 y failureThreshold=1. Si uno de los pods deja de responder, el balanceador deja de enviar tr\u00e1fico a ese pod y debe responder el otro. Hemos establecido el healthcheck del experimento cada 5s (tiempo m\u00e1ximo de respuesta aceptable) atacando directamente contra el balanceador, por lo que no deber\u00edamos de tener p\u00e9rdida de servicio en ning\u00fan momento.<\/li>\n<li><strong>Creaci\u00f3n de SA, Role y RoleBinding<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/kill-container\/kill-container-sa.yaml -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<ul>\n<li><strong>Ejecuci\u00f3n de experimento<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/kill-container\/chaos-engine-kill-container.yaml  -n \"${TESTING_NAMESPACE}\"\n# Awaited -&gt; Pass\/Fail\nwatch -n 1 kubectl get chaosresult app-sample-chaos-container-kill -n \"${TESTING_NAMESPACE}\" -o jsonpath=\"{.status.experimentstatus.verdict}\"\n <\/code><\/pre>\n<ul>\n<li><strong>Observaciones:<\/strong>&nbsp;durante el experimento observamos 2 reinicios de pod con transici\u00f3n &#8220;Running&#8221; -&gt; &#8220;Error&#8221; -&gt; &#8220;Running&#8221;.<\/li>\n<li><strong>Validaci\u00f3n:<\/strong>&nbsp;Peticiones get al balanceador con respuesta 200.<\/li>\n<\/ul>\n<pre><code class=\"language-python\">probe:\n- name: \"check-frontend-access-url\"\n    type: \"httpProbe\"\n    httpProbe\/inputs:\n    url: \"http:\/\/app-sample.testing.svc.cluster.local\"\n    insecureSkipVerify: false\n    method:\n        get:\n        criteria: ==\n        responseCode: \"200\"\n    mode: \"Continuous\"\n    runProperties:\n    probeTimeout: 5\n    interval: 5\n    retry: 1\n    probePollingInterval: 2\n <\/code><\/pre>\n<ul>\n<li><strong>Resultado:<\/strong>&nbsp;resultado &#8220;Pass&#8221; (dos pods en estado &#8220;Running&#8221;, sin p\u00e9rdida de servicio durante la duraci\u00f3n del experimento)<\/li>\n<\/ul>\n<pre><code class=\"language-python\">$ kubectl describe chaosresult app-sample-chaos-container-kill -n \"${TESTING_NAMESPACE}\" \n# --------------------------------------------------------------------------------------\nSpec:\n    Engine:      app-sample-chaos\n    Experiment:  container-kill\nStatus:\n    Experimentstatus:\n        Fail Step:                 N\/A\n        Phase:                     Completed\n        Probe Success Percentage:  100\n        Verdict:                   Pass\nHistory:\n    Failed Runs:   0\n    Passed Runs:   6\n    Stopped Runs:  0\nProbe Status:\n    Name:  check-frontend-access-url\n    Status:\n        Continuous:  Passed ????\n    Type:            httpProbe\nEvents:\n    Type    Reason   Age    From                         Message\n    ----    ------   ----   ----                         -------\n    Normal  Awaited  4m48s  container-kill-5i56m6-4pkxg  experiment: container-kill, Result: Awaited\n    Normal  Pass     4m4s   container-kill-5i56m6-4pkxg  experiment: container-kill, Result: Pass\n$ kubectl get pods -n testing\nNAME                          READY   STATUS    RESTARTS   AGE\napp-sample-6c48f8c4cc-74lvl   1\/1     Running   2          25m\napp-sample-6c48f8c4cc-msdmj   1\/1     Running   0          25m\n <\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/kill-container.png\" title=\"\" alt=\"\"><\/p>\n<ul>\n<li>\n<h4><strong>Pod autoscaler<\/strong><\/h4>\n<ul>\n<li><strong>Descripci\u00f3n:<\/strong>&nbsp;permite escalar las r\u00e9plicas para testear el autoescalado en el nodo.<\/li>\n<li><strong>Informaci\u00f3n oficial del experimento:<\/strong>&nbsp;<a href=\"https:\/\/docs.litmuschaos.io\/docs\/pod-autoscaler\/\" rel=\"nofollow\">enlace<\/a><\/li>\n<li><strong>Criterio de entrada:<\/strong>&nbsp;2 pods de app-sample en estado &#8220;Running&#8221;<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<pre><code class=\"language-python\">  $ kubectl get pods -n \"${TESTING_NAMESPACE}\"\n  # ------------------------------------------\n  NAME                          READY   STATUS    RESTARTS   AGE\n  app-sample-6c48f8c4cc-74lvl   1\/1     Running   2          29m\n  app-sample-6c48f8c4cc-msdmj   1\/1     Running   0          28m\n <\/code><\/pre>\n<ul>\n<li><strong>Par\u00e1metros de entrada experimento:<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">experiments:\n  - name: pod-autoscaler\n    spec:\n      components:\n        env:\n          # set chaos duration (in sec) as desired\n          - name: TOTAL_CHAOS_DURATION\n            value: \"60\"\n          # number of replicas to scale\n          - name: REPLICA_COUNT\n            value: \"10\"\n <\/code><\/pre>\n<ul>\n<li><strong>Hip\u00f3tesis:<\/strong>&nbsp;Disponemos de un HPA con min = 2 y max = 10. Con la ejecuci\u00f3n de este experimento queremos validar que nuestro nodo es capaz de escalar a 10 r\u00e9plicas (el max. establecido en el HPA). Cuando ejecutemos el experimento, se crear\u00e1n 10 r\u00e9plicas y en ning\u00fan momento tendremos p\u00e9rdida de servicio. Nuestro HPA tiene establecido el par\u00e1metro &#8220;&#8211;horizontal-pod-autoscaler-downscale-stabilization&#8221; a 300s, por lo que durante ese intervalo tendremos 10 r\u00e9plicas en estado &#8220;Running&#8221; y transcurrido ese intervalo, volveremos a tener 2 r\u00e9plicas.<\/li>\n<li><strong>Creaci\u00f3n de SA, Role y RoleBinding<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">$ kubectl apply -f src\/litmus\/pod-autoscaler\/pod-autoscaler-sa.yaml -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<ul>\n<li><strong>Ejecuci\u00f3n de experimento<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">$ kubectl apply -f src\/litmus\/pod-autoscaler\/chaos-engine-pod-autoscaler.yaml  -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<ul>\n<li><strong>Observaciones:<\/strong><\/li>\n<li><strong>Validaci\u00f3n:<\/strong>&nbsp;Peticiones get al balanceador con respuesta 200.<\/li>\n<\/ul>\n<pre><code class=\"language-python\">probe:\n- name: \"check-frontend-access-url\"\n    type: \"httpProbe\"\n    httpProbe\/inputs:\n    url: \"http:\/\/app-sample.testing.svc.cluster.local\"\n    insecureSkipVerify: false\n    method:\n        get:\n        criteria: ==\n        responseCode: \"200\"\n    mode: \"Continuous\"\n    runProperties:\n    probeTimeout: 5\n    interval: 5\n    retry: 1\n    probePollingInterval: 2\n <\/code><\/pre>\n<ul>\n<li><strong>Resultado:<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">$ kubectl describe chaosresult app-sample-chaos-pod-autoscaler  -n \"${TESTING_NAMESPACE}\"\n# ----------------------------------------------------------------------------------------\nSpec:\n    Engine:      app-sample-chaos\n    Experiment:  pod-autoscaler\nStatus:\n    Experimentstatus:\n        Fail Step:                 N\/A\n        Phase:                     Completed\n        Probe Success Percentage:  100\n        Verdict:                   Pass\nHistory:\n    Failed Runs:   0\n    Passed Runs:   6\n    Stopped Runs:  0\nProbe Status:\n    Name:  check-frontend-access-url\n    Status:\n        Continuous:  Passed ????\n    Type:            httpProbe\nEvents:\n    Type    Reason   Age    From                         Message\n    ----    ------   ----   ----                         -------\n    Normal  Awaited  4m46s  pod-autoscaler-95wa6x-858jv  experiment: pod-autoscaler, Result: Awaited\n    Normal  Pass     3m32s  pod-autoscaler-95wa6x-858jv  experiment: pod-autoscaler, Result: Pass\n$ kubectl get pods -n testing\n# ---------------------------\nNAME                          READY   STATUS        RESTARTS   AGE\napp-sample-6c48f8c4cc-5kzpg   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-74lvl   0\/1     Running       2          32m\napp-sample-6c48f8c4cc-bflws   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-c5ls8   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-d9zj4   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-f2xnt   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-f7qdl   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-ff84v   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-k29rr   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-l5fqp   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-m587t   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-msdmj   1\/1     Running       0          32m\napp-sample-6c48f8c4cc-n5h6l   0\/1     Completed     0          39s\napp-sample-6c48f8c4cc-qr5nd   0\/1     Completed     0          39s\napp-sample-chaos-runner       0\/1     Completed     0          47s\npod-autoscaler-95wa6x-858jv   0\/1     Completed     0          45s\n <\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/pod-autoscaler.png\" title=\"\" alt=\"\"><\/p>\n<h4><strong>Pod CPU Hog<\/strong><\/h4>\n<ul>\n<li><strong>Descripci\u00f3n:<\/strong>&nbsp;permite consumir recursos de CPU dentro de POD<\/li>\n<li><strong>Informaci\u00f3n oficial del experimento:<\/strong>&nbsp;<a href=\"https:\/\/docs.litmuschaos.io\/docs\/pod-cpu-hog\/\" rel=\"nofollow\">enlace<\/a><\/li>\n<li><strong>Criterio de entrada:<\/strong>&nbsp;2 pods de app-sample en estado &#8220;Running&#8221;<\/li>\n<\/ul>\n<pre><code class=\"language-python\">  kubectl get pods -n \"${TESTING_NAMESPACE}\"\n  # ---------------------------------------\n  NAME                          READY   STATUS    RESTARTS   AGE\n  app-sample-6c48f8c4cc-74lvl   1\/1     Running   2          52m\n  app-sample-6c48f8c4cc-msdmj   1\/1     Running   0          52m\n <\/code><\/pre>\n<ul>\n<li><strong>Par\u00e1metros de entrada experimento:<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">experiments:\n  - name: pod-cpu-hog\n    spec:\n      components:\n        env:\n          #number of cpu cores to be consumed\n          #verify the resources the app has been launched with\n          - name: CPU_CORES\n            value: \"1\"\n          - name: TOTAL_CHAOS_DURATION\n            value: \"60\" # in seconds\n          - name: PODS_AFFECTED_PERC\n            value: \"0\"\n <\/code><\/pre>\n<ul>\n<li><strong>Hip\u00f3tesis:<\/strong>&nbsp;Disponemos de un HPA con min = 2 y max = 10. Con la ejecuci\u00f3n de este experimento queremos validar que nuestro HPA funciona correctamente. Tenemos establecido un targetCPUUtilizationPercentage=50%, lo que quiere decir que si inyectamos consumo de CPU en un pod, el HPA debe establecer el n\u00famero de r\u00e9plicas a 3 (2 min + 1 autoscaler). En ning\u00fan momento debemos tener p\u00e9rdida de servicio. Nuestro HPA tiene establecido el par\u00e1metro &#8220;&#8211;horizontal-pod-autoscaler-downscale-stabilization&#8221; a 300s, por lo que durante ese intervalo tendremos 10 r\u00e9plicas en estado &#8220;Running&#8221; y transcurrido ese intervalo, volveremos a tener 2 r\u00e9plicas.<\/li>\n<li><strong>Creaci\u00f3n de SA, Role y RoleBinding<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/pod-cpu-hog\/pod-cpu-hog-sa.yaml -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<ul>\n<li><strong>Ejecuci\u00f3n de experimento<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/pod-cpu-hog\/chaos-engine-pod-cpu-hog.yaml -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<ul>\n<li><strong>Observaciones:<\/strong>&nbsp;durante el experimento vemos 2 pods en estado &#8220;Runnning&#8221;. Se comienza a inyectar consumo en uno de los POD y se autoescala a 3 r\u00e9plicas. A los 300s se vuelve a tener 2 r\u00e9plicas.<\/li>\n<li><strong>Validaci\u00f3n:<\/strong>&nbsp;Peticiones get al balanceador con respuesta 200.<\/li>\n<\/ul>\n<pre><code class=\"language-python\">probe:\n- name: \"check-frontend-access-url\"\n    type: \"httpProbe\"\n    httpProbe\/inputs:\n    url: \"http:\/\/app-sample.testing.svc.cluster.local\"\n    insecureSkipVerify: false\n    method:\n        get:\n        criteria: ==\n        responseCode: \"200\"\n    mode: \"Continuous\"\n    runProperties:\n    probeTimeout: 5\n    interval: 5\n    retry: 1\n    probePollingInterval: 2\n <\/code><\/pre>\n<ul>\n<li><strong>Resultado:<\/strong>&nbsp;resultado &#8220;Pass&#8221; (tres pods en estado &#8220;Running&#8221;, sin p\u00e9rdida de servicio durante la duraci\u00f3n del experimento)<\/li>\n<\/ul>\n<pre><code class=\"language-python\">$ kubectl describe chaosresult app-sample-chaos-pod-cpu-hog -n \"${TESTING_NAMESPACE}\" \n# -----------------------------------------------------------------------------------\nSpec:\n    Engine:      app-sample-chaos\n    Experiment:  pod-cpu-hog\nStatus:\n    Experimentstatus:\n        Fail Step:                 N\/A\n        Phase:                     Completed\n        Probe Success Percentage:  100\n        Verdict:                   Pass\nHistory:\n    Failed Runs:   0\n    Passed Runs:   6\n    Stopped Runs:  0\nProbe Status:\n    Name:  check-frontend-access-url\n    Status:\n        Continuous:  Passed ????\n    Type:            httpProbe\nEvents:\n    Type    Reason   Age    From                         Message\n    ----    ------   ----   ----                         -------\n    Normal  Awaited  2m23s  pod-cpu-hog-mpen59-zcpr6  experiment: pod-cpu-hog, Result: Awaited\n    Normal  Pass     74s    pod-cpu-hog-mpen59-zcpr6  experiment: pod-cpu-hog, Result: Pass\n$ kubectl get pods -n testing\n  NAME                          READY   STATUS      RESTARTS   AGE\n  app-sample-6c48f8c4cc-74lvl   1\/1     Running     6          46m\n  app-sample-6c48f8c4cc-msdmj   1\/1     Running     0          46m\n  app-sample-5c5575cdb7-hq5gs   1\/1     Running     0          49s\n  app-sample-chaos-runner       0\/1     Completed   0          104s\n  pod-cpu-hog-mpen59-zcpr6      0\/1     Completed   0          103s\n <\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/pod-cpu.png\" title=\"\" alt=\"\"><\/p>\n<h4><strong>Extra &#8211; Otros experimentos<\/strong><\/h4>\n<ul>\n<li><strong>pod-network-loss<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/pod-network-loss\/pod-network-loss-sa.yaml -n \"${TESTING_NAMESPACE}\"\nkubectl apply -f src\/litmus\/pod-network-loss\/chaos-engine-pod-network-loss.yaml  -n \"${TESTING_NAMESPACE}\"\nkubectl describe chaosresult app-sample-chaos-pod-network-loss -n \"${TESTING_NAMESPACE}\"\n <\/code><\/pre>\n<ul>\n<li><strong>pod-memory-hog<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/pod-memory\/pod-memory-hog-sa.yaml -n \"${TESTING_NAMESPACE}\"\nkubectl apply -f src\/litmus\/pod-memory\/chaos-engine-pod-memory-hog.yaml  -n \"${TESTING_NAMESPACE}\"\nkubectl describe chaosresult app-sample-chaos-pod-memory-hog -n \"${TESTING_NAMESPACE}\" \n <\/code><\/pre>\n<ul>\n<li><strong>pod-delete<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/pod-delete\/pod-delete-sa.yaml -n \"${TESTING_NAMESPACE}\"\nkubectl apply -f src\/litmus\/pod-delete\/chaos-engine-pod-delete.yaml -n \"${TESTING_NAMESPACE}\"\nkubectl describe chaosresult app-sample-chaos-pod-delete -n \"${TESTING_NAMESPACE}\" \n <\/code><\/pre>\n<h3>Planificaci\u00f3n de experimentos<\/h3>\n<p>Litmus soporta el uso de planificaciones de experimentos. Dispone de las siguientes opciones:<\/p>\n<ul>\n<li><strong>Inmediato<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosSchedule\nmetadata:\n  name: schedule-nginx\nspec:\n  schedule:\n    now: true\n  engineTemplateSpec:\n    appinfo:\n      appns: testing\n      applabel: app.kubernetes.io\/name=app-sample\n      appkind: deployment\n    annotationCheck: 'true'\n <\/code><\/pre>\n<ul>\n<li><strong>Timestamp espec\u00edfico<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosSchedule\nmetadata:\n  name: schedule-nginx\nspec:\n  schedule:\n    once:\n      #should be modified according to current UTC Time\n      executionTime: \"2020-05-12T05:47:00Z\" \n  engineTemplateSpec:\n    appinfo:\n      appns: testing\n      applabel: app.kubernetes.io\/name=app-sample\n      appkind: deployment\n    annotationCheck: 'true'\n <\/code><\/pre>\n<ul>\n<li><strong>Repeticiones<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosSchedule\nmetadata:\n  name: schedule-nginx\nspec:\n  schedule:\n    repeat:\n      properties:\n         #format should be like \"10m\" or \"2h\" accordingly for minutes or hours\n        minChaosInterval: \"2m\"  \n  engineTemplateSpec:\n    appinfo:\n      appns: testing\n      applabel: app.kubernetes.io\/name=app-sample\n      appkind: deployment\n    annotationCheck: 'true'\n <\/code><\/pre>\n<ul>\n<li><strong>Repeticiones entre un rango de fechas<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosSchedule\nmetadata:\n  name: schedule-nginx\nspec:\n  schedule:\n    repeat:\n      timeRange:\n        #should be modified according to current UTC Time\n        startTime: \"2020-05-12T05:47:00Z\"   \n        endTime: \"2020-09-13T02:58:00Z\"   \n      properties:\n        #format should be like \"10m\" or \"2h\" accordingly for minutes and hours\n        minChaosInterval: \"2m\"  \n  engineTemplateSpec:\n    appinfo:\n      appns: testing\n      applabel: app.kubernetes.io\/name=app-sample\n      appkind: deployment\n    annotationCheck: 'true'\n <\/code><\/pre>\n<ul>\n<li><strong>Repeticiones con una fecha de finalizaci\u00f3n<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosSchedule\nmetadata:\n  name: schedule-nginx\nspec:\n  schedule:\n    repeat:\n      timeRange:\n        #should be modified according to current UTC Time\n        endTime: \"2020-09-13T02:58:00Z\"   \n      properties:\n        #format should be like \"10m\" or \"2h\" accordingly for minutes and hours\n        minChaosInterval: \"2m\"   \n  engineTemplateSpec:\n    appinfo:\n      appns: testing\n      applabel: app.kubernetes.io\/name=app-sample\n      appkind: deployment\n    annotationCheck: 'true'\n <\/code><\/pre>\n<ul>\n<li><strong>Repeticiones desde una fecha de inicio (ejecuciones indefinidas)<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosSchedule\nmetadata:\n  name: schedule-nginx\nspec:\n  schedule:\n    repeat:\n      timeRange:\n        #should be modified according to current UTC Time\n        startTime: \"2020-05-12T05:47:00Z\"   \n      properties:\n         #format should be like \"10m\" or \"2h\" accordingly for minutes and hours\n        minChaosInterval: \"2m\" \n  engineTemplateSpec:\n    appinfo:\n      appns: testing\n      applabel: app.kubernetes.io\/name=app-sample\n      appkind: deployment\n    annotationCheck: 'true'\n <\/code><\/pre>\n<ul>\n<li><strong>Ejecuci\u00f3n entre horas con frecuencia<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosSchedule\nmetadata:\n  name: schedule-nginx\nspec:\n  schedule:\n    repeat:\n      properties:\n        #format should be like \"10m\" or \"2h\" accordingly for minutes and hours\n        minChaosInterval: \"2m\"   \n      workHours:\n        # format should be &lt;starting-hour-number&gt;-&lt;ending-hour-number&gt;(inclusive)\n        includedHours: 0-12\n  engineTemplateSpec:\n    appinfo:\n      appns: testing\n      applabel: app.kubernetes.io\/name=app-sample\n      appkind: deployment\n    annotationCheck: 'true'\n <\/code><\/pre>\n<ul>\n<li><strong>Ejecuciones peri\u00f3dicas en d\u00edas espec\u00edficos<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-python\">apiVersion: litmuschaos.io\/v1alpha1\nkind: ChaosSchedule\nmetadata:\n  name: schedule-nginx\nspec:\n  schedule:\n    repeat:\n      properties:\n        #format should be like \"10m\" or \"2h\" accordingly for minutes and hours\n        minChaosInterval: \"2m\"   \n      workDays:\n        includedDays: \"Mon,Tue,Wed,Sat,Sun\"\n  engineTemplateSpec:\n    appinfo:\n      appns: testing\n      applabel: app.kubernetes.io\/name=app-sample\n      appkind: deployment\n    annotationCheck: 'true'\n <\/code><\/pre>\n<h3>LitmusChaos + Load Test Performance con Apache Jmeter<\/h3>\n<p>Hasta el momento hemos realizado pruebas para validar c\u00f3mo se comporta nuestro nodo de k8s bajo escenarios ideales, sin carga en el sistema por parte de los usuarios finales de la aplicaci\u00f3n.<\/p>\n<p>Por lo general, tendremos definidos SLIs\/SLOs\/SLAs los cuales hay que garantizar que cumplimos bajo cualquier eventualidad y para ello debemos de disponer de las herramientas adecuadas. En este caso, Litmus +&nbsp;<a href=\"https:\/\/jmeter.apache.org\/\" rel=\"nofollow\">Apache Jmeter<\/a>&nbsp;nos facilitar\u00e1n la tarea de simular m\u00faltiples escenarios de concurrencia con inyecci\u00f3n de anomal\u00edas en el sistema. Durante esta fase de pruebas es posible que tengamos que realizar ajustes de dimensionamiento, modificar alguna pol\u00edtica de escalado o incluso que identifiquemos cuellos de botella y los equipos de desarrollo tengan que ajustar alg\u00fan componente.<\/p>\n<p>Para no desvirtuar el objetivo del workshop con la definici\u00f3n de SLIs\/SLOs\/SLAs (m\u00e1s info&nbsp;<a href=\"https:\/\/cloud.google.com\/blog\/products\/devops-sre\/sre-fundamentals-slis-slas-and-slos\" rel=\"nofollow\">aqu\u00ed<\/a>), \u00fanicamente vamos a utilizar la m\u00e9trica &#8220;Ratio de error&#8221;, la cual vamos a establecer en &lt; 2,00%.<\/p>\n<p>Planteamos un escenario ficticio donde nuestra aplicaci\u00f3n tiene 200 usuarios concurrentes durante la mayor parte del tiempo de servicio.<\/p>\n<p>Procedemos a descargar el binario de JMeter y unos complementos para la visualizaci\u00f3n de gr\u00e1ficas:<\/p>\n<p>JMeter requiere Java JRE. En el caso de no estar disponible en el sistema, puedes realizar la instalaci\u00f3n de [OpenJDK](https:\/\/adoptopenjdk.net\/index.html). En caso contrario, omite este paso.<\/p>\n<pre><code class=\"language-python\">curl -L https:\/\/ftp.cixug.es\/apache\/\/jmeter\/binaries\/apache-jmeter-5.4.1.tgz --output \/tmp\/apache-jmeter.tgz\ntar zxvf \/tmp\/apache-jmeter.tgz &amp;&amp; mv apache-jmeter-5.4.1 apache-jmeter\n# install plugins-manager\ncurl -L https:\/\/jmeter-plugins.org\/get\/ --output apache-jmeter\/lib\/ext\/jmeter-plugins-manager-1.6.jar\n# install bzm - Concurrency Thread Group\ncurl -L https:\/\/repo1.maven.org\/maven2\/kg\/apc\/jmeter-plugins-casutg\/2.9\/jmeter-plugins-casutg-2.9.jar --output apache-jmeter\/lib\/ext\/jmeter-plugins-casutg-2.9.jar\ncurl -L https:\/\/repo1.maven.org\/maven2\/kg\/apc\/jmeter-plugins-cmn-jmeter\/0.6\/jmeter-plugins-cmn-jmeter-0.6.jar --output apache-jmeter\/lib\/jmeter-plugins-cmn-jmeter-0.6.jar\ncurl -L https:\/\/repo1.maven.org\/maven2\/kg\/apc\/cmdrunner\/2.2\/cmdrunner-2.2.jar --output apache-jmeter\/lib\/cmdrunner-2.2.jar\ncurl -L https:\/\/repo1.maven.org\/maven2\/net\/sf\/json-lib\/json-lib\/2.4\/json-lib-2.4.jar --output apache-jmeter\/lib\/json-lib-2.4-jdk15.jar\ncurl -L https:\/\/repo1.maven.org\/maven2\/kg\/apc\/jmeter-plugins-graphs-basic\/2.0\/jmeter-plugins-graphs-basic-2.0.jar --output apache-jmeter\/lib\/ext\/jmeter-plugins-graphs-basic-2.0.jar\ncurl -L https:\/\/repo1.maven.org\/maven2\/kg\/apc\/jmeter-plugins-graphs-additional\/2.0\/jmeter-plugins-graphs-additional-2.0.jar --output apache-jmeter\/lib\/ext\/jmeter-plugins-graphs-additional-2.0.jar\n# Get url service\nurl=$(minikube service app-sample --url -n \"${TESTING_NAMESPACE}\")\nHOST_APP_SAMPLE=$(echo ${url} | cut -d\/ -f3 | cut -d: -f1)\nPORT_APP_SAMPLE=$(echo ${url} | cut -d: -f3)\n <\/code><\/pre>\n<p>Vamos a validar que con el dimensionamiento actual cumplimos con los requisitos. Durante 60 segundos, ejecutamos 200 peticiones concurrentes, lo que se traduce en 12.000 peticiones. La petici\u00f3n ser\u00e1 de tipo &#8220;GET&#8221; por el puerto 80 del balanceador.<\/p>\n<p>Este es el aspecto que tiene la GUI de JMeter con el plan de pruebas.<\/p>\n<pre><code class=\"language-python\">TARGET_RATE=200\nRAMP_UP_TIME=60\nRAMP_UP_STEPS=1\n# GUI mode\nbash apache-jmeter\/bin\/jmeter.sh -t src\/jmeter\/litmus-k8s-workshop.jmx -f -l apache-jmeter\/logs\/result.jtl -j apache-jmeter\/logs\/jmeter.log -Jhost=${HOST_APP_SAMPLE} -Jport=${PORT_APP_SAMPLE} -Jtarget_rate=${TARGET_RATE} -Jramp_up_time=${RAMP_UP_TIME} -Jramp_up_steps=${RAMP_UP_STEPS}\n <\/code><\/pre>\n<p><img decoding=\"async\" width=\"1024\" height=\"581\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-1024x581-1.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-1024x581-1.png 1024w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-1024x581-1-300x170.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-1024x581-1-768x436.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"><\/p>\n<p>Nuestro dimensionamiento base son dos r\u00e9plicas de nuestro servicio app-sample:<\/p>\n<pre><code class=\"language-python\">kubectl get pods -n \"${TESTING_NAMESPACE}\"\n# ----------------------------------------\nNAME                         READY   STATUS    RESTARTS   AGE\napp-sample-d9d578cfb-55flr   1\/1     Running   8          3h1m\napp-sample-d9d578cfb-klmxn   1\/1     Running   0          3h2m\n <\/code><\/pre>\n<p>Ejecutamos el plan de pruebas sin GUI:<\/p>\n<pre><code class=\"language-python\">TARGET_RATE=200\nRAMP_UP_TIME=60\nRAMP_UP_STEPS=1\nbash apache-jmeter\/bin\/jmeter.sh -n -t src\/jmeter\/litmus-k8s-workshop.jmx -f -l apache-jmeter\/logs\/result.jtl -j apache-jmeter\/logs\/jmeter.log -Jhost=${HOST_APP_SAMPLE} -Jport=${PORT_APP_SAMPLE} -Jtarget_rate=${TARGET_RATE} -Jramp_up_time=${RAMP_UP_TIME} -Jramp_up_steps=${RAMP_UP_STEPS}\nrm -rf apache-jmeter\/logs\/report &amp;&amp; bash apache-jmeter\/bin\/jmeter.sh -g apache-jmeter\/logs\/result.jtl -o apache-jmeter\/logs\/report\n <\/code><\/pre>\n<p>En la ruta &#8220;.\/apache-jmeter\/logs\/report\/index.html&#8221; pod\u00e9is ver un dashboard con los resultados.<\/p>\n<p>Hemos realizado 12000 peticiones con 200 usuarios concurrentes durante 60s. Estos son los resultados:<\/p>\n<ul>\n<li>Ratio de error: 0.00%<\/li>\n<\/ul>\n<p><img decoding=\"async\" width=\"1024\" height=\"481\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-001-1024x481-1.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-001-1024x481-1.png 1024w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-001-1024x481-1-300x141.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-001-1024x481-1-768x361.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"><\/p>\n<p>Vamos a realizar la misma prueba pero inyectando disrupcci\u00f3n de red en uno de los pods, lo que provocar\u00e1 que deje de responder (estado CrashLoopBackOff) y s\u00f3lo tengamos disponible una r\u00e9plica.<\/p>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/pod-network-loss\/pod-network-loss-sa.yaml -n \"${TESTING_NAMESPACE}\"\nkubectl apply -f src\/litmus\/pod-network-loss\/chaos-engine-pod-network-loss.yaml  -n \"${TESTING_NAMESPACE}\"\nTARGET_RATE=200\nRAMP_UP_TIME=60\nRAMP_UP_STEPS=1\nbash apache-jmeter\/bin\/jmeter.sh -n -t src\/jmeter\/litmus-k8s-workshop.jmx -f -l apache-jmeter\/logs\/result.jtl -j apache-jmeter\/logs\/jmeter.log -Jhost=${HOST_APP_SAMPLE} -Jport=${PORT_APP_SAMPLE} -Jtarget_rate=${TARGET_RATE} -Jramp_up_time=${RAMP_UP_TIME} -Jramp_up_steps=${RAMP_UP_STEPS}\nrm -rf apache-jmeter\/logs\/report &amp;&amp; bash apache-jmeter\/bin\/jmeter.sh -g apache-jmeter\/logs\/result.jtl -o apache-jmeter\/logs\/report\n <\/code><\/pre>\n<p><img decoding=\"async\" width=\"1024\" height=\"509\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-002-1024x509-1.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-002-1024x509-1.png 1024w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-002-1024x509-1-300x149.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-002-1024x509-1-768x382.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"><\/p>\n<p><strong>\u00bfQu\u00e9 ha sucedido?<\/strong><\/p>\n<p>Al inyectar el experimento, uno de los pods ha dejado de responder. Si nos fijamos en la definici\u00f3n del&nbsp;<em>deployment app-sample<\/em>, tenemos un&nbsp;<em>livenessProbe<\/em>&nbsp;cuya propiedad&nbsp;<em>periodSeconds<\/em>&nbsp;est\u00e1 establecida a 5 segundos y&nbsp;<em>failureThreshold<\/em>&nbsp;a 1 intento. Seg\u00fan nuestra configuraci\u00f3n, el balanceador env\u00eda el 50% aprox. del tr\u00e1fico a cada uno de los pods. Durante 5 segundos tenemos que el pod al que hemos inyectado una disrupci\u00f3n de red mediante el experimento no responde, lo que se traduce en error en la petici\u00f3n. Transcurridos los 5 segundos, el balanceador deja de enviar tr\u00e1fico a ese pod y s\u00f3lo tendremos un pod recibiendo peticiones.<\/p>\n<p>Ten\u00edamos establecido un requisito que nuestro servicio no puede superar el 2% de errores bajo ning\u00fan escenario y hemos obtenido un 5,03% (603 peticiones err\u00f3neas), por lo que debemos realizar alg\u00fan ajuste para cumplir el objetivo.<\/p>\n<p><strong>\u00bfCu\u00e1l es el resultado del experimento?<\/strong><\/p>\n<pre><code class=\"language-python\">kubectl describe chaosresult app-sample-chaos-pod-network-loss  -n \"${TESTING_NAMESPACE}\"\n#-------------------------\nEvents:\nType    Reason   Age    From                           Message\n----    ------   ----   ----                           -------\nNormal  Awaited  4m16s  pod-network-loss-uf6hms-sk47z  experiment: pod-network-loss, Result: Awaited\nNormal  Pass     2m23s  pod-network-loss-uf6hms-sk47z  experiment: pod-network-loss, Result: Pass\n <\/code><\/pre>\n<p>Aunque nuestro requisito de ratio de error &lt; 2,00% no se cumple, el experimento termina con resultado &#8220;Pass&#8221;. Esto es debido a que Litmus tiene como criterio de salida &#8220;Pass&#8221; si el pod vuelve a estar disponible, lo cual se cumple. Aqu\u00ed estamos haciendo uso de litmus para inyectar errores en el sistema.<\/p>\n<p><strong>\u00bfC\u00f3mo podemos conseguir reducir el ratio de error?<\/strong><\/p>\n<p>\u00danicamente con fines ilustrativos, para resolver el problema que nos ocupa, vamos a incrementar el n\u00famero de r\u00e9plicas a 4 en el HorizontalPodAutoscaler y en el&nbsp;<em>deployment<\/em>&nbsp;disminuir el valor de la propiedad&nbsp;<em>periodSeconds<\/em>&nbsp;de 5s a 2s. Con esto pasamos a distribuir el 25% del tr\u00e1fico a cada pod y adem\u00e1s, el tiempo que el pod afectado por la disrupci\u00f3n de tr\u00e1fico pasa de 5s a 2s, lo que debe traducirse en una reducci\u00f3n del ratio de error.<\/p>\n<p>\u2139\ufe0f&nbsp;Nuestro sistema debe estar dise\u00f1ado para adaptarse a la demanda en base a m\u00e9tricas (CPU, memoria, peticiones por segundo, latencia, I\/O, etc.) siempre manteniendo los m\u00ednimos recursos activos. Con la expansi\u00f3n de servicios gestionados de kubernetes en los principales proveedores cloud (EKS\/GKE\/AKS), disponemos de m\u00faltiples estrategias para conseguir dicho objetivo.<\/p>\n<pre><code class=\"language-python\">kubectl edit deployment app-sample -n \"${TESTING_NAMESPACE}\" \nkubectl edit HorizontalPodAutoscaler app-sample-ha -n \"${TESTING_NAMESPACE}\" \n <\/code><\/pre>\n<p>Volvemos a ejecutar nuestro test:<\/p>\n<pre><code class=\"language-python\">kubectl apply -f src\/litmus\/pod-network-loss\/pod-network-loss-sa.yaml -n \"${TESTING_NAMESPACE}\"\nkubectl apply -f src\/litmus\/pod-network-loss\/chaos-engine-pod-network-loss.yaml  -n \"${TESTING_NAMESPACE}\"\nTARGET_RATE=200\nRAMP_UP_TIME=60\nRAMP_UP_STEPS=1\nbash apache-jmeter\/bin\/jmeter.sh -n -t src\/jmeter\/litmus-k8s-workshop.jmx -f -l apache-jmeter\/logs\/result.jtl -j apache-jmeter\/logs\/jmeter.log -Jhost=${HOST_APP_SAMPLE} -Jport=${PORT_APP_SAMPLE} -Jtarget_rate=${TARGET_RATE} -Jramp_up_time=${RAMP_UP_TIME} -Jramp_up_steps=${RAMP_UP_STEPS}\nrm -rf apache-jmeter\/logs\/report &amp;&amp; bash apache-jmeter\/bin\/jmeter.sh -g apache-jmeter\/logs\/result.jtl -o apache-jmeter\/logs\/report\n <\/code><\/pre>\n<p><img decoding=\"async\" width=\"1024\" height=\"509\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-003-1024x509-1.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-003-1024x509-1.png 1024w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-003-1024x509-1-300x149.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/jmeter-gui-003-1024x509-1-768x382.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"><\/p>\n<p>Como podemos observar, nuestros cambios han provocado disminuir nuestro ratio de error a 1,60%, por lo que conseguimos cumplir nuestro objetivo de &lt; 2,00%.<\/p>\n<h3>Litmus UI Portal<\/h3>\n<p>Litmus dispone de un portal para poder realizar experimentos sin necesidad de utilizar la consola. Dispone de las siguientes funcionalidades:<\/p>\n<ul>\n<li>Gesti\u00f3n de workflows: dispone de todos los experimentos pre-cargados listos para ejecutar en tu k8s.<\/li>\n<li>MyHubs: permite conectar a repositorios p\u00fablicos\/privados para hacer uso de tus propios experimentos.<\/li>\n<li>Analytics: permite visualizar las ejecuciones de tus experimentos, as\u00ed como estad\u00edsticas sobre los mismos. Adem\u00e1s, permite conectar a otros DataSources como Prometheus.<\/li>\n<li>Gesti\u00f3n de equipos y usuarios.<\/li>\n<\/ul>\n<pre><code class=\"language-python\"># install litmus portal\nkubectl apply -f src\/litmus\/portal\/portal.yaml\nminikube service litmusportal-frontend-service -n  ${LITMUS_NAMESPACE} &gt; \/dev\/null &amp;\n <\/code><\/pre>\n<p><img decoding=\"async\" width=\"1024\" height=\"438\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/litmus-portal-1024x438-1.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/litmus-portal-1024x438-1.png 1024w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/litmus-portal-1024x438-1-300x128.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2021\/07\/litmus-portal-1024x438-1-768x329.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\"><\/p>\n<h3>Gu\u00eda Litmus para desarrolladores<\/h3>\n<p>En la actualidad, litmus dispone de 53 experimentos a trav\u00e9s de&nbsp;<a href=\"https:\/\/hub.litmuschaos.io\/\" rel=\"nofollow\">Litmus ChaosHub<\/a>. Est\u00e1n desarrollados principalmente en Go, aunque disponen de una SDK para python y ansible.<\/p>\n<p>Los experimentos tienen una estructura bien definida (pre-checks, chaos-injection, litmus-probes, post-checks y result-updates) y es viable desarrollar experimentos que se ajusten a tus necesidades.<\/p>\n<p>En este&nbsp;<a href=\"https:\/\/docs.litmuschaos.io\/docs\/devguide\/\" rel=\"nofollow\">enlace<\/a>&nbsp;encontrar\u00e9is toda la informaci\u00f3n para desarrolladores.<\/p>\n<h3>Consideraciones finales<\/h3>\n<p>Debemos asumir que nuestro sistema no va a ser 100% tolerante a fallos pero ello no implica que pongamos todos los medios para minimizar los riesgos y en caso de producirse el desastre, lo hagamos de una forma relativamente controlada. La clave del \u00e9xito pasa por aplicar las pr\u00e1cticas de ingenier\u00eda del caos en fases tempranas del desarrollo, conocer las particularidades de la infraestructura donde ejecuta y disponer de herramientas adecuadas para automatizar las pruebas.<\/p>\n<p>Un factor importante es dimensionar los esfuerzos en base a la criticidad del servicio que presta nuestro sistema: el esfuerzo en validar la resiliencia de un portal con informaci\u00f3n para empleados con 100 usuarios potenciales cuyo SLA es del 98% difiere mucho de una aplicaci\u00f3n bancaria que realiza operaciones financieras a miles de usuarios concurrentes cuyo SLA es del 99.9XX%. En ambos casos el \u00fanico m\u00e9todo para verificar el cumplimiento del SLA es mediante test de resiliencia pero existe una notable diferencia respecto al esfuerzo que deber\u00edamos dedicar.<\/p>\n<p>En este workshop nos hemos centrado en Litmus y Kubernetes pero cabe recordar que dependiendo del sistema que estemos desarrollando, tengamos que complementar nuestras pruebas con otras herramientas, principalmente las enfocadas a la inyecci\u00f3n de fallos sobre infraestructura (<a href=\"https:\/\/github.com\/dastergon\/awesome-chaos-engineering\">+ info<\/a>).<\/p>\n<h3>Referencias<\/h3>\n<ul>\n<li><a href=\"https:\/\/litmuschaos.io\/\" rel=\"nofollow\">Litmus official web<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/litmuschaos\/litmu\">Litmus GitHub<\/a><\/li>\n<li><a href=\"https:\/\/principlesofchaos.org\/\" rel=\"nofollow\">Principles of Chaos Engineering<\/a><\/li>\n<li><a href=\"https:\/\/www.gremlin.com\/community\/tutorials\/chaos-engineering-the-history-principles-and-practice\/\" rel=\"nofollow\">Chaos Engineering: the history, principles and practice<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dastergon\/awesome-chaos-engineering\">Awesome Chaos Engineering<\/a><\/li>\n<li><a href=\"https:\/\/cloud.google.com\/blog\/products\/devops-sre\/sre-fundamentals-sli-vs-slo-vs-sla\" rel=\"nofollow\">SRE Fundamentals &#8211; Google<\/a><\/li>\n<\/ul>\n<h3>Licencia<\/h3>\n<p>Este workshop est\u00e1 licenciado bajo MIT (ver <a href=\"https:\/\/github.com\/angelmaroco\/litmus-chaos-engineering-workshop\/blob\/master\/LICENSE\">LICENSE<\/a>&nbsp;para m\u00e1s detalle).<\/p>\n<h6><strong>Navegaci\u00f3n<\/strong><\/h6>\n<p><a href=\"\/#introduccion\">Introducci\u00f3n<\/a><\/p>\n<p><a href=\"\/#objetivos\">Objetivos del workshop<\/a><\/p>\n<p><a href=\"\/#consola\">Preparaci\u00f3n de consola<\/a><\/p>\n<p><a href=\"\/#clonar\">Clonaci\u00f3n de repositorio<\/a><\/p>\n<p><a href=\"\/#minikube\">Creaci\u00f3n de entorno de pruebas K8s con minikube<\/a><\/p>\n<p><a href=\"\/#namespaces\">Creaci\u00f3n de namespaces K8s<\/a><\/p>\n<p><a href=\"\/#test\">Despliegue de aplicaci\u00f3n de test<\/a><\/p>\n<p><a href=\"\/#chaos\">Despliegue&nbsp;<em>Chaos Experiments<\/em><\/a><\/p>\n<p><a href=\"\/#grafana\">Despliegue servicios monitorizaci\u00f3n: Prometheus + Grafana<\/a><\/p>\n<p><a href=\"\/#litmuschaos\">Creaci\u00f3n de anotaci\u00f3n &#8220;litmuschaos&#8221;<\/a><\/p>\n<p><a href=\"\/#detalle\">Detalle componentes de un experimento<\/a><\/p>\n<p><a href=\"\/#experimentos\">Ejecuci\u00f3n de experimentos<\/a><\/p>\n<p><a href=\"\/#plan\">Planificaci\u00f3n de experimentos<\/a><\/p>\n<p><a href=\"\/#apache\">LitmusChaos +&nbsp;<em>Load Test Performance<\/em>&nbsp;con Apache Jmeter<\/a><\/p>\n<p><a href=\"\/#portal\">Litmus UI Portal<\/a><\/p>\n<p><a href=\"\/#guia\">Gu\u00eda Litmus para desarrolladores<\/a><\/p>\n<p><a href=\"\/#finales\">Consideraciones finales<\/a><\/p>\n<p><a href=\"\/#referencias\">Referencias<\/a><\/p>\n<p><a href=\"\/#licencia\">Licencia<\/a><\/p>\n<p><a href=\"\/#autor\">Autor<\/a><\/p>\n<h5>\u00bfQuieres saber m\u00e1s de lo que ofrecemos y ver otros casos de \u00e9xito?<\/h5>\n<p><a href=\"\/\" role=\"button\"><br \/>\nDESCUBRE BLUETAB<br \/>\n<\/a><br \/>\nShare on twitter<br \/>\nShare on linkedin<\/p>\n<figure><a href=\"https:\/\/www.linkedin.com\/in\/elipajares\/\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-150x150.jpg\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-150x150.jpg 150w, https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-300x300.jpg 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-768x768.jpg 768w, https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco-75x75.jpg 75w, https:\/\/bluetab.net\/wp-content\/uploads\/2020\/11\/Angel-Maroco.jpg 800w\" sizes=\"(max-width: 150px) 100vw, 150px\"><\/a><\/figure>\n<p>\u00c1ngel Maroco<br \/>\nAWS Cloud Architect<\/p>\n<p><strong><a href=\"https:\/\/www.linkedin.com\/in\/%C3%A1ngel-maroco-85a0807b\/\">\u00c1ngel Maroco<\/a><\/strong> llevo en el sector IT m\u00e1s de una d\u00e9cada, iniciando mi carrera profesional con el desarrollo web, pasando una buena etapa en distintas plataformas informacionales en entornos bancarios y los \u00faltimos 5 a\u00f1os dedicado al dise\u00f1o de soluciones en entornos AWS.<\/p>\n<p>En la actualidad, compagino mi papel de arquitecto junto al de responsable de la&nbsp;<a href=\"https:\/\/www.linkedin.com\/feed\/hashtag\/?keywords=cloudpractice\">P\u0155actica Cloud<\/a>&nbsp;\/bluetab, cuya misi\u00f3n es impulsar la cultura Cloud dentro de la compa\u00f1\u00eda.<\/p>\n<p><b>SOLUCIONES, <\/b>SOMOS EXPERTOS<\/p>\n<p><a href=\"\/soluciones\/data-strategy\/\"><\/a><\/p>\n<p><a href=\"\/soluciones\/data-strategy\/\"><\/p>\n<h5>\n\t\t\t\t\t\tDATA STRATEGY<\/h5>\n<p><\/a><a href=\"\/soluciones\/data-strategy\/\">\t\t\t\t\t\t<\/a><br \/>\n<a href=\"\/soluciones\/data-fabric\/\"><\/a><\/p>\n<p><a href=\"\/soluciones\/data-fabric\/\"><\/p>\n<h5>\n\t\t\t\t\t\tDATA FABRIC<\/h5>\n<p><\/a><a href=\"\/soluciones\/data-fabric\/\">\t\t\t\t\t\t<\/a><br \/>\n<a href=\"\/soluciones\/augmented-analytics\/\"><\/a><\/p>\n<p><a href=\"\/soluciones\/augmented-analytics\/\"><\/p>\n<h5>\n\t\t\t\t\t\tAUGMENTED ANALYTICS<\/h5>\n<p><\/a><a href=\"\/soluciones\/augmented-analytics\/\">\t\t\t\t\t\t<\/a><\/p>\n<p>Te puede interesar<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Workshop Ingenier\u00eda del caos sobre Kubernetes con Litmus \u00c1ngel Maroco AWS Cloud Architect Share on twitter Share on linkedin LitmusChaos nace con el objetivo de ayudar a desarrolladores y SREs (Site Reliability Engineering ) de Kubernetes a identificar puntos d\u00e9biles y mejorar la resiliencia de sus aplicaciones\/plataformas proporcionando un marco de trabajo completo. Sus principales [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":20785,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"elementor_header_footer","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7,29,30],"tags":[],"class_list":["post-10574","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-es","category-practices-en","category-tech-en"],"acf":[],"jetpack_featured_media_url":"https:\/\/bluetab.es\/wp-content\/uploads\/2021\/07\/10.png","_links":{"self":[{"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/posts\/10574","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/comments?post=10574"}],"version-history":[{"count":0,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/posts\/10574\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/media\/20785"}],"wp:attachment":[{"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/media?parent=10574"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/categories?post=10574"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/tags?post=10574"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}