Use Function e eventgrid para realizar a análise automática e a conversão do registro da conta de armazenamento

Este artigo ainda é a ideia anterior. No artigo anterior, compartilhamos uma ideia. Você pode baixar o log de acesso da conta de armazenamento por meio do script do PowerShell e carregá-lo automaticamente no Log Analytics, para que possa ser diretamente em LA Analise e consulte o log. Embora esse método seja simples e conveniente, não é um método automatizado, afinal. Depois de expandir nossas ideias, podemos também tentar usar o eventgrid combinado com a função para converter esse método em uma solução automatizada.

Primeiro, vamos primeiro popularizar o que EventGrid e Function são

EventGrid

Com o Azure Event Grid, os aplicativos podem ser gerados facilmente usando uma arquitetura baseada em eventos. Primeiro, selecione o recurso do Azure no qual deseja se inscrever e, em seguida, forneça um manipulador de eventos ou ponto de extremidade WebHook para o qual enviar eventos. A grade de eventos inclui suporte integrado para eventos de serviços do Azure, como blobs de armazenamento e grupos de recursos. A grade de eventos também suporta seus próprios eventos usando temas customizados.

Simplificando, é como um gatilho, que pode acionar vários eventos e, em seguida, dar respostas direcionadas. Parece um pouco como gatilhos em aplicativos lógicos, mas o eventgrid é apenas uma ferramenta simples de transferência de eventos, métodos de processamento downstream Completamente preenchido por outros produtos, a seguinte imagem também pode ser vista onde a eventgrid está localizada, semelhante a uma fila de mensagens para transmissão de eventos

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

Imagem 1.png

Função

Azure Functions é uma solução sem servidor que permite aos usuários reduzir a escrita de código, reduzir a infraestrutura que precisa ser mantida e economizar custos. Não há necessidade de se preocupar com a implantação e manutenção de servidores, a infraestrutura em nuvem fornece todos os recursos mais recentes necessários para manter os aplicativos em execução.

A função é realmente mais fácil de entender. Agora, todas as nuvens têm basicamente produtos semelhantes. Se você comparar horizontalmente, é AWS lambda, uma plataforma de execução de código totalmente gerenciada

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

Combinando a figura acima, podemos realmente ver nosso pensamento. Eventgird tem gatilhos de blob embutidos, o que significa que quando um novo blob aparece, ele irá automaticamente disparar o eventgrid e procedimentos de processamento downstream, podemos combinar a função para Sim, o código já está pronto, basta usar o anterior, ele só precisa ser alterado um pouco, a carga de trabalho geral é muito pequena

Claro, há realmente um problema oculto aqui, porque o log da conta de armazenamento é armazenado no contêiner $ logs e esse contêiner não acionará o eventgrid no back-end do Azure. Isso é um pouco complicado. O método que usamos é para criar uma função , E, em seguida, use o azcopy para sincronizar periodicamente a sincronização do log com outro contêiner. Apenas uma linha de código é fácil, então não vou escrever por agora.

Etapas de implementação

Vejamos as etapas de implementação específicas abaixo. Primeiro, crie um aplicativo de funções. A relação entre o aplicativo de funções e a função é muito simples. O aplicativo de funções é equivalente à plataforma em que a função é executada. O código é executado nesta plataforma. O aplicativo de funções pode conter muitos Função

Criar aplicativo de funções

O processo de criação de aplicativos de funções é muito simples, escolhemos o tempo de execução como PowerShell Core

Figura 2.png

Criar Função 

Depois que o aplicativo de funções é criado, você pode criar funções nele. O Azure, na verdade, tem uma função de gatilho de grade de evento integrada, basta selecioná-la ao criá-la

Figura 4.png


WeChat screenshot_20210112104638.png


Criar assinatura de grade de eventos

A função está pronta, então você pode preparar a grade de eventos, você pode criar a assinatura da grade de eventos diretamente na função

Figura 5.png

Ao criar a assinatura da grade de eventos, existem muitos tipos que podem ser selecionados. Aqui, escolha o tipo de armazenamento.

Figura 6.png


Configure o tipo de evento da conta de armazenamento

Imagem 7.png


Então preste atenção na necessidade de configurar o filtro, pois temos que limitar o caminho a um intervalo específico, nem todos os blobs irão disparar eventos

Figura 8.png

O gatilho também está pronto, e então você pode preparar o código para ser processado na função

Escrever código

Como o código anterior é processado em um loop e o eventgrid é realmente empurrado um por um, a lógica aqui precisa ser ligeiramente ajustada

Função Build-Signature ($ customerId, $ sharedKey, $ date, $ contentLength, $ method, $ contentType, $ resource) 
{ 
    $ xHeaders = "x-ms-date:" + $ date 
    $ stringToHash = $ method + "` n "+ $ contentLength +" `n" + $ contentType + "` n "+ $ xHeaders +" `n" + $ resource 

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

    $ sha256 = Novo objeto System.Security.Cryptography.HMACSHA256 
    $ sha256.Key = $ keyBytes 
    $ CalculadoHash = $ sha256.ComputeHash ($ bytesToHash) 
    $ encodedHash = [Convert] :: ToBase64String ($ CalculadoHash) 
    $ autorização = 'SharedKey {0}: {1}' -f $ customerId,$ encodedHash 
    retorna $ autorização 
}

Função Post-LogAnalyticsData ($ customerId, $ sharedKey, $ body, $ logType) 
{ 

    

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

    $ headers = @ {
        "Autorização" = $ assinatura; 
        "Log-Type" = $ logType; 
        "x-ms-date" = $ rfc1123date; 
        "campo gerado pelo tempo" = $ TimeStampField; 
    } 

    $ response = Invoke-WebRequest -Uri $ uri -Method $ method -ContentType $ contentType -Headers $ headers -Body $ body -UseBasicParsing 
    return $ response.StatusCode 
} 

Função ConvertSemicolonToURLEncoding ([String] $ InputText) 
{ 
    $ ReturnText = "" 
    $ chars = $ InputText.ToCharArray () 



    $ StartConvert = $ false 



    foreach ($ c em $ chars) 
    { 
        if ($ c -eq '"') { 
            $ StartConvert =! $ StartConvert 
        }


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

    return $ ReturnText 
} 

Função 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 
} 

Função ConvertLogLineToJson ([String] $ logLine) 
{


    $ logLineEncoded = ConvertSemicolonToURLEncoding ($ logLine) 

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

    

    $ FormattedElements = New-Object System.Collections.ArrayList 
                
    foreach ($ element in $ elements) 
    { 

        $ NewText = FormalizeJsonValue ($ element) 
        $ FormattedElements .Add ($ NewText)> null 
    } 
    $ Columns =  
    ("version-number", 
        "request-start-time", 
        "operation-type", 
        "request-status", 
        "http-status-code", 
        "end- latência-final-em-ms ", 
        " latência-servidor-em-ms ", 
        " tipo de autenticação ",
        "requester-account-name",
        "owner-account-name", 
        "service-type", 
        "request-url", 
        "required-object-key", 
        "request-id-header", 
        "operation-count", 
        "requester-ip-address", 
        "request-version-header", 
        "request-header-size", 
        "request-packet-size", 
        "response-header-size", 
        "response-packet-size", 
        "request-content-length", 
        "request -md5 ", 
        " server-md5 ", 
        " etag-identifier ", 
        " última modificação ",
        "conditions-used", 
        "user-agent-header", 
        "referrer-header", 
        "client-request-id" 
    ) 

    $ 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 "A conta de armazenamento especificada não existe nesta assinatura." 
} 

$ storageContext = $ storageAccount.



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

Write-Output ("> Baixando blob: {0}" -f $ blob) 
$ filename = ". \ log .txt " 
Get-AzStorageBlobContent -Context $ storageContext -Container $ container -Blob $ blob -Destination $ filename -Force> Null 
Write-Output ("> Registros de postagem para log do espaço de trabalho analítico: {0} "-f $ blob) 

$ linhas = Get-Content $ filename 

foreach ($ linha em $ linhas) 
        { 
            $ json = ConvertLogLineToJson ($ linha)
           

            $ 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 "> Falha ao postar um log no espaço de trabalho do Log Analytics" 
            } 
        } 

        remove-item $ filename -Force 

    


Write-Output "> Linhas de log postadas no espaço de trabalho do Log Analytics: success = $ successPost, failure = $ failedPost "


A última etapa é autorizar o aplicativo de funções a acessar o armazenamento. Esta etapa não será discutida em detalhes. Você também pode usar a chave da conta de armazenamento para fazer isso. Claro, esse método não é muito recomendado.

Por fim, você pode ver o efeito concluído no monitoramento na função

Figura 10.png

Resumindo

De modo geral, em comparação com a maneira de usar o script do PowerShell sozinho, não mudou muito, mas por causa da adição de eventgrid e função, toda a solução se tornou mais flexível. Ideias semelhantes também podem ser estendidas para muitas outras tarefas para serem mais nebulosas. para olhar e lidar com problemas de uma maneira nativa

Acho que você gosta

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