Ayudándote a sobresalir usando low code en equipos distribuidos y programación paralela
La mayoría de las empresas están explorando el desarrollo low-code/no-code ahora que lo más importante es lograr agilidad en los artefactos tecnológicos desde diferentes perspectivas (desarrollo, implementación y operación).
Los beneficios de esta forma de trabajar hacen que sea casi una decisión obvia para la mayoría de las empresas. Ya los cubrimos en un artículo anterior. Échale un vistazo si aún no lo has leído.
Pero sabemos que todas las cosas nuevas vienen con sus propios desafíos que necesitamos abordar y dominar para liberar todos los beneficios que estos nuevos paradigmas o tecnologías están proporcionando. Al igual que con la arquitectura nativa de la nube, necesitamos ser capaces de adaptarnos.
A veces no es la cultura lo que necesitamos cambiar. A veces la tecnología y las herramientas también necesitan evolucionar para abordar esos desafíos y ayudarnos en ese viaje. Y así es como Visual Diff cobró vida.
Cuando desarrollas usando un enfoque low-code, todo el proceso de desarrollo es más fácil. Necesitas combinar diferentes bloques que realizan la lógica que necesitas, y todo es más simple que un montón de líneas de código.
Enfoque de desarrollo low-code usando TIBCO BusinessWorks.
Pero también necesitamos gestionar todos estos artefactos en un repositorio donde todos ellos están enfocados en el desarrollo de código fuente. Eso significa que cuando trabajas con esas herramientas al final, no estás trabajando con un “enfoque low-code” sino más bien con un enfoque de código fuente. Cosas como fusionar diferentes ramas y mirar el historial de versiones para conocer los cambios son complejas.
Y son complejas porque son realizadas por el propio repositorio, que está enfocado en los cambios de archivos y el código fuente que cambia. Pero uno de los grandes beneficios del desarrollo low-code es que el desarrollador no necesita estar al tanto del código fuente generado como parte de la actividad visual, más rápida. Entonces, ¿cómo podemos resolver eso? ¿Qué podemos usar para resolver eso?
Las tecnologías low-code necesitan avanzar para tomar la delantera aquí. Por ejemplo, esto es lo que TIBCO BusinessWorks ha hecho con el lanzamiento de su capacidad Visual Diff.
Entonces, todavía tienes tu integración con tu repositorio de código fuente. Puedes hacer todos los procesos y actividades que usualmente necesitas hacer en este tipo de desarrollo distribuido paralelo. Aún así, también puedes ver todas esas actividades desde una perspectiva “low-code”.
Eso significa que cuando estoy echando un vistazo al historial de versiones, puedo ver los artefactos visuales que han sido modificados. Las actividades añadidas o eliminadas se muestran allí de una manera significativa para el desarrollo low-code. Eso cierra el ciclo sobre cómo los desarrollos low-code pueden aprovechar todas las ventajas de los repositorios de código fuente modernos y sus flujos (GitFlow, GitHub Flow, One Flow, etc.) así como las ventajas de la perspectiva low-code.
Digamos que hay dos opciones con las que puedes ver cómo ha cambiado una aplicación. Una es el enfoque tradicional y la otra usa el Visual Diff:
Opción A: Visual Diff de tus procesosOpción B: Mismos procesos pero con un enfoque de Comparación de Texto
Entonces, basándonos en esta evidencia, ¿qué crees que es más fácil de entender? Incluso si eres un verdadero programador como yo, no podemos negar la facilidad y los beneficios del enfoque low-code para el desarrollo masivo y estándar en el mundo empresarial.
Resumen
No importa qué tan rápido estemos desarrollando con todos los aceleradores y marcos que tenemos, una aplicación low-code bien definida será más rápida que cualquiera de nosotros. Es la misma batalla que tuvimos en el pasado con las Interfaces Gráficas o el control del ratón frente al teclado.
Aceptamos que hay una preferencia personal para elegir una u otra, pero cuando necesitamos decidir qué es más efectivo y necesitamos basarnos en los hechos, no podemos ser ciegos a lo que está frente a nosotros.
Espero que hayas disfrutado este artículo. ¡Que tengas un buen día!
Aprende algunos trucos para analizar y optimizar el uso que estás haciendo de la TSDB y ahorrar dinero en tu implementación en la nube.
En publicaciones anteriores, discutimos cómo funcionaba la capa de almacenamiento para Prometheus y cuán efectiva era. Pero en los tiempos actuales, estamos en la era de la computación en la nube y sabemos que cada optimización técnica es también una optimización de costos, y es por eso que necesitamos ser muy diligentes con cualquier opción que usemos en cuanto a optimización.
Sabemos que usualmente cuando monitoreamos usando Prometheus tenemos muchos exportadores disponibles a nuestra disposición y también que cada uno de ellos expone muchas métricas muy relevantes que necesitamos para rastrear todo lo que necesitamos. Pero también, debemos ser conscientes de que hay métricas que no necesitamos en este momento o que no planeamos usar. Entonces, si no planeamos usarlas, ¿por qué queremos desperdiciar espacio en disco almacenándolas?
Así que, comencemos echando un vistazo a uno de los exportadores que tenemos en nuestro sistema. En mi caso, me gustaría usar una Aplicación de Contenedor BusinessWorks que expone métricas sobre su utilización. Si revisas su punto de acceso de métricas podrías ver algo como esto:
# HELP jvm_info Información de la versión de JVM # TYPE jvm_info gauge jvm_info{version="1.8.0_221-b27",vendor="Oracle Corporation",runtime="Java(TM) SE Runtime Environment",} 1.0 # HELP jvm_memory_bytes_used Bytes usados de un área de memoria JVM dada. # TYPE jvm_memory_bytes_used gauge jvm_memory_bytes_used{area="heap",} 1.0318492E8 jvm_memory_bytes_used{area="nonheap",} 1.52094712E8 # HELP jvm_memory_bytes_committed Bytes comprometidos de un área de memoria JVM dada. # TYPE jvm_memory_bytes_committed gauge jvm_memory_bytes_committed{area="heap",} 1.35266304E8 jvm_memory_bytes_committed{area="nonheap",} 1.71302912E8 # HELP jvm_memory_bytes_max Máximo de bytes de un área de memoria JVM dada. # TYPE jvm_memory_bytes_max gauge jvm_memory_bytes_max{area="heap",} 1.073741824E9 jvm_memory_bytes_max{area="nonheap",} -1.0 # HELP jvm_memory_bytes_init Bytes iniciales de un área de memoria JVM dada. # TYPE jvm_memory_bytes_init gauge jvm_memory_bytes_init{area="heap",} 1.34217728E8 jvm_memory_bytes_init{area="nonheap",} 2555904.0 # HELP jvm_memory_pool_bytes_used Bytes usados de un pool de memoria JVM dado. # TYPE jvm_memory_pool_bytes_used gauge jvm_memory_pool_bytes_used{pool="Code Cache",} 3.3337536E7 jvm_memory_pool_bytes_used{pool="Metaspace",} 1.04914136E8 jvm_memory_pool_bytes_used{pool="Compressed Class Space",} 1.384304E7 jvm_memory_pool_bytes_used{pool="G1 Eden Space",} 3.3554432E7 jvm_memory_pool_bytes_used{pool="G1 Survivor Space",} 1048576.0 jvm_memory_pool_bytes_used{pool="G1 Old Gen",} 6.8581912E7 # HELP jvm_memory_pool_bytes_committed Bytes comprometidos de un pool de memoria JVM dado. # TYPE jvm_memory_pool_bytes_committed gauge jvm_memory_pool_bytes_committed{pool="Code Cache",} 3.3619968E7 jvm_memory_pool_bytes_committed{pool="Metaspace",} 1.19697408E8 jvm_memory_pool_bytes_committed{pool="Compressed Class Space",} 1.7985536E7 jvm_memory_pool_bytes_committed{pool="G1 Eden Space",} 4.6137344E7 jvm_memory_pool_bytes_committed{pool="G1 Survivor Space",} 1048576.0 jvm_memory_pool_bytes_committed{pool="G1 Old Gen",} 8.8080384E7 # HELP jvm_memory_pool_bytes_max Máximo de bytes de un pool de memoria JVM dado. # TYPE jvm_memory_pool_bytes_max gauge jvm_memory_pool_bytes_max{pool="Code Cache",} 2.5165824E8 jvm_memory_pool_bytes_max{pool="Metaspace",} -1.0 jvm_memory_pool_bytes_max{pool="Compressed Class Space",} 1.073741824E9 jvm_memory_pool_bytes_max{pool="G1 Eden Space",} -1.0 jvm_memory_pool_bytes_max{pool="G1 Survivor Space",} -1.0 jvm_memory_pool_bytes_max{pool="G1 Old Gen",} 1.073741824E9 # HELP jvm_memory_pool_bytes_init Bytes iniciales de un pool de memoria JVM dado. # TYPE jvm_memory_pool_bytes_init gauge jvm_memory_pool_bytes_init{pool="Code Cache",} 2555904.0 jvm_memory_pool_bytes_init{pool="Metaspace",} 0.0 jvm_memory_pool_bytes_init{pool="Compressed Class Space",} 0.0 jvm_memory_pool_bytes_init{pool="G1 Eden Space",} 7340032.0 jvm_memory_pool_bytes_init{pool="G1 Survivor Space",} 0.0 jvm_memory_pool_bytes_init{pool="G1 Old Gen",} 1.26877696E8 # HELP jvm_buffer_pool_used_bytes Bytes usados de un pool de buffer JVM dado. # TYPE jvm_buffer_pool_used_bytes gauge jvm_buffer_pool_used_bytes{pool="direct",} 148590.0 jvm_buffer_pool_used_bytes{pool="mapped",} 0.0 # HELP jvm_buffer_pool_capacity_bytes Capacidad en bytes de un pool de buffer JVM dado. # TYPE jvm_buffer_pool_capacity_bytes gauge jvm_buffer_pool_capacity_bytes{pool="direct",} 148590.0 jvm_buffer_pool_capacity_bytes{pool="mapped",} 0.0 # HELP jvm_buffer_pool_used_buffers Buffers usados de un pool de buffer JVM dado. # TYPE jvm_buffer_pool_used_buffers gauge jvm_buffer_pool_used_buffers{pool="direct",} 19.0 jvm_buffer_pool_used_buffers{pool="mapped",} 0.0 # HELP jvm_classes_loaded El número de clases que están actualmente cargadas en la JVM # TYPE jvm_classes_loaded gauge jvm_classes_loaded 16993.0 # HELP jvm_classes_loaded_total El número total de clases que han sido cargadas desde que la JVM comenzó a ejecutarse # TYPE jvm_classes_loaded_total counter jvm_classes_loaded_total 17041.0 # HELP jvm_classes_unloaded_total El número total de clases que han sido descargadas desde que la JVM comenzó a ejecutarse # TYPE jvm_classes_unloaded_total counter jvm_classes_unloaded_total 48.0 # HELP bwce_activity_stats_list Lista de estadísticas de actividad BWCE # TYPE bwce_activity_stats_list gauge # HELP bwce_activity_counter_list Lista de contadores relacionados con la actividad BWCE # TYPE bwce_activity_counter_list gauge # HELP all_activity_events_count Conteo de todos los eventos de actividad BWCE por estado # TYPE all_activity_events_count counter all_activity_events_count{StateName="CANCELLED",} 0.0 all_activity_events_count{StateName="COMPLETED",} 0.0 all_activity_events_count{StateName="STARTED",} 0.0 all_activity_events_count{StateName="FAULTED",} 0.0 # HELP activity_events_count Conteo de todos los eventos de actividad BWCE por proceso, estado de actividad # TYPE activity_events_count counter # HELP activity_total_evaltime_count Tiempo total de evaluación de actividad BWCE por proceso y actividad # TYPE activity_total_evaltime_count counter # HELP activity_total_duration_count Tiempo total de duración de actividad BWCE por proceso y actividad # TYPE activity_total_duration_count counter # HELP bwpartner_instance:total_request Solicitud total para la invocación del socio que se mapeó desde las actividades # TYPE bwpartner_instance:total_request counter # HELP bwpartner_instance:total_duration_ms Duración total para la invocación del socio que se mapeó desde las actividades (ejecución o latencia) # TYPE bwpartner_instance:total_duration_ms counter # HELP bwce_process_stats Lista de estadísticas de proceso BWCE # TYPE bwce_process_stats gauge # HELP bwce_process_counter_list Lista de contadores relacionados con el proceso BWCE # TYPE bwce_process_counter_list gauge # HELP all_process_events_count Conteo de todos los eventos de proceso BWCE por estado # TYPE all_process_events_count counter all_process_events_count{StateName="CANCELLED",} 0.0 all_process_events_count{StateName="COMPLETED",} 0.0 all_process_events_count{StateName="STARTED",} 0.0 all_process_events_count{StateName="FAULTED",} 0.0 # HELP process_events_count Conteo de eventos de proceso BWCE por operación # TYPE process_events_count counter # HELP process_duration_seconds_total Duración de eventos de proceso BWCE por operación en segundos # TYPE process_duration_seconds_total counter # HELP process_duration_milliseconds_total Duración de eventos de proceso BWCE por operación en milisegundos # TYPE process_duration_milliseconds_total counter # HELP bwdefinitions:partner Conteo de eventos de proceso BWCE por operación # TYPE bwdefinitions:partner counter bwdefinitions:partner{ProcessName="t1.module.item.getTransactionData",ActivityName="FTLPublisher",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="TransactionService",PartnerOperation="GetTransactionsOperation",Location="internal",PartnerMiddleware="MW",} 1.0 bwdefinitions:partner{ProcessName=" t1.module.item.auditProcess",ActivityName="KafkaSendMessage",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="AuditService",PartnerOperation="AuditOperation",Location="internal",PartnerMiddleware="MW",} 1.0 bwdefinitions:partner{ProcessName="t1.module.item.getCustomerData",ActivityName="JMSRequestReply",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="CustomerService",PartnerOperation="GetCustomerDetailsOperation",Location="internal",PartnerMiddleware="MW",} 1.0 # HELP bwdefinitions:binding Repositorio de tiempo de diseño BW - definición de enlace/transporte # TYPE bwdefinitions:binding counter bwdefinitions:binding{ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInterface="GetCustomer360:GetDataOperation",Binding="/customer",Transport="HTTP",} 1.0 # HELP bwdefinitions:service Repositorio de tiempo de diseño BW - definición de servicio # TYPE bwdefinitions:service counter bwdefinitions:service{ProcessName="t1.module.sub.item.getCustomerData",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0 bwdefinitions:service{ProcessName="t1.module.sub.item.auditProcess",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0 bwdefinitions:service{ProcessName="t1.module.sub.orchestratorSubFlow",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0 bwdefinitions:service{ProcessName="t1.module.Process",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0 # HELP bwdefinitions:gateway Repositorio de tiempo de diseño BW - definición de puerta de enlace # TYPE bwdefinitions:gateway counter bwdefinitions:gateway{ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",Endpoint="bwce-demo-mon-orchestrator-bwce",InteractionType="ISTIO",} 1.0 # HELP process_cpu_seconds_total Tiempo total de usuario y sistema de CPU gastado en segundos. # TYPE process_cpu_seconds_total counter process_cpu_seconds_total 1956.86 # HELP process_start_time_seconds Hora de inicio del proceso desde la época de Unix en segundos. # TYPE process_start_time_seconds gauge process_start_time_seconds 1.604712447107E9 # HELP process_open_fds Número de descriptores de archivo abiertos. # TYPE process_open_fds gauge process_open_fds 763.0 # HELP process_max_fds Número máximo de descriptores de archivo abiertos. # TYPE process_max_fds gauge process_max_fds 1048576.0 # HELP process_virtual_memory_bytes Tamaño de la memoria virtual en bytes. # TYPE process_virtual_memory_bytes gauge process_virtual_memory_bytes 3.046207488E9 # HELP process_resident_memory_bytes Tamaño de la memoria residente en bytes. # TYPE process_resident_memory_bytes gauge process_resident_memory_bytes 4.2151936E8 # HELP jvm_gc_collection_seconds Tiempo gastado en un recolector de basura JVM dado en segundos. # TYPE jvm_gc_collection_seconds summary jvm_gc_collection_seconds_count{gc="G1 Young Generation",} 540.0 jvm_gc_collection_seconds_sum{gc="G1 Young Generation",} 4.754 jvm_gc_collection_seconds_count{gc="G1 Old Generation",} 2.0 jvm_gc_collection_seconds_sum{gc="G1 Old Generation",} 0.563 # HELP jvm_threads_current Conteo actual de hilos de una JVM # TYPE jvm_threads_current gauge jvm_threads_current 98.0 # HELP jvm_threads_daemon Conteo de hilos daemon de una JVM # TYPE jvm_threads_daemon gauge jvm_threads_daemon 43.0 # HELP jvm_threads_peak Conteo máximo de hilos de una JVM # TYPE jvm_threads_peak gauge jvm_threads_peak 98.0 # HELP jvm_threads_started_total Conteo de hilos iniciados de una JVM # TYPE jvm_threads_started_total counter jvm_threads_started_total 109.0 # HELP jvm_threads_deadlocked Ciclos de hilos JVM que están en deadlock esperando adquirir monitores de objetos o sincronizadores propios # TYPE jvm_threads_deadlocked gauge jvm_threads_deadlocked 0.0 # HELP jvm_threads_deadlocked_monitor Ciclos de hilos JVM que están en deadlock esperando adquirir monitores de objetos # TYPE jvm_threads_deadlocked_monitor gauge jvm_threads_deadlocked_monitor 0.0
Como puedes ver, muchas métricas, pero tengo que ser honesto, no estoy usando la mayoría de ellas en mis paneles y para generar mis alertas. Puedo usar las métricas relacionadas con el rendimiento de la aplicación para cada uno de los procesos de BusinessWorks y sus actividades, también el rendimiento de la memoria JVM y el número de hilos, pero cosas como cómo está funcionando el GC de la JVM para cada una de las capas de la JVM (G1 Young Generation, G1 Old Generation) no las estoy usando en absoluto.
Entonces, si muestro el mismo punto de acceso de métricas destacando las cosas que no estoy usando, sería algo como esto:
# HELP jvm_info Información de la versión de JVM # TYPE jvm_info gauge jvm_info{version="1.8.0_221-b27",vendor="Oracle Corporation",runtime="Java(TM) SE Runtime Environment",} 1.0 # HELP jvm_memory_bytes_used Bytes usados de un área de memoria JVM dada. # TYPE jvm_memory_bytes_used gauge jvm_memory_bytes_used{area="heap",} 1.0318492E8 jvm_memory_bytes_used{area="nonheap",} 1.52094712E8 # HELP jvm_memory_bytes_committed Bytes comprometidos de un área de memoria JVM dada. # TYPE jvm_memory_bytes_committed gauge jvm_memory_bytes_committed{area="heap",} 1.35266304E8 jvm_memory_bytes_committed{area="nonheap",} 1.71302912E8 # HELP jvm_memory_bytes_max Máximo de bytes de un área de memoria JVM dada. # TYPE jvm_memory_bytes_max gauge jvm_memory_bytes_max{area="heap",} 1.073741824E9 jvm_memory_bytes_max{area="nonheap",} -1.0 # HELP jvm_memory_bytes_init Bytes iniciales de un área de memoria JVM dada. # TYPE jvm_memory_bytes_init gauge jvm_memory_bytes_init{area="heap",} 1.34217728E8 jvm_memory_bytes_init{area="nonheap",} 2555904.0 # HELP jvm_memory_pool_bytes_used Bytes usados de un pool de memoria JVM dado. # TYPE jvm_memory_pool_bytes_used gauge jvm_memory_pool_bytes_used{pool="Code Cache",} 3.3337536E7 jvm_memory_pool_bytes_used{pool="Metaspace",} 1.04914136E8 jvm_memory_pool_bytes_used{pool="Compressed Class Space",} 1.384304E7 jvm_memory_pool_bytes_used{pool="G1 Eden Space",} 3.3554432E7 jvm_memory_pool_bytes_used{pool="G1 Survivor Space",} 1048576.0 jvm_memory_pool_bytes_used{pool="G1 Old Gen",} 6.8581912E7 # HELP jvm_memory_pool_bytes_committed Bytes comprometidos de un pool de memoria JVM dado. # TYPE jvm_memory_pool_bytes_committed gauge jvm_memory_pool_bytes_committed{pool="Code Cache",} 3.3619968E7 jvm_memory_pool_bytes_committed{pool="Metaspace",} 1.19697408E8 jvm_memory_pool_bytes_committed{pool="Compressed Class Space",} 1.7985536E7 jvm_memory_pool_bytes_committed{pool="G1 Eden Space",} 4.6137344E7 jvm_memory_pool_bytes_committed{pool="G1 Survivor Space",} 1048576.0 jvm_memory_pool_bytes_committed{pool="G1 Old Gen",} 8.8080384E7 # HELP jvm_memory_pool_bytes_max Máximo de bytes de un pool de memoria JVM dado. # TYPE jvm_memory_pool_bytes_max gauge jvm_memory_pool_bytes_max{pool="Code Cache",} 2.5165824E8 jvm_memory_pool_bytes_max{pool="Metaspace",} -1.0 jvm_memory_pool_bytes_max{pool="Compressed Class Space",} 1.073741824E9 jvm_memory_pool_bytes_max{pool="G1 Eden Space",} -1.0 jvm_memory_pool_bytes_max{pool="G1 Survivor Space",} -1.0 jvm_memory_pool_bytes_max{pool="G1 Old Gen",} 1.073741824E9 # HELP jvm_memory_pool_bytes_init Bytes iniciales de un pool de memoria JVM dado. # TYPE jvm_memory_pool_bytes_init gauge jvm_memory_pool_bytes_init{pool="Code Cache",} 2555904.0 jvm_memory_pool_bytes_init{pool="Metaspace",} 0.0 jvm_memory_pool_bytes_init{pool="Compressed Class Space",} 0.0 jvm_memory_pool_bytes_init{pool="G1 Eden Space",} 7340032.0 jvm_memory_pool_bytes_init{pool="G1 Survivor Space",} 0.0 jvm_memory_pool_bytes_init{pool="G1 Old Gen",} 1.26877696E8 # HELP jvm_buffer_pool_used_bytes Bytes usados de un pool de buffer JVM dado. # TYPE jvm_buffer_pool_used_bytes gauge jvm_buffer_pool_used_bytes{pool="direct",} 148590.0 jvm_buffer_pool_used_bytes{pool="mapped",} 0.0 # HELP jvm_buffer_pool_capacity_bytes Capacidad en bytes de un pool de buffer JVM dado. # TYPE jvm_buffer_pool_capacity_bytes gauge jvm_buffer_pool_capacity_bytes{pool="direct",} 148590.0 jvm_buffer_pool_capacity_bytes{pool="mapped",} 0.0 # HELP jvm_buffer_pool_used_buffers Buffers usados de un pool de buffer JVM dado. # TYPE jvm_buffer_pool_used_buffers gauge jvm_buffer_pool_used_buffers{pool="direct",} 19.0 jvm_buffer_pool_used_buffers{pool="mapped",} 0.0 # HELP jvm_classes_loaded El número de clases que están actualmente cargadas en la JVM # TYPE jvm_classes_loaded gauge jvm_classes_loaded 16993.0 # HELP jvm_classes_loaded_total El número total de clases que han sido cargadas desde que la JVM comenzó a ejecutarse # TYPE jvm_classes_loaded_total counter jvm_classes_loaded_total 17041.0 # HELP jvm_classes_unloaded_total El número total de clases que han sido descargadas desde que la JVM comenzó a ejecutarse # TYPE jvm_classes_unloaded_total counter jvm_classes_unloaded_total 48.0 # HELP bwce_activity_stats_list Lista de estadísticas de actividad BWCE # TYPE bwce_activity_stats_list gauge # HELP bwce_activity_counter_list Lista de contadores relacionados con la actividad BWCE # TYPE bwce_activity_counter_list gauge # HELP all_activity_events_count Conteo de todos los eventos de actividad BWCE por estado # TYPE all_activity_events_count counter all_activity_events_count{StateName="CANCELLED",} 0.0 all_activity_events_count{StateName="COMPLETED",} 0.0 all_activity_events_count{StateName="STARTED",} 0.0 all_activity_events_count{StateName="FAULTED",} 0.0 # HELP activity_events_count Conteo de todos los eventos de actividad BWCE por proceso, estado de actividad # TYPE activity_events_count counter # HELP activity_total_evaltime_count Tiempo total de evaluación de actividad BWCE por proceso y actividad # TYPE activity_total_evaltime_count counter # HELP activity_total_duration_count Tiempo total de duración de actividad BWCE por proceso y actividad # TYPE activity_total_duration_count counter # HELP bwpartner_instance:total_request Solicitud total para la invocación del socio que se mapeó desde las actividades # TYPE bwpartner_instance:total_request counter # HELP bwpartner_instance:total_duration_ms Duración total para la invocación del socio que se mapeó desde las actividades (ejecución o latencia) # TYPE bwpartner_instance:total_duration_ms counter # HELP bwce_process_stats Lista de estadísticas de proceso BWCE # TYPE bwce_process_stats gauge # HELP bwce_process_counter_list Lista de contadores relacionados con el proceso BWCE # TYPE bwce_process_counter_list gauge # HELP all_process_events_count Conteo de todos los eventos de proceso BWCE por estado # TYPE all_process_events_count counter all_process_events_count{StateName="CANCELLED",} 0.0 all_process_events_count{StateName="COMPLETED",} 0.0 all_process_events_count{StateName="STARTED",} 0.0 all_process_events_count{StateName="FAULTED",} 0.0 # HELP process_events_count Conteo de eventos de proceso BWCE por operación # TYPE process_events_count counter # HELP process_duration_seconds_total Duración de eventos de proceso BWCE por operación en segundos # TYPE process_duration_seconds_total counter # HELP process_duration_milliseconds_total Duración de eventos de proceso BWCE por operación en milisegundos # TYPE process_duration_milliseconds_total counter # HELP bwdefinitions:partner Conteo de eventos de proceso BWCE por operación # TYPE bwdefinitions:partner counter bwdefinitions:partner{ProcessName="t1.module.item.getTransactionData",ActivityName="FTLPublisher",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="TransactionService",PartnerOperation="GetTransactionsOperation",Location="internal",PartnerMiddleware="MW",} 1.0 bwdefinitions:partner{ProcessName=" t1.module.item.auditProcess",ActivityName="KafkaSendMessage",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="AuditService",PartnerOperation="AuditOperation",Location="internal",PartnerMiddleware="MW",} 1.0 bwdefinitions:partner{ProcessName="t1.module.item.getCustomerData",ActivityName="JMSRequestReply",ServiceName="GetCustomer360",OperationName="GetDataOperation",PartnerService="CustomerService",PartnerOperation="GetCustomerDetailsOperation",Location="internal",PartnerMiddleware="MW",} 1.0 # HELP bwdefinitions:binding Repositorio de tiempo de diseño BW - definición de enlace/transporte # TYPE bwdefinitions:binding counter bwdefinitions:binding{ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInterface="GetCustomer360:GetDataOperation",Binding="/customer",Transport="HTTP",} 1.0 # HELP bwdefinitions:service Repositorio de tiempo de diseño BW - definición de servicio # TYPE bwdefinitions:service counter bwdefinitions:service{ProcessName="t1.module.sub.item.getCustomerData",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0 bwdefinitions:service{ProcessName="t1.module.sub.item.auditProcess",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0 bwdefinitions:service{ProcessName="t1.module.sub.orchestratorSubFlow",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0 bwdefinitions:service{ProcessName="t1.module.Process",ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",} 1.0 # HELP bwdefinitions:gateway Repositorio de tiempo de diseño BW - definición de puerta de enlace # TYPE bwdefinitions:gateway counter bwdefinitions:gateway{ServiceName="GetCustomer360",OperationName="GetDataOperation",ServiceInstance="GetCustomer360:GetDataOperation",Endpoint="bwce-demo-mon-orchestrator-bwce",InteractionType="ISTIO",} 1.0 # HELP process_cpu_seconds_total Tiempo total de usuario y sistema de CPU gastado en segundos. # TYPE process_cpu_seconds_total counter process_cpu_seconds_total 1956.86 # HELP process_start_time_seconds Hora de inicio del proceso desde la época de Unix en segundos. # TYPE process_start_time_seconds gauge process_start_time_seconds 1.604712447107E9 # HELP process_open_fds Número de descriptores de archivo abiertos. # TYPE process_open_fds gauge process_open_fds 763.0 # HELP process_max_fds Número máximo de descriptores de archivo abiertos. # TYPE process_max_fds gauge process_max_fds 1048576.0 # HELP process_virtual_memory_bytes Tamaño de la memoria virtual en bytes. # TYPE process_virtual_memory_bytes gauge process_virtual_memory_bytes 3.046207488E9 # HELP process_resident_memory_bytes Tamaño de la memoria residente en bytes. # TYPE process_resident_memory_bytes gauge process_resident_memory_bytes 4.2151936E8 # HELP jvm_gc_collection_seconds Tiempo gastado en un recolector de basura JVM dado en segundos. # TYPE jvm_gc_collection_seconds summary jvm_gc_collection_seconds_count{gc="G1 Young Generation",} 540.0 jvm_gc_collection_seconds_sum{gc="G1 Young Generation",} 4.754 jvm_gc_collection_seconds_count{gc="G1 Old Generation",} 2.0 jvm_gc_collection_seconds_sum{gc="G1 Old Generation",} 0.563 # HELP jvm_threads_current Conteo actual de hilos de una JVM # TYPE jvm_threads_current gauge jvm_threads_current 98.0 # HELP jvm_threads_daemon Conteo de hilos daemon de una JVM # TYPE jvm_threads_daemon gauge jvm_threads_daemon 43.0 # HELP jvm_threads_peak Conteo máximo de hilos de una JVM # TYPE jvm_threads_peak gauge jvm_threads_peak 98.0 # HELP jvm_threads_started_total Conteo de hilos iniciados de una JVM # TYPE jvm_threads_started_total counter jvm_threads_started_total 109.0 # HELP jvm_threads_deadlocked Ciclos de hilos JVM que están en deadlock esperando adquirir monitores de objetos o sincronizadores propios # TYPE jvm_threads_deadlocked gauge jvm_threads_deadlocked 0.0 # HELP jvm_threads_deadlocked_monitor Ciclos de hilos JVM que están en deadlock esperando adquirir monitores de objetos # TYPE jvm_threads_deadlocked_monitor gauge jvm_threads_deadlocked_monitor 0.0
Entonces, puede ser un 50% de la respuesta del punto de acceso de métricas la parte que no estoy usando, entonces, ¿por qué estoy usando espacio en disco que estoy pagando para almacenarlo? Y esto es solo para un «exportador crítico», uno que trato de usar tanta información como sea posible, pero piensa en cuántos exportadores tienes y cuánta información usas para cada uno de ellos.
Ok, entonces ahora el propósito y la motivación de esta publicación están claros, pero ¿qué podemos hacer al respecto?
Descubriendo la API REST
Prometheus tiene una increíble API REST para exponer toda la información que puedas desear. Si alguna vez has usado la Interfaz Gráfica para Prometheus (mostrada a continuación) estás usando la API REST porque esto es lo que está detrás de ella.
Vista de destino de la Interfaz Gráfica de Prometheus
Tenemos toda la documentación sobre la API REST en la documentación oficial de Prometheus:
Pero, ¿qué nos proporciona esta API en términos de la base de datos de series temporales TSDB que utiliza Prometheus?
APIs de Administración de TSDB
Tenemos una API específica para gestionar el rendimiento de la base de datos TSDB, pero para poder usarla, necesitamos habilitar la API de Administración. Y eso se hace proporcionando la siguiente bandera donde estamos lanzando el servidor Prometheus --web.enable-admin-api.
Si estamos usando el Prometheus Operator Helm Chart para desplegar esto, necesitamos usar el siguiente elemento en nuestro values.yaml
## EnableAdminAPI habilita la API HTTP administrativa de Prometheus, que incluye funcionalidades como eliminar series temporales. ## Esto está deshabilitado por defecto. ## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis ## enableAdminAPI: true
Tenemos muchas opciones habilitadas cuando habilitamos esta API administrativa, pero hoy nos vamos a centrar en una sola operación REST que es el «stats». Este es el único método relacionado con TSDB que no requiere habilitar la API de Administración. Esta operación, como podemos leer en la documentación de Prometheus, devuelve los siguientes elementos:
headStats: Esto proporciona los siguientes datos sobre el bloque principal de la TSDB:
numSeries: El número de series.
chunkCount: El número de fragmentos.
minTime: La marca de tiempo mínima actual en milisegundos.
maxTime: La marca de tiempo máxima actual en milisegundos.
seriesCountByMetricName: Esto proporcionará una lista de nombres de métricas y su conteo de series.
labelValueCountByLabelName: Esto proporcionará una lista de nombres de etiquetas y su conteo de valores.
memoryInBytesByLabelName Esto proporcionará una lista de nombres de etiquetas y la memoria utilizada en bytes. El uso de memoria se calcula sumando la longitud de todos los valores para un nombre de etiqueta dado.
seriesCountByLabelPair Esto proporcionará una lista de pares de valores de etiquetas y su conteo de series.
Para acceder a esa API, necesitamos acceder al siguiente punto de acceso:
GET /api/v1/status/tsdb
Entonces, cuando hago eso en mi implementación de Prometheus, obtengo algo similar a esto:
También podemos verificar la misma información si usamos la nueva y experimental Interfaz de Usuario React en el siguiente punto de acceso:
/new/tsdb-status
Visualización gráfica del conteo de las 10 series principales por nombre de métrica en la nueva interfaz de usuario de Prometheus
Entonces, con eso, obtendrás las 10 series y etiquetas principales que están dentro de tu base de datos de series temporales, por lo que en caso de que algunas de ellas no sean útiles, puedes simplemente deshacerte de ellas usando los enfoques normales para eliminar una serie o una etiqueta. Esto es genial, pero ¿qué pasa si todas las que se muestran aquí son relevantes, qué podemos hacer al respecto?
Mmmm, tal vez podamos usar PromQL para monitorear esto (enfoque de dogfooding). Así que si quisiéramos extraer la misma información pero usando PromQL, podemos hacerlo con la siguiente consulta:
topk(10, count by (__name__)({__name__=~".+"}))
Top 10 de series de métricas generadas y almacenadas en la base de datos de series temporales
Y ahora tenemos todo el poder en mis manos. Por ejemplo, echemos un vistazo no a las 10 más relevantes, sino a las 100 más relevantes o cualquier otro filtro que necesitemos aplicar. Por ejemplo, veamos las métricas relacionadas con la JVM que discutimos al principio. Y lo haremos con la siguiente consulta PromQL:
topk(100, count by (__name__)({__name__=~"jvm.+"}))
Top 100 de series de métricas relacionadas con métricas de JVM
Así que podemos ver que tenemos al menos 150 series relacionadas con métricas que no estoy usando en absoluto. Pero hagámoslo aún mejor, echemos un vistazo a lo mismo pero agrupado por nombres de trabajos:
topk(10, count by (job,__name__)({__name__=~".+"}))
Resultado de verificar el conteo de las 10 series de métricas principales con el trabajo que las está generando
Prometheus es uno de los sistemas clave en las arquitecturas de nube actuales. El segundo proyecto graduado de la Cloud Native Computing Foundation (CNCF) después de Kubernetes, y es la solución de monitoreo por excelencia en la mayoría de las cargas de trabajo que se ejecutan en Kubernetes.
Si ya has usado Prometheus por algún tiempo, sabes que se basa en una base de datos de series temporales, por lo que el almacenamiento de Prometheus es uno de los elementos clave. Basado en sus propias palabras de la página oficial de Prometheus:
Storage | Prometheus
An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.
Cada serie temporal se identifica de manera única por su nombre de métrica y pares clave-valor opcionales llamados etiquetas, y esa serie es similar a las tablas en un modelo relacional. Y dentro de cada una de esas series, tenemos muestras que son similares a las tuplas. Y cada una de las muestras contiene un valor flotante y una marca de tiempo con precisión de milisegundos.
Enfoque predeterminado en disco
Por defecto, Prometheus utiliza un enfoque de almacenamiento local guardando todas esas muestras en disco. Estos datos se distribuyen en diferentes archivos y carpetas para agrupar diferentes fragmentos de datos.
Así que, tenemos carpetas para crear esos grupos, y por defecto, son un bloque de dos horas y pueden contener uno o más archivos dependiendo de la cantidad de datos ingeridos en ese período de tiempo, ya que cada carpeta contiene todas las muestras para esa línea de tiempo específica.
Además, cada carpeta también tiene algún tipo de archivos de metadatos que ayudan a localizar las métricas de cada uno de los archivos de datos.
Un archivo es persistente de manera completa cuando el bloque ha terminado, y antes de eso, se mantiene en memoria y utiliza una técnica de registro de escritura anticipada para recuperar los datos en caso de un fallo del servidor de Prometheus.
Así que, a un nivel alto, la estructura de directorios del directorio de datos de un servidor de Prometheus se verá algo así:
Integración de Almacenamiento Remoto
El almacenamiento predeterminado en disco es bueno y tiene algunas limitaciones en términos de escalabilidad y durabilidad, incluso considerando la mejora de rendimiento de la última versión de TSDB. Así que, si queremos explorar otras opciones para almacenar estos datos, Prometheus proporciona una manera de integrarse con ubicaciones de almacenamiento remoto.
Proporciona una API que permite escribir muestras que se están ingiriendo en una URL remota y, al mismo tiempo, poder leer datos de muestra para esa URL remota como se muestra en la imagen a continuación:
Como siempre en cualquier cosa relacionada con Prometheus, el número de adaptadores creados usando este patrón es enorme, y se puede ver en el siguiente enlace en detalle:
Integrations | Prometheus
An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.
Resumen
Saber cómo funciona el almacenamiento de Prometheus es crítico para entender cómo podemos optimizar su uso para mejorar el rendimiento de nuestra solución de monitoreo y proporcionar un despliegue rentable.
En las siguientes publicaciones, vamos a cubrir cómo podemos optimizar el uso de esta capa de almacenamiento, asegurándonos de que solo se almacenen las métricas y muestras que son importantes para usar, y también cómo analizar cuáles métricas son las más utilizadas de la base de datos de series temporales para poder tomar buenas decisiones sobre qué métricas deben ser eliminadas y cuáles deben mantenerse.
Aprende cómo puedes aprovechar el uso de Snyk dentro de tu instalación del motor Docker
La seguridad es el tema más relevante en la arquitectura moderna. Necesita ser manejado desde todas las diferentes perspectivas. Tener un solo equipo auditando las plataformas y los desarrollos que construimos no es suficiente.
La introducción de DevSecOps como la nueva normalidad, incluyendo a los equipos de seguridad y las políticas como parte del proceso de desarrollo para evitar que la seguridad se convierta en un obstáculo para la innovación y asegurar que los artefactos que desplegamos estén seguros, ha dejado esto claro.
El escaneo de imágenes Docker es uno de los temas más importantes que podemos cubrir respecto a las imágenes de contenedores para saber que todos los componentes internos que forman parte de la imagen están a salvo de vulnerabilidades. Usualmente confiamos en algunos sistemas para hacerlo.
Escribí un artículo sobre el uso de una de las opciones más relevantes (Harbor) del mundo de código abierto para hacer este trabajo.
Y esto también está siendo realizado por diferentes repositorios Docker de proveedores de nube como Amazon ECR a partir de este año. Pero, ¿por qué necesitamos esperar hasta que subamos las imágenes a un registro Docker externo? ¿Por qué no podemos hacerlo en nuestro entorno local?
Ahora podemos. La versión 2.5.0.1 del motor Docker también incluye los componentes de Snyk necesarios para inspeccionar las imágenes Docker directamente desde la línea de comandos:
Entonces, comencemos. Abramos un nuevo terminal y escribamos el siguiente comando:
docker scan <nombre-de-imagen>
Tan pronto como escribamos esto, el comando nos dirá que este proceso de escaneo usará Snyk para hacerlo y necesitamos autorizar el acceso a esos servicios para realizar el proceso de escaneo.
Después de eso, obtenemos una lista de todas las vulnerabilidades detectadas, como puedes ver en la imagen a continuación:
Escaneo de vulnerabilidades usando tu cliente Docker local
Para cada una de las vulnerabilidades, puedes ver los siguientes datos:
Información detallada proporcionada para cada una de las vulnerabilidades detectadas
Obtenemos la biblioteca con la vulnerabilidad, el nivel de severidad y una breve descripción de la misma. Si necesitas más detalles, también puedes consultar la URL proporcionada que está vinculada a una página de descripción para esa vulnerabilidad:
Página detallada de vulnerabilidades de snyk
Finalmente, también proporciona las fuentes que introducen esta biblioteca en tu imagen para que esto pueda resolverse rápidamente.
También proporciona una vista de alto nivel de toda la imagen, como puedes ver aquí:
Visión general de tus imágenes Docker con todas las vulnerabilidades detectadas
Así que ahora no tienes excusa para no tener todas tus imágenes seguras antes de subirlas a tu repositorio local. ¡Hagámoslo!
Descubre cómo puedes mejorar el tamaño de tus imágenes de Docker para una mejor experiencia y ahorros dentro de tu organización.
La contenedorización es la nueva normalidad. Todos somos conscientes de eso. Todas las nuevas versiones del software corporativo y todos los proyectos de código abierto están incluyendo las opciones para usar una imagen de Docker para ejecutar su software. Probablemente ya hayas estado haciendo tus pruebas o incluso ejecutando cargas de trabajo en producción basadas en imágenes de Docker que has construido tú mismo. Si ese es el caso, probablemente conozcas uno de los grandes desafíos cuando realizas este tipo de tarea: ¿Cómo optimizar el tamaño de la imagen que generas? Una de las principales razones por las que la imagen de Docker puede ser tan grande es porque se construyen siguiendo un concepto de capas. Y eso significa que cada una de las imágenes se crea como la adición de capas, cada una asociada con los diferentes comandos que tienes en tu Dockerfile.Explicación gráfica de cómo se compone una imagen de Docker.
Usa dive para analizar el tamaño de tus imágenes
dive es un proyecto de código abierto que proporciona una vista detallada de la composición de tus imágenes de Docker. Funciona como una aplicación de interfaz de línea de comandos que tiene una gran vista del contenido de las capas, como puedes ver en la imagen a continuación:Ejecución de Dive de una imagen de BusinessWorks Container Edition La herramienta sigue una interfaz n-curses (si eres lo suficientemente mayor para recordar cómo eran las herramientas antes de que las interfaces gráficas de usuario fueran algo; debería parecerte familiar) y tiene estas características principales:
Esta herramienta proporcionará la lista de capas en la parte superior izquierda de la pantalla y el tamaño asociado con cada una de ellas.
Proporciona estadísticas generales sobre la eficiencia de la imagen (un valor porcentual), una vista potencial del tamaño desperdiciado y el tamaño total de la imagen.
Para cada una de las capas seleccionadas, obtienes una vista en el sistema de archivos para esta vista con los datos del tamaño de cada carpeta.
También obtén una vista de los elementos más grandes y el número de replicaciones de estos objetos.
Ahora, tienes una herramienta que te ayudará primero a saber cómo se construye tu imagen y obtener datos de rendimiento de cada uno de los ajustes que haces para mejorar ese tamaño. Así que, comencemos con los trucos.
1.- ¡Limpia tu imagen!
Este primero es bastante obvio, pero eso no significa que no sea importante. Por lo general, cuando creas una imagen de Docker, sigues el mismo patrón:
Declaras una imagen base para aprovechar.
Agregas recursos para hacer algún trabajo.
Haces algún trabajo.
Por lo general, olvidamos un paso adicional: ¡Limpiar los recursos agregados cuando ya no son necesarios! Por lo tanto, es importante asegurarse de eliminar cada uno de los archivos que ya no necesitamos. Esto también se aplica a otros componentes como la caché de apt cuando estamos instalando un nuevo paquete que necesitamos o cualquier carpeta temporal que necesitemos para realizar una instalación o algún trabajo para construir la imagen.
2.- Ten cuidado con cómo creas tu Dockerfile
Como ya mencionamos, cada uno de los comandos que declaramos en nuestro Dockerfile genera una nueva capa. Por lo tanto, es importante tener mucho cuidado con las líneas que tenemos en el Dockerfile. Incluso si esto es un compromiso con respecto a la legibilidad del Dockerfile, es importante intentar fusionar comandos en la misma primitiva RUN para asegurarnos de no estar creando capas adicionales.Ejemplo de un Dockerfile con comandos fusionados También puedes usar linters de Docker como Hadolint que te ayudarán con esto y otros anti-patrones que deberías evitar cuando estás creando un Dockerfile.
3.- Opta por docker build — squash
Las últimas versiones del motor de Docker proporcionan una nueva opción cuando construyes tus imágenes para crear con el tamaño minimizado squashing de las capas intermedias que pueden ser creadas como parte del proceso de creación del Dockerfile. Eso funciona, proporcionando una nueva bandera cuando estás haciendo la construcción de tu imagen. Así que, en lugar de hacer esto:
Para poder usar esta opción, debes habilitar las características experimentales en tu Docker Engine. Para hacer eso, necesitas habilitarlo en tu archivo daemon.json y reiniciar el motor. Si estás usando Docker para Windows o Docker para Mac, puedes hacerlo usando la interfaz de usuario como se muestra a continuación:
Resumen
Estos ajustes te ayudarán a hacer tus imágenes de Docker más delgadas y mucho más agradable el proceso de extraer y empujar y, al mismo tiempo, incluso ahorrar algo de dinero con respecto al almacenamiento de las imágenes en el repositorio de tu elección. Y no solo para ti, sino para muchos otros que pueden aprovechar el trabajo que estás haciendo. Así que piensa en ti mismo, pero también piensa en la comunidad.
En el post anterior de esta serie sobre cómo configurar un clúster EKS híbrido utilizando tanto máquinas EC2 tradicionales como opciones sin servidor usando Fargate, pudimos crear el clúster EKS con ambas modalidades de implementación disponibles. ¡Si aún no lo has visto, hazlo ahora! https://medium.com/@alexandrev/hybrid-aws-kubernetes-cluster-using-eks-ec2-and-fargate-13198d864baa En ese punto, tenemos un clúster vacío con todo listo para desplegar nuevas cargas de trabajo, pero aún necesitamos configurar algunas cosas antes de realizar el despliegue. Lo primero es decidir qué cargas de trabajo se van a desplegar usando la opción sin servidor y cuáles usarán la opción tradicional de EC2. Por defecto, todas las cargas de trabajo desplegadas en los espacios de nombres default y kube-system como puedes ver en la imagen a continuación desde la Consola de AWS: Eso significa que todas las cargas de trabajo del espacio de nombres default y del espacio de nombres kube-system se desplegarán de manera sin servidor. Si eso es lo que deseas, perfecto. Pero a veces te gustaría comenzar con un conjunto delimitado de espacios de nombres donde te gustaría usar la opción sin servidor y confiar en el despliegue tradicional. Podemos verificar esa misma información usando eksctl y para hacerlo necesitamos escribir el siguiente comando:
eksctl get fargateprofile --cluster cluster-test-hybrid -o yaml
La salida de ese comando debería ser algo similar a la información que podemos ver en la Consola de AWS:
NOTA: Si no recuerdas el nombre de tu clúster solo necesitas escribir el comando eksctl get clusters
Entonces, esto es lo que vamos a hacer y para hacerlo lo primero que necesitamos hacer es crear un nuevo espacio de nombres llamado “serverless” que va a contener nuestro despliegue sin servidor y para hacerlo usamos un comando kubectl de la siguiente manera:
kubectl create namespace serverless
Y ahora, solo necesitamos crear un nuevo perfil de fargate que va a reemplazar el que tenemos en este momento y para hacerlo necesitamos usar nuevamente eksctl para manejar ese trabajo:
NOTA: También podemos usar no solo el espacio de nombres para limitar el alcance de nuestro despliegue sin servidor sino también etiquetas, por lo que podemos tener en el mismo espacio de nombres cargas de trabajo que se despliegan usando el despliegue tradicional y otras usando la modalidad sin servidor. Eso nos dará todas las posibilidades para diseñar tu clúster como desees. Para hacerlo, añadiremos el argumento labels en un formato clave=valor.
Y obtendremos una salida similar a esta:
[ℹ] creando perfil de Fargate “fp-serverless-profile” en el clúster EKS “cluster-test-hybrid”
[ℹ] creado perfil de Fargate “fp-serverless-profile” en el clúster EKS “cluster-test-hybrid”
Si ahora verificamos el número de perfiles que tenemos disponibles deberíamos obtener dos perfiles manejando tres espacios de nombres (los que son gestionados por el perfil por defecto — default y kube-system — y el que — serverless — es gestionado por el que acabamos de crear ahora) Solo usaremos el siguiente comando para eliminar el perfil por defecto:
Y la salida de ese comando debería ser similar a esta:
[ℹ] eliminado perfil de Fargate “fp-default” en el clúster EKS “cluster-test-hybrid”
Y después de eso, ahora tenemos listo nuestro clúster con un alcance limitado para despliegues sin servidor. En el próximo post de la serie, solo desplegaremos cargas de trabajo en ambas modalidades para ver la diferencia entre ellas. Así que, no te pierdas las actualizaciones sobre esta serie asegurándote de seguir mis publicaciones, y si te gustó el artículo, o tienes algunas dudas o comentarios, por favor deja tus comentarios usando los comentarios a continuación!
Cluster de Kubernetes EKS Fargate AWS: Aprende cómo crear un clúster de Kubernetes que también pueda utilizar todo el poder de la computación sin servidor usando AWS Fargate
Sabemos que hay varios movimientos y paradigmas que nos están empujando fuertemente a cambiar nuestras arquitecturas tratando de aprovechar mucho más los servicios gestionados y cuidando el nivel operativo para que podamos centrarnos en lo que realmente es importante para nuestro propio negocio: crear aplicaciones y entregar valor a través de ellas.
AWS de Amazon ha sido un socio crítico durante ese viaje, especialmente en el mundo de los contenedores. Con el lanzamiento de EKS hace algún tiempo, pudieron proporcionar un servicio de Kubernetes gestionado que todos pueden usar, pero también introduciendo la solución CaaS Fargate también nos da el poder de ejecutar una carga de trabajo de contenedor de manera sin servidor, sin necesidad de preocuparse por nada más.
Pero podrías estar pensando si esos servicios pueden trabajar juntos. Y la respuesta corta es sí. Pero aún más importante que eso, estamos viendo que también pueden trabajar en un modo mixto:
Así que puedes tener un clúster EKS que tiene algunos nodos que son servicios Fargate y algunos nodos que son máquinas EC2 normales para cargas de trabajo que están trabajando de manera con estado o se ajustan mejor a un enfoque tradicional de EC2. Y todo funciona bajo las mismas reglas y es gestionado por el mismo clúster EKS.
Entonces, eso suena increíble, pero, ¿cómo podemos hacer eso? Vamos a ver.
eksctl
Para llegar a ese punto hay una herramienta que necesitamos presentar primero, y esa herramienta se llama eksctl y es una utilidad de línea de comandos que nos ayuda a realizar cualquier acción para interactuar con el servicio EKS y simplifica mucho el trabajo a realizar y también permite automatizar la mayoría de las tareas en un modo no requerido por humanos. Así que, lo primero que necesitamos es tener eksctl listo en nuestras plataformas. Veamos cómo podemos obtener eso.
Aquí tenemos todos los detalles de Amazon sobre cómo instalar eksctl en diferentes plataformas, no importa si estás usando Windows, Linux o MacOS X:
Installing or updating eksctl – Amazon EKS
Learn how to install or update the eksctl command line tool. This tool is used to create and work with an Amazon EKS cluster.
Después de hacer eso, podemos verificar que hemos instalado el software eksctl ejecutando el comando:
eksctl version
Y deberíamos obtener una salida similar a esta:
Salida del comando eksctl version
Así que después de hacer eso, podemos ver que tenemos acceso a todo el poder detrás del servicio EKS simplemente escribiendo estos simples comandos en nuestra ventana de consola.
Creando el Clúster Híbrido EKS
Ahora, vamos a crear un entorno mixto con algunas máquinas EC2 y habilitar el soporte Fargate para EKS. Para hacer eso, comenzaremos con el siguiente comando:
eksctl create cluster --version=1.15 --name=cluster-test-hybrid --region=eu-west-1 --max-pods-per-node=1000 --fargate
[ℹ] eksctl version 0.26.0
[ℹ] usando la región eu-west-1
[ℹ] configurando zonas de disponibilidad a [eu-west-1c eu-west-1a eu-west-1b]
[ℹ] subredes para eu-west-1c - pública:192.168.0.0/19 privada:192.168.96.0/19
[ℹ] subredes para eu-west-1a - pública:192.168.32.0/19 privada:192.168.128.0/19
[ℹ] subredes para eu-west-1b - pública:192.168.64.0/19 privada:192.168.160.0/19
[ℹ] usando la versión de Kubernetes 1.15
[ℹ] creando el clúster EKS "cluster-test-hybrid" en la región "eu-west-1" con perfil Fargate
[ℹ] si encuentras algún problema, revisa la consola de CloudFormation o intenta 'eksctl utils describe-stacks --region=eu-west-1 --cluster=cluster-test-hybrid'
[ℹ] el registro de CloudWatch no estará habilitado para el clúster "cluster-test-hybrid" en "eu-west-1"
[ℹ] puedes habilitarlo con 'eksctl utils update-cluster-logging --region=eu-west-1 --cluster=cluster-test-hybrid'
[ℹ] el acceso al punto final de la API de Kubernetes usará el valor predeterminado de {publicAccess=true, privateAccess=false} para el clúster "cluster-test-hybrid" en "eu-west-1"
[ℹ] 2 tareas secuenciales: { crear el plano de control del clúster "cluster-test-hybrid", crear perfiles fargate }
[ℹ] construyendo la pila del clúster "eksctl-cluster-test-hybrid-cluster"
[ℹ] desplegando la pila "eksctl-cluster-test-hybrid-cluster"
[ℹ] creando el perfil Fargate "fp-default" en el clúster EKS "cluster-test-hybrid"
[ℹ] creado el perfil Fargate "fp-default" en el clúster EKS "cluster-test-hybrid"
[ℹ] "coredns" ahora es programable en Fargate
[ℹ] "coredns" ahora está programado en Fargate
[ℹ] los pods de "coredns" ahora están programados en Fargate
[ℹ] esperando la disponibilidad del plano de control...
[✔] guardado kubeconfig como "C:Usersavazquez/.kube/config"
[ℹ] sin tareas
[✔] todos los recursos del clúster EKS para "cluster-test-hybrid" han sido creados
[ℹ] el comando kubectl debería funcionar con "C:Usersavazquez/.kube/config", intenta 'kubectl get nodes'
[✔] el clúster EKS "cluster-test-hybrid" en la región "eu-west-1" está listo
Este comando configurará el clúster EKS habilitando el soporte Fargate.
NOTA: Lo primero que deberíamos notar es que el soporte Fargate para EKS aún no está disponible en todas las regiones de AWS. Por lo tanto, dependiendo de la región que estés utilizando, podrías obtener un error. En este momento, esto solo está habilitado en US East (N. Virginia), US East (Ohio), US West (Oregon), Europa (Irlanda), Europa (Frankfurt), Asia Pacífico (Singapur), Asia Pacífico (Sídney), Asia Pacífico (Tokio) según la información de los Anuncios de AWS: https://aws.amazon.com/about-aws/whats-new/2020/04/eks-adds-fargate-support-in-frankfurt-oregon-singapore-and-sydney-aws-regions/
Así que, ahora, deberíamos agregar a ese clúster un Grupo de Nodos. Un Grupo de Nodos es un conjunto de instancias EC2 que van a ser gestionadas como parte de él. Y para hacer eso, utilizaremos el siguiente comando:
eksctl create nodegroup --cluster cluster-test-hybrid --managed
[ℹ] eksctl version 0.26.0
[ℹ] usando la región eu-west-1
[ℹ] se usará la versión 1.15 para el/los nuevo(s) grupo(s) de nodos basado en la versión del plano de control
[ℹ] el grupo de nodos "ng-1262d9c0" está presente en la configuración dada, pero falta en el clúster
[ℹ] 1 grupo de nodos (ng-1262d9c0) fue incluido (basado en las reglas de inclusión/exclusión)
[ℹ] se creará una pila de CloudFormation para cada uno de los 1 grupos de nodos gestionados en el clúster "cluster-test-hybrid"
[ℹ] 2 tareas secuenciales: { corregir la compatibilidad del clúster, 1 tarea: { 1 tarea: { crear grupo de nodos gestionado "ng-1262d9c0" } } }
[ℹ] comprobando la pila del clúster para recursos faltantes
[ℹ] la pila del clúster tiene todos los recursos requeridos
[ℹ] construyendo la pila del grupo de nodos gestionado "eksctl-cluster-test-hybrid-nodegroup-ng-1262d9c0"
[ℹ] desplegando la pila "eksctl-cluster-test-hybrid-nodegroup-ng-1262d9c0"
[ℹ] sin tareas
[✔] creado 0 grupo(s) de nodos en el clúster "cluster-test-hybrid"
[ℹ] el grupo de nodos "ng-1262d9c0" tiene 2 nodo(s)
[ℹ] el nodo "ip-192-168-69-215.eu-west-1.compute.internal" está listo
[ℹ] el nodo "ip-192-168-9-111.eu-west-1.compute.internal" está listo
[ℹ] esperando que al menos 2 nodo(s) estén listos en "ng-1262d9c0"
[ℹ] el grupo de nodos "ng-1262d9c0" tiene 2 nodo(s)
[ℹ] el nodo "ip-192-168-69-215.eu-west-1.compute.internal" está listo
[ℹ] el nodo "ip-192-168-9-111.eu-west-1.compute.internal" está listo
[✔] creado 1 grupo(s) de nodos gestionado(s) en el clúster "cluster-test-hybrid"
[ℹ] comprobando la configuración del grupo de seguridad para todos los grupos de nodos
[ℹ] todos los grupos de nodos tienen la configuración actualizada
Así que ahora deberíamos poder usar kubectl para gestionar este nuevo clúster. Si no tienes instalado kubectl o no has oído hablar de él. Esta es la herramienta de línea de comandos que nos permite gestionar tu Clúster de Kubernetes y puedes instalarla basándote en la documentación mostrada aquí:
Installing or updating eksctl – Amazon EKS
Learn how to install or update the eksctl command line tool. This tool is used to create and work with an Amazon EKS cluster.
Así que, ahora, deberíamos empezar a echar un vistazo a la infraestructura que tenemos. Así que si escribimos el siguiente comando para ver los nodos a nuestra disposición:
kubectl get nodes
Vemos una salida similar a esta:
NAME STATUS ROLES AGE VERSION
fargate-ip-192-168-102-22.eu-west-1.compute.internal Ready <none> 10m v1.15.10-eks-094994
fargate-ip-192-168-112-125.eu-west-1.compute.internal Ready <none> 10m v1.15.10-eks-094994
ip-192-168-69-215.eu-west-1.compute.internal Ready <none> 85s v1.15.11-eks-bf8eea
ip-192-168-9-111.eu-west-1.compute.internal Ready <none> 87s v1.15.11-eks-bf8eea
Como puedes ver, tenemos 4 “nodos”, dos que comienzan con el nombre fargate que son nodos fargate y dos que solo comienzan con ip-… y esos son las instancias EC2 tradicionales. Y después de ese momento, eso es todo, tenemos nuestro entorno mixto listo para usar.
Podemos verificar el mismo clúster usando la página de AWS EKS para ver esa configuración con más detalle. Si ingresamos en la página de EKS para este clúster, vemos en la pestaña de Computación la siguiente información:
Vemos bajo Grupos de Nodos los datos sobre las máquinas EC2 que son gestionadas como parte de este clúster y como puedes ver vimos 2 como la Capacidad Deseada y por eso tenemos 2 instancias EC2 en nuestro clúster. Y con respecto al perfil Fargate, vemos los espacios de nombres configurados como predeterminado y kube-system y eso significa que todos los despliegues a esos espacios de nombres se van a desplegar usando Tareas Fargate.
Resumen
En los siguientes artículos de esta serie, veremos cómo progresar en nuestro clúster Híbrido, desplegar cargas de trabajo, escalarlo en función de la demanda que estamos recibiendo, habilitar la integración con otros servicios como AWS CloudWatch, y así sucesivamente. Así que, mantente atento, y no olvides seguir mis artículos para no perderte ninguna nueva actualización tan pronto como esté disponible para ti.
Descubra cómo TIBCO Cloud Integration puede ayudarle a aumentar la agilidad empresarial conectando todas sus aplicaciones, dispositivos y datos sin importar dónde estén alojados
Vivimos en un mundo donde el número de activos digitales que necesitan ser integrados, los tipos de activos y dónde están alojados están explotando. Hemos pasado de un panorama empresarial simple donde todos nuestros sistemas estaban alojados en un solo centro de datos, y el número de sistemas era pequeño. Si aún recuerda esos días, probablemente podría nombrar todos los sistemas que mantenía. ¿Podría imaginarse haciendo eso hoy?
Esto ha cambiado completamente. Las empresas hoy en día operan cada vez más en aplicaciones y datos en lugar de en procesos manuales documentados, y eso ha aumentado las demandas para tenerlos conectados para apoyar las operaciones del negocio. ¿Cómo puede un equipo de TI tradicional mantenerse al día con todas las solicitudes de conectividad provenientes de todas las áreas del negocio para asegurar que estos activos estén completamente integrados y funcionen sin problemas?
Además, el entorno empresarial ha cambiado completamente. Hoy en día todo está hiperacelerado. Ya no puede esperar seis meses para poner en línea sus nuevas promociones de marketing o para introducir nuevos servicios digitales.
Esto se debe a que los mercados cambian constantemente con el tiempo. A veces crecen, y otras veces se contraen. Esto obligó a las empresas a cambiar rápidamente la forma en que hacen negocios.
Entonces, si necesitamos resumir todo lo que necesitamos de una arquitectura de aplicaciones para asegurarnos de que pueda ayudarnos a cumplir con nuestros requisitos empresariales, esa palabra es «agilidad». Y la agilidad arquitectónica crea agilidad empresarial.
Se han adoptado diferentes paradigmas de TI para ayudar a aumentar la agilidad arquitectónica desde diferentes perspectivas que proporcionan una forma rápida de adaptarse, conectarse y ofrecer nuevas capacidades a los clientes:
Agilidad de Infraestructura: Basada en la adopción de la nube, los proveedores de nube ofrecen una forma ágil de aprovechar inmediatamente la capacidad de infraestructura requerida, permitiendo una rápida innovación al crear rápidamente nuevos entornos y desplegar nuevos servicios bajo demanda.
Agilidad de Operación y Gestión: Las aplicaciones basadas en SaaS le permiten adoptar suites empresariales de mejor calidad sin tener que adquirir y gestionar la infraestructura subyacente, como lo hace en su enfoque local. Esto le permite agilizar y acelerar las operaciones de su negocio.
Agilidad de Desarrollo: Basada en las tecnologías de aplicaciones que crean componentes de software pequeños y altamente escalables que pueden evolucionarse, desplegarse y gestionarse de manera autónoma. Este enfoque integra capacidades de integración directamente dentro de las aplicaciones desplegadas, haciendo que la integración ya no sea una capa separada, sino algo que está incorporado dentro de cada componente. Los conceptos de microservicios, desarrollo liderado por API y arquitectura impulsada por eventos juegan un papel esencial y expanden las personas involucradas en el proceso de desarrollo.
Entonces, todas estas formas de agilidad ayudan a construir una arquitectura de aplicaciones que es altamente ágil, capaz de responder rápidamente a los cambios en el entorno en el que opera. Y puede lograr todas ellas con TIBCO® Cloud Integration (TCI).
TCI es una Plataforma de Integración como Servicio (iPaaS), una solución de integración basada en la nube que hace extremadamente fácil para usted conectar todos sus activos sin importar dónde estén alojados. Es una oferta SaaS que se ejecuta tanto en AWS como en Microsoft Azure, por lo que no tiene que gestionar la infraestructura subyacente para asegurarse de que los activos de integración que son críticos para su negocio estén siempre disponibles y se escalen a cualquier nivel de demanda.
Desde la perspectiva del desarrollo, TCI le proporciona todas las herramientas necesarias para que su negocio desarrolle y conecte todos sus activos digitales, incluidas sus aplicaciones, fuentes de datos, dispositivos, suites empresariales, procesos y soluciones SaaS, utilizando los estándares más modernos dentro de una experiencia inmersiva.
Aborda patrones de integración desde enfoques tradicionales, como en la replicación de datos, hasta enfoques modernos, incluyendo arquitecturas lideradas por API e impulsadas por eventos. También admite los últimos estándares de conectividad como REST, GraphQL, AsyncAPI y gRPC. Y para reducir el tiempo de comercialización de sus integraciones, también incluye un número significativo de conectores preempaquetados que simplifican la conectividad a suites empresariales heredadas y modernas, fuentes de datos y más, sin importar si residen en su centro de datos o en la nube. Estos conectores son fácilmente accesibles dentro de un mercado de conectores integrado directamente en la experiencia del usuario para ser utilizados en toda la plataforma.
TCI mejora el desarrollo basado en equipos. Con TIBCO® Cloud Mesh, accesible a través de TCI, sus integradores pueden compartir, descubrir y reutilizar fácilmente activos digitales creados en toda la empresa dentro de TIBCO Cloud, como APIs y aplicaciones, y utilizarlos muy rápidamente dentro de las integraciones de manera segura sin necesidad de preocuparse por aspectos técnicos.
Esta capacidad promueve la reutilización de activos existentes y una mejor colaboración entre equipos. Combinado con conectores preempaquetados que son directamente accesibles dentro de TCI, el tiempo de desarrollo para introducir nuevas integraciones se reduce significativamente.
Acceda fácilmente a conectores preempaquetados dentro de un mercado de conectores integrado
TCI también amplía el número de personas en su negocio que pueden crear integraciones, con múltiples experiencias de desarrollo que están adaptadas para diferentes roles, proporcionando su propia experiencia y habilidades. Ahora no solo los especialistas en integración pueden participar en el proceso de integración, sino también los desarrolladores, propietarios de productos API e integradores ciudadanos.
Esto aumenta drásticamente la agilidad empresarial porque sus diversas unidades de negocio pueden crear integraciones de manera autoservicio, colaborar para proporcionar soluciones incluso si abarcan diferentes unidades de negocio, y reducir sus dependencias en equipos de TI sobrecargados. Esto libera a sus especialistas en integración para que se concentren en proporcionar las mejores prácticas de integración para su empresa y en diseñar una arquitectura de aplicaciones receptiva.
TCI aborda una serie de casos de uso de integración, incluyendo:
Conectar aplicaciones, datos y dispositivos que residen en cualquier lugar (por ejemplo, en las instalaciones, SaaS, nube privada/pública)
Diseñar, orquestar y gestionar APIs y microservicios
Rearquitecturar aplicaciones monolíticas inflexibles en aplicaciones nativas de la nube altamente escalables.
Construir aplicaciones impulsadas por eventos que procesan flujos de datos (por ejemplo, de dispositivos IoT o Apache Kafka)
TCI también proporciona información detallada sobre el rendimiento y el estado de ejecución de sus integraciones para que pueda optimizarlas según sea necesario o detectar y resolver fácilmente cualquier problema potencial con ellas. Esto asegura que los procesos empresariales que dependen de sus integraciones se vean mínimamente interrumpidos.
Obtenga vistas rápidas de la ejecución de aplicaciones y detalles de rendimiento.Profundice para obtener información ampliada sobre los historiales de ejecución de aplicaciones y las tendencias de rendimiento.
Al incorporar a más personas en su proceso de integración, empoderándolas con una vista inmersiva que les ayuda a trabajar juntos sin problemas en sus integraciones, proporcionando capacidades como TIBCO Cloud Mesh y conectores preempaquetados dentro de un mercado de conectores unificado que acelera el desarrollo de integraciones, su negocio digital puede conectarse y reconectarse muy rápidamente para responder a los mercados cambiantes, lo que aumenta enormemente su agilidad empresarial.
Para experimentar lo fácil que es conectar todos sus activos digitales para aumentar su agilidad empresarial, regístrese hoy para una prueba gratuita de 30 días de TIBCO Cloud Integration.
TIBCO Cloud Integration es un servicio proporcionado dentro de la Plataforma de Inteligencia Conectada de TIBCO, que proporciona un conjunto completo de capacidades para conectar su negocio.
La Plataforma de Contenedores Gestionada está revolucionando todo. Estamos viviendo en una época donde el desarrollo y el panorama de TI están cambiando, nuevos paradigmas como microservicios y contenedores parecen estar presentes desde hace algunos años, y si confiamos en la realidad que los blogs y artículos muestran hoy, todos los usuarios ya los estamos usando todo el tiempo.
¿Has visto alguna publicación de blog sobre cómo desarrollar una aplicación J2EE que se ejecute en tu servidor Tomcat local? Probablemente no. El artículo más similar probablemente debería ser cómo contenerizar tu aplicación basada en Tomcat.
¿Pero sabes qué? La mayoría de las empresas todavía están trabajando de esa manera. Así que incluso si todas las empresas tienen un nuevo enfoque digital en algunos departamentos, también tienen otros que son más tradicionales.
Entonces, parece que necesitamos encontrar una manera diferente de traducir las principales ventajas de una plataforma basada en contenedores a un tipo de discurso que puedan ver y darse cuenta de los beneficios tangibles que pueden obtener de allí y tener el espíritu de «¡Hey, esto puede funcionar para mí!».
1. Obtendrás todos los componentes aislados y actualizados más rápidamente
Esa es una de las grandes cosas sobre las plataformas basadas en contenedores en comparación con enfoques anteriores como las plataformas basadas en servidores de aplicaciones. Cuando tienes un clúster de servidores de aplicaciones, todavía tienes un clúster con varias aplicaciones. Así que usualmente haces algo de aislamiento, mantienes aplicaciones relacionadas, proporcionas infraestructura independiente para las críticas, y así sucesivamente.
Pero incluso con eso, a algún nivel, la aplicación continúa estando acoplada, por lo que algunos problemas con algunas aplicaciones podrían derribar otra que no se esperaba por razones comerciales.
Con una plataforma basada en contenedores, obtienes cada aplicación en su burbuja, por lo que cualquier problema o error afectará a esa aplicación y nada más. La estabilidad de la plataforma es una prioridad para todas las empresas y todos los departamentos dentro de ellas. Solo pregúntate: ¿Quieres terminar con esas «cadenas de dominó» de fallos? ¿Cuánto mejorarán tus operaciones? ¿Cuánto aumentará tu felicidad?
Además, basado en el enfoque de contenedores, obtendrás componentes más pequeños. Cada uno de ellos realizará una sola tarea proporcionando una única capacidad a tu negocio, lo que significa que será mucho más fácil de actualizar, probar y desplegar en producción. Así que, al final, generará más despliegues en el entorno de producción y reducirá el tiempo de comercialización de tus capacidades empresariales.
Podrás desplegar más rápido y tener operaciones más estables al mismo tiempo.
2.- Optimizarás el uso de tu infraestructura
Costos, todo se trata de costos. No hay conversaciones con clientes que no estén tratando de pagar menos por su infraestructura. Así que, enfrentémoslo. Deberíamos poder ejecutar operaciones de manera optimizada. Así que, si el costo de nuestra infraestructura está aumentando, eso necesita significar que nuestro negocio está creciendo.
Las plataformas basadas en contenedores permitirán optimizar la infraestructura de dos maneras diferentes. Primero, si se utilizan dos conceptos principales: Elasticidad y Compartición de Infraestructura.
La elasticidad está relacionada porque solo voy a tener la infraestructura que necesito para soportar la carga que tengo en este momento. Así que, si la carga aumenta, mi infraestructura aumentará para manejarla, pero después de que ese momento pase, volverá a lo que necesita ahora después de que ese pico haya ocurrido.
La compartición de infraestructura se trata de usar cada parte del servidor que está libre para desplegar otras aplicaciones. Imagina un enfoque tradicional donde tengo dos servidores para mi conjunto de aplicaciones. Probablemente no tengo un uso del 100% de esos servidores porque necesito tener algo de capacidad de reserva para poder actuar cuando la carga aumente. Probablemente tengo un 60–70% de uso. Eso significa un 30% libre. Si tenemos diferentes departamentos con diferentes sistemas, y cada uno tiene su infraestructura con un 30% libre, ¿cuánta de nuestra infraestructura estamos simplemente desperdiciando? ¿Cuántos dólares/euros/libras estás simplemente tirando por la ventana?
Las plataformas basadas en contenedores no necesitan herramientas o software específicos instalados en la plataforma para ejecutar un tipo diferente de aplicación. No es necesario porque todo reside dentro del contenedor, por lo que puedo usar cualquier espacio libre para desplegar otras aplicaciones haciendo un uso más eficiente de esos.
3.- No necesitarás infraestructura para administración
Cada sistema que es lo suficientemente grande tiene algunos recursos dedicados para poder gestionarlo. Sin embargo, incluso la mayoría de las arquitecturas recomendadas recomiendan colocar esos componentes aislados de tus componentes de tiempo de ejecución para evitar cualquier problema relacionado con el administrador o el mantenimiento que pueda afectar tus cargas de trabajo de tiempo de ejecución, lo que significa infraestructura específica que estás usando para algo que no está ayudando a tu negocio. Por supuesto, puedes explicar a cualquier usuario de negocio que necesitas una máquina para ejecutar que proporcione las capacidades requeridas. Pero es más complejo que usar infraestructura adicional (y generar costo) para colocar otros componentes que no están ayudando al negocio.
Así que, las plataformas de contenedores gestionadas eliminan ese problema porque vas a proporcionar la infraestructura que necesitas para ejecutar tus cargas de trabajo, y se te proporcionarán de forma gratuita o por una tarifa tan baja las capacidades de administración. Y además de eso, ni siquiera necesitas preocuparte de que las funciones de administración estén siempre disponibles y funcionando bien porque esto se apoya en el propio proveedor.
Conclusión y próximos pasos
Como puedes ver, describimos beneficios muy tangibles que no están basados en la industria o enfocados en el desarrollo. Por supuesto, podemos tener muchos más para agregar a esta lista, pero estos son los críticos que afectan a cualquier empresa en cualquier industria en todo el mundo. Así que, por favor, tómate tu tiempo para pensar en cómo estas capacidades pueden ayudar a mejorar tu negocio. Pero no solo eso, tómate tu tiempo para cuantificar cómo eso mejorará tu negocio. ¿Cuánto puedes ahorrar? ¿Cuánto puedes obtener de este enfoque?
Y cuando tengas frente a ti un caso de negocio sólido basado en este enfoque, obtendrás todo el apoyo y el coraje que necesitas para avanzar en esa ruta. ¡Así que te deseo una transición pacífica!
Aprende cómo puedes incluir el registro de Harbor en tu conjunto de herramientas DevSecOps para aumentar la seguridad y gestión en tu plataforma basada en contenedores
Con la transición a un proceso de desarrollo más ágil donde el número de implementaciones ha aumentado de manera exponencial. Esa situación ha hecho que sea bastante complejo mantener el ritmo para asegurarnos de que no solo estamos implementando código más a menudo en producción que proporciona las capacidades requeridas por el negocio. Sino que, al mismo tiempo, podemos hacerlo de manera segura y confiable.
Esa necesidad está llevando hacia la idea de DevSecOps para incluir la seguridad como parte de la cultura y prácticas de DevOps como una forma de garantizar la seguridad desde el principio en el desarrollo y a lo largo de todos los pasos estándar desde la máquina del desarrollador hasta el entorno de producción.
Además de eso, debido al paradigma de los contenedores, tenemos un enfoque más políglota con diferentes tipos de componentes ejecutándose en nuestra plataforma utilizando una imagen base diferente, paquetes, bibliotecas, etc. Necesitamos asegurarnos de que sigan siendo seguros de usar y necesitamos herramientas para poder gobernar eso de manera natural. Para ayudarnos en esa tarea es donde componentes como Harbor nos ayudan a hacerlo.
Harbor es un proyecto de CNCF en la etapa de incubación en el momento de escribir este artículo, y proporciona varias capacidades sobre cómo gestionar imágenes de contenedores desde una perspectiva de proyecto. Ofrece un enfoque de proyecto con su registro de docker y también un museo de gráficos si queremos usar Helm Charts como parte de nuestro desarrollo de proyectos. Pero también incluye características de seguridad, y esa es la que vamos a cubrir en este artículo:
Escaneo de Vulnerabilidades: te permite escanear todas las imágenes de docker registradas en los diferentes repositorios para verificar si tienen vulnerabilidades. También proporciona automatización durante ese proceso para asegurarse de que cada vez que empujamos una nueva imagen, esta se escanea automáticamente. Además, permitirá definir políticas para evitar extraer cualquier imagen con vulnerabilidades y también establecer el nivel de vulnerabilidades (bajo, medio, alto o crítico) que nos gustaría tolerar. Por defecto, viene con Clair como el escáner predeterminado, pero también puedes introducir otros.
Imágenes firmadas: el registro de Harbor proporciona opciones para desplegar notary como parte de sus componentes para poder firmar imágenes durante el proceso de empuje para asegurarse de que no se realicen modificaciones a esa imagen
Inmutabilidad de Etiquetas y Reglas de Retención: el registro de Harbor también proporciona la opción de definir la inmutabilidad de etiquetas y reglas de retención para asegurarse de que no haya ningún intento de reemplazar imágenes con otras usando la misma etiqueta.
El registro de Harbor se basa en docker, por lo que puedes ejecutarlo localmente usando docker y docker-compose siguiendo el procedimiento disponible en su página web oficial. Pero también admite ser instalado sobre tu plataforma Kubernetes usando el helm chart y el operador que están disponibles.
Una vez que la herramienta está instalada, tenemos acceso al Portal Web de la UI, y podemos crear un proyecto que tenga repositorios como parte de él.
Lista de Proyectos dentro del Portal UI de Harbor
Como parte de la configuración del proyecto, podemos definir las políticas de seguridad que nos gustaría proporcionar a cada proyecto. Eso significa que diferentes proyectos pueden tener diferentes perfiles de seguridad.
Configuraciones de seguridad dentro de un Proyecto en el Portal UI de Harbor
Y una vez que empujamos una nueva imagen al repositorio que pertenece a ese proyecto, vamos a ver los siguientes detalles:
En este caso, he empujado una aplicación de TIBCO BusinessWorks Container Edition que no contiene ninguna vulnerabilidad y solo muestra eso y también dónde se verificó.
Además, si vemos los detalles, podemos verificar información adicional como si la imagen ha sido firmada o no, o poder verificarla nuevamente.
Detalles de la imagen dentro del Portal UI de Harbor
Resumen
Así que, estas son solo algunas características que Harbor proporciona desde la perspectiva de seguridad. Pero Harbor es mucho más que solo eso, así que probablemente cubramos más de sus características en futuros artículos. Espero que, basado en lo que leíste hoy, te gustaría darle una oportunidad y comenzar a introducirlo en tu conjunto de herramientas DevSecOps.