Utilice Function y eventgrid para realizar análisis y conversión automáticos del registro de la cuenta de almacenamiento

Este artículo sigue siendo la idea anterior. En el artículo anterior, compartimos una idea. Puede descargar el registro de acceso de la cuenta de almacenamiento a través del script de PowerShell y luego cargarlo automáticamente en Log Analytics, para que pueda estar directamente en LA Analizar y consultar el registro. Aunque este método es simple y conveniente, no es un método automatizado después de todo. Después de expandir nuestras ideas, podríamos intentar usar eventgrid combinado con función para convertir este método en una solución automatizada.

Primero, popularicemos primero qué son EventGrid y Function

EventGrid

Con Azure Event Grid, las aplicaciones se pueden generar fácilmente mediante una arquitectura basada en eventos. Primero, seleccione el recurso de Azure al que desea suscribirse y luego proporcione un controlador de eventos o un punto de conexión de WebHook al que enviar eventos. La cuadrícula de eventos incluye compatibilidad integrada para eventos de servicios de Azure, como blobs de almacenamiento y grupos de recursos. La cuadrícula de eventos también admite sus propios eventos utilizando temas personalizados.

En pocas palabras, es como un disparador, que puede disparar varios eventos y luego dar respuestas específicas. Suena un poco como disparadores en aplicaciones lógicas, pero eventgrid es solo una herramienta simple de transferencia de eventos, métodos de procesamiento posteriores Completamente completada por otros productos, la siguiente imagen también se puede ver donde se encuentra la cuadrícula de eventos, similar a una cola de mensajes para la transmisión de eventos.

https://docs.microsoft.com/en-us/azure/event-grid/?WT.mc_id=AZ-MVP-5001235

Imagen 1.png

Función

Azure Functions es una solución sin servidor que permite a los usuarios reducir la escritura de código, reducir la infraestructura que debe mantenerse y ahorrar costos. No es necesario preocuparse por la implementación y el mantenimiento de los servidores, la infraestructura de la nube proporciona todos los recursos más recientes necesarios para mantener las aplicaciones en ejecución.

La función es realmente más fácil de entender. Ahora todas las nubes tienen básicamente productos similares. Si lo comparas horizontalmente, es AWS lambda, una plataforma de ejecución de código completamente administrada

https://docs.microsoft.com/zh-cn/azure/azure-functions/functions-overview?WT.mc_id=AZ-MVP-5001235

Combinando la figura anterior, podemos ver nuestro pensamiento. Eventgird tiene activadores de blobs incorporados, lo que significa que cuando aparece un blob nuevo, activará automáticamente eventgrid, y los procedimientos de procesamiento posteriores, podemos combinar la función para Sí, el código está realmente listo, solo use el anterior, solo necesita cambiarse ligeramente, la carga de trabajo general es muy pequeña

Por supuesto, en realidad hay un problema oculto aquí, porque el registro de la cuenta de almacenamiento se almacena en el contenedor $ logs, y este contenedor no activará la cuadrícula de eventos en el backend de Azure. Esto es un poco complicado. El método que usamos es crear una función , Y luego use azcopy para sincronizar periódicamente la sincronización de registros con otro contenedor. Solo una línea de código es fácil, por lo que no la escribiré por ahora.

Pasos de implementación

Veamos los pasos de implementación específicos a continuación. Primero, cree una aplicación de función. La relación entre la aplicación de función y la función es muy simple. La aplicación de función es equivalente a la plataforma en la que se ejecuta la función. El código se ejecuta en esta plataforma. La aplicación de función puede contener muchos Función

Crear aplicación de función

El proceso de creación de la aplicación de funciones es muy simple, elegimos el tiempo de ejecución como PowerShell Core

Imagen 2.png

Crear función 

Una vez creada la aplicación Función, puede crear funciones en ella. Azure en realidad tiene una función de desencadenador de cuadrícula uniforme incorporada, simplemente selecciónela al crearla

Imagen 4.png


WeChat screenshot_20210112104638.png


Crear suscripción a Event Grid

La función está lista, luego puede preparar eventgrid, puede crear una suscripción a la cuadrícula de eventos directamente en la función

Imagen 5.png

Al crear una suscripción a la cuadrícula de eventos, hay muchos tipos que se pueden seleccionar. Aquí, elija el tipo de almacenamiento.

Imagen 6.png


Configurar el tipo de evento de la cuenta de almacenamiento

Imagen 7.png


Luego preste atención a la necesidad de configurar el filtro, porque tenemos que limitar la ruta a un rango específico, no todos los blobs dispararán eventos

Imagen 8.png

El disparador también está listo, y luego puede preparar el código para ser procesado en la función

Escribir código

Debido a que el código anterior se procesa en un bucle, y eventgrid se empuja uno por uno, la lógica aquí debe ajustarse ligeramente

Función Build-Signature ($ customerId, $ sharedKey, $ date, $ contentLength, $ method, $ contentType, $ resource) 
{ 
    $ xHeaders = "x-ms-date:" + $ date 
    $ stringToHash = $ método + "` n "+ $ contentLength +" `n" + $ contentType + "` n "+ $ xHeaders +" `n" + $ recurso 

    $ bytesToHash = [Text.Encoding] :: UTF8.GetBytes ($ stringToHash) 
    $ keyBytes = [Convertir ] :: FromBase64String ($ sharedKey) 

    $ sha256 = New-Object System.Security.Cryptography.HMACSHA256 
    $ sha256.Key = $ keyBytes 
    $ calculadoHash = $ sha256.ComputeHash ($ bytesToHash) 
    $ encodedHash = [Convertir] :: ToBase64String ($ calculadoHash) 
    $ autorización = 'SharedKey {0}: {1}' -f $ customerId,$ encodedHash 
    return $ autorización 
}

Función Post-LogAnalyticsData ($ customerId, $ sharedKey, $ body, $ logType) 
{ 

    

    $ method = "POST" 
    $ contentType = "application / json" 
    $ resource = "/ api / logs" 
    $ rfc1123date = [DateTime] :: UtcNow .ToString ( "r") 
    $ = $ contentLength body.Length 
    $ = firma Build-firma ` 
        -customerId $ customerId` 
        -sharedKey $ sharedkey ` 
        -date $ rfc1123date` 
        -contentLength $ contentLength ` 
        método $ -method` 
        -contentType $ contentType ` 
        -resource $ resource 
    $ uri =" https: // "+ $ customerId +" .ods.opinsights.azure.com "+ $ resource +"? api-version = 2016-04-01 " 

    $ headers = @ {
        "Autorización" = $ firma; 
        "Tipo de registro" = $ logType; 
        "x-ms-date" = $ rfc1123date; 
        "campo-generado-por-tiempo" = $ TimeStampField; 
    } 

    $ respuesta = Invoke-WebRequest -Uri $ uri -Method $ método -ContentType $ contentType -Headers $ encabezados -Body $ body -UseBasicParsing 
    return $ response.StatusCode 
} 

Función ConvertSemicolonToURLEncoding ([String] $ InputText) 
{ 
    $ ReturnText = "" 
    $ caracteres = $ InputText.ToCharArray () 



    $ StartConvert = $ false 



    foreach ($ c en $ caracteres) 
    { 
        if ($ c -eq '"') { 
            $ StartConvert =! $ StartConvert 
        }


        if ($ StartConvert -eq $ true -and $ c -eq ';') 
        { 
            $ ReturnText + = "% 3B" 
        } else { 
            $ ReturnText + = $ c 
        } 
    } 

    return $ ReturnText 
} 

Función FormalizeJsonValue ($ Text) 
{ 
    $ Text1 = "" 
    if ($ Text.IndexOf ("` "") -eq 0) {$ Text1 = $ Text} else {$ Text1 = "` "" + $ Text + "` ""} 
    if ($ Text1.IndexOf ("% 3B") -ge 0) { 
        $ ReturnText = $ Text1.Replace ("% 3B", ";") 
    } else { 
        $ ReturnText = $ Text1 
    } 
    return $ ReturnText 
} 

Función ConvertLogLineToJson ([String] $ logLine) 
{


    $ logLineEncoded = ConvertSemicolonToURLEncoding ($ logLine) 

    $ elementos = $ logLineEncoded.split (';') 

    

    $ FormattedElements = New-Object System.Collections.ArrayList 
                
    foreach ($ elemento en $ elementos) 
    { 

        $ NewText = FormalizeJsonValue ($ elemento) 
        $ FormattedElements .Añadir ($ NewText)> null 
    } 
    $ Columns =  
    ("número-versión", 
        "hora de inicio de la solicitud", 
        "tipo-operación", 
        "estado-solicitud", 
        "código-estado-http", 
        "fin- a-latencia-final-en-ms ", 
        " latencia-del-servidor-en-ms ", 
        " tipo de autenticación ",
        "nombre-cuenta-solicitante",
        "nombre-cuenta-propietario", 
        "encabezado-referente",
        "tipo-servicio", 
        "url-solicitud", 
        "clave-objeto-solicitada", 
        "encabezado-id-solicitud", 
        "recuento-operación", 
        "dirección-IP-solicitante", 
        "encabezado-solicitud-versión", 
        "request-header-size", 
        "request-packet-size", 
        "response-header-size", 
        "response-packet-size", 
        "request-content-length", 
        "request-md5", 
        "server-md5 ", 
        " identificador-etag ", " hora-de 
        -última-modificación ", 
        " condiciones-utilizadas ",
        "encabezado-agente-usuario", 
        "id-solicitud-cliente" 
    ) 

    $ logJson = "[{";
    Para ($ i = 0; $ i -lt $ Columns.Length; $ i ++) 
    { 
        $ logJson + = "` "" + $ Columns [$ i] + "` ":" + $ FormattedElements [$ i] 
        if ( $ i -lt $ Columns.Length - 1) { 
            $ logJson + = "," 
        } 
    } 
    $ logJson + = "}]"; 

    return $ logJson 
} 

$ storageAccount = Get-AzStorageAccount -ResourceGroupName $ ResourceGroup -Name $ StorageAccountName -ErrorAction SilentlyContinue 
if ($ null -eq $ storageAccount) 
{ 
    throw "La cuenta de almacenamiento especificada no existe en esta suscripción". 
} 

$ storageContext = $ storageAccount.



$ asunto = $ eventGridEvent.subject.ToString () 
$ BlobArray = $ sujeto.Split ('/') 
$ contenedor = $ BlobArray [$ BlobArray.indexof ('contenedores') + 1] 
$ BlobIndex = $ sujeto.indexof (' blobs / ') + 6 
$ Blob = $ subject.substring ($ BlobIndex, $ subject.length - $ BlobIndex) 

Salida de escritura ("> Descarga de blob: {0}" -f $ blob) 
$ filename = ". \ log .txt " 
Get-AzStorageBlobContent -Context $ storageContext -Container $ container -Blob $ blob -Destination $ filename -Force> Null 
Write-Output ("> Publicar registros en el espacio de trabajo analítico: {0} "-f $ blob) 

$ líneas = Get-Content $ nombre de archivo 

foreach ($ línea en $ líneas) 
        { 
            $ json = ConvertLogLineToJson ($ línea)
           

            $ response = Post-LogAnalyticsData -customerId $ customerId -sharedKey $ sharedKey -body ([System.Text.Encoding] :: UTF8.GetBytes ($ json)) -logType $ logType 

            if ($ response -eq "200") { 
                $ successPost ++ 
            } else {  
                $ failedPost ++ 
                Write-Output "> No se pudo publicar un registro en el espacio de trabajo de Log Analytics" 
            } 
        } 

        remove-item $ filename -Force 

    


Write-Output "> Líneas de registro publicadas en el espacio de trabajo de Log Analytics: éxito = $ successPost, failure = $ failedPost "


El último paso es autorizar a la aplicación de función a acceder al almacenamiento. Este paso no se discutirá en detalle. También puedes usar la clave de la cuenta de almacenamiento para hacerlo. Por supuesto, este método no es muy recomendable.

Finalmente, puede ver el efecto completo en el monitoreo en la función

Imagen 10.png

para resumir

En términos generales, no ha cambiado mucho en comparación con la forma de usar simplemente scripts de PowerShell, pero debido a la adición de eventgrid y funciones, toda la solución se ha vuelto más flexible. Ideas similares también se pueden extender a muchas otras tareas para estar más basadas en la nube. para mirar y tratar los problemas de forma nativa

Supongo que te gusta

Origin blog.51cto.com/mxyit/2588527
Recomendado
Clasificación