Responsável por gerenciar a configuração do Windows. História de sucesso

Em uma das reuniões da comunidade .net de St. Petersburg dos desenvolvedores da comunidade SpbDotNet, realizamos um experimento e decidimos falar sobre como você pode aplicar abordagens que há muito se tornaram padrão no mundo Linux para automatizar as infraestruturas do Windows. Mas, para não levar tudo ao ponto de sinalizar o sinalizador Ansible, decidiu-se mostrar isso pelo exemplo da implantação de um aplicativo ASP.Net.


Aleksey Chernov, desenvolvedor sênior da equipe que desenvolve a biblioteca de componentes de interface do usuário para nossos projetos, ofereceu-se como orador. E sim, não lhe pareceu: um desenvolvedor de JavaScript esteve na frente de um público .Net.


Qualquer pessoa interessada no resultado de um experimento desse tipo, seja bem-vinda, abaixo do corte para decodificação.



Olá) Eles já estragaram um pouco e disseram que sou um front-end, então você já pode divergir =) Meu nome é Alexei, venho fazendo todo tipo de coisa sobre desenvolvimento da Web há algum tempo. Comecei com Perl, depois havia PHP, um pouco de RoR, um pouco, um pouco disso. E então o JavaScript entrou na minha vida, e desde então eu tenho feito quase tudo isso.


Além do JS, ultimamente tenho escrito muitos autotestes (além disso, no mesmo JS) e, portanto, tenho que lidar com a automação da implantação de bancos de teste e a infraestrutura para eles.


Antecedentes


Dois anos atrás, acabei na Veeam, onde eles estão desenvolvendo produtos para Windows. Naquele momento, fiquei muito surpreso, mas aconteceu que acontece =). Mas, acima de tudo, fiquei surpreso com o nível incomumente baixo de automação de tudo relacionado à implantação, com a implantação de aplicativos, com testes etc.


Nós, aqueles que desenvolvemos para Linux, há muito que estamos acostumados ao fato de que tudo deve estar no Docker, existe o Kubernetes e tudo se desenrola com um único clique. E quando eu acabei em um ambiente onde tudo isso não está lá, chocou. E quando comecei a realizar testes automáticos, percebi que esse sucesso era de apenas 20% e tudo o mais estava preparando a infraestrutura para eles.



Meus sentimentos no começo


Condições atuais


Vou falar um pouco sobre como tudo está organizado conosco, o que precisamos automatizar e o que fazemos.


Temos um monte de produtos diferentes, a maioria deles está no Windows, há vários no Linux e até algo no Solaris. Muitas compilações são coletadas diariamente para todos os produtos. Portanto, é necessário distribuir tudo isso nos laboratórios de teste, tanto para o controle de qualidade quanto para os próprios desenvolvedores, para que eles possam verificar a integração de aplicativos. Tudo isso requer uma enorme infraestrutura de muitos servidores de ferro e máquinas virtuais. E, às vezes, fazemos testes de desempenho, quando precisamos aumentar imediatamente mil máquinas virtuais e ver com que rapidez nossos aplicativos funcionarão.


Os problemas


Obviamente, nos primeiros estágios (leia-se há muito tempo), ao tentar automatizar tudo de frente, o PowerShell era usado. A ferramenta é poderosa, mas os scripts de implantação são extremamente complicados. Outro problema foi a falta de gerenciamento centralizado desse processo. Alguns scripts foram executados localmente por desenvolvedores, outros em máquinas virtuais criadas na era dos mamutes, etc. Como resultado: foi difícil obter um único resultado e entender o que funciona e o que não funciona. Você vem para o trabalho, abra o navegador - o servidor está indisponível. Por que não está disponível, o que aconteceu, onde quebrou - não estava completamente claro. Não havia um único ponto de entrada, e eu tinha que procurar a verdade nas salas de bate-papo em funcionamento, e é bom que alguém atenda.


Outro problema, não tão óbvio, são os novatos. Foi difícil para eles. Na primeira semana de trabalho, eles apenas se aprofundaram no que estava acontecendo. Habitualmente vivíamos com isso, assegurando a nós mesmos que a vida é uma coisa difícil e que devemos atendê-la. Entender e perdoar, por assim dizer.


Mas em algum momento eles encontraram a força interior para superá-la e olhar em volta. Provavelmente, de alguma forma, você pode lidar com isso.



O primeiro passo para resolver o problema é aceitá-lo.


Seleção de solução


Quando você não souber o que fazer, veja o que os outros estão fazendo.


E, para começar, fizemos nossa lista de requisitos para o que queremos obter no final.


  • Base de código unificada. Todos os scripts de implantação devem estar no mesmo local. Deseja implantar algo ou ver como ele se desenrola: aqui está um repositório para você, vá lá.
  • Todo mundo sabe como isso funciona. As perguntas devem desaparecer à la "Eu não entendo como implantá-lo, então no segundo dia não consigo fechar o bug".
  • Capacidade de iniciar pelo botão. Precisamos ser capazes de controlar implantações. Por exemplo, algum tipo de interface da web, para onde você vai, pressione um botão e o produto desejado é implantado no host desejado.

Depois de garantir que essa lista cubra os requisitos mínimos e necessários para a nossa felicidade, começamos a tentar. Tradicionalmente, a primeira coisa que tentavam resolver problemas era o método de ataque frontal. Temos muitos scripts do PowerShell? Então, vamos combiná-los em um repositório. Mas o problema não é que havia muitos scripts, mas que equipes diferentes fizeram a mesma coisa com scripts diferentes. Andei por equipes diferentes, ouvi seus requisitos, coletei os mesmos scripts, tentei pentear e parametrizá-los de alguma forma e depois os coloquei em um único repositório.


Falha: A tentativa falhou. Em primeiro lugar, começamos a discutir muito sobre por que estamos fazendo isso e não dessa maneira. Por que esse método foi usado, e não outro, etc. E, como resultado, havia muitos que queriam refazer tudo "como deveria", com o princípio de "vou bifurcar e reescrever tudo para você". E, é claro, não será possível combinar filiais com essa abordagem.


Tentativa número dois: era necessário pegar nosso servidor de CI (TeamCity), criar alguns modelos e, usando herança, fechar o problema principal desde a primeira tentativa. Mas, como você deve ter adivinhado imediatamente, Fail também estava esperando por nós : você pode usar o modelo apenas para a versão mais recente, o que significa que não obteremos o controle de versão necessário. E a consequência de um grande número de equipes - os modelos se tornaram muitos, tornou-se mais difícil gerenciá-los e, no horizonte, um novo pântano era claramente visível.



Cansado de cair de bruços em qualquer tentativa de decolar, decidiu-se sentar novamente e pensar muito. Portanto, temos um monte de scripts ps, por um lado, e um grande número de virtuais, por outro. Mas estávamos errados, porque essa não era a raiz do problema. O problema era que sempre havia uma pessoa entre essas coisas. Não importa se é um desenvolvedor, um testador ou outra pessoa, a seguinte cadeia lógica sempre ocorreu na cabeça:


  • Então, eu preciso de uma máquina virtual para testes
  • Sim, aqui temos um pool de host
  • E aqui está o script que eu preciso, agora eu vou executá-lo, e tudo vai acontecer

Com a realização de uma coisa aparentemente simples, o problema geral começou a brincar com novas cores. Aconteceu que todas as nossas dores são decorrentes da falta de uma única descrição de nossa infraestrutura. Estava na mente das pessoas que o criaram, eles se sentaram em departamentos diferentes, não tentaram documentá-lo de alguma forma e, geralmente, todos viviam em seu próprio estado separado.
Nesse momento, chegamos à conclusão de que a resposta para todos os nossos problemas é:


Infraestrutura como um código


É precisamente que toda a nossa infraestrutura deve ser descrita em código e colocada no repositório. Todas as máquinas virtuais, todos os seus parâmetros, tudo o que está instalado lá - tudo precisa ser descrito no código.


Surge uma pergunta legítima - por quê?


Respondemos: essa abordagem nos dará a oportunidade de aplicar as melhores práticas do mundo do desenvolvimento, às quais estamos todos tão acostumados:


  • Controle de versão. Sempre podemos entender o que e quando mudou. Não há mais hosts saindo do nada ou indo a lugar nenhum. Sempre ficará claro quem fez as alterações.
  • Revisão de código. Poderemos controlar os processos de implantação para que alguns não violem outros.
  • Integração Contínua.

Seleção de ferramenta


Como todos sabemos, existem muitas ferramentas de gerenciamento de configuração. Optamos pelo Ansible, pois contém um conjunto de recursos que precisamos.
Antes de tudo, queremos que o sistema de automação não execute nenhum instalador, algo para migrar para algum lugar etc. Primeiro de tudo, a partir de um sistema assim, queremos que, depois de pressionar um botão, veremos a interface do aplicativo que precisamos.


Portanto, o principal recurso para nós é a idempotência. Ansible não importa o que aconteceu antes. Depois de iniciar o manual desejado, sempre obtemos o mesmo resultado. Isso é muito importante quando você diz não "Instalar o IIS", mas "Deve haver o IIS", e não precisa pensar se ele já estava lá antes ou não. É muito difícil conseguir isso com scripts, e os manuais Ansible oferecem essa oportunidade.


Também vale mencionar a ausência de agente da Ansible. A maioria dos sistemas de automação trabalha com agentes. Há muitas vantagens nisso - por exemplo, o melhor desempenho -, mas era importante para nós que não houvesse agente para que o sistema não precisasse ser preparado de alguma forma adicional.


PowerShell:


$url = "http://buildserver/build.msi" $output = "$PSSscriptRoot\build.msi" Invoke-WebRequest -Uri $url -OutFile $output 

Ansible:


 name: Download build hosts: all tasks: name: Download installer win_get_url: url: "http://buildserver/build.msi" dest: "build.msi" force: no 

Aqui vemos que no exemplo básico, o script ps será ainda mais conciso do que o manual Ansible. 3 linhas de script versus 7 linhas de playbook para fazer o download de um arquivo.


Mas, Petka, há uma nuance (s). Assim que quisermos aderir ao princípio da idempotência e, por exemplo, para garantir que o arquivo no servidor não tenha sido alterado e não precise ser baixado, será necessário implementar uma solicitação HEAD no script, que adiciona cerca de 200 linhas. E no manual - um. O módulo Ansible win_get_url, que faz todas as verificações para você, contém 257 linhas de código que você não precisa inserir em cada script.


E este é apenas um exemplo de uma tarefa muito simples.



E se você pensar bem, precisamos de idempotência em todos os lugares:


  • Verifique a existência de uma máquina virtual. No caso de scripts, corremos o risco de produzir um número infinito deles, ou o script falhará no início.
  • Quais pacotes msi existem na máquina? Na melhor das hipóteses, nada cairá aqui; na pior das hipóteses, a máquina deixará de funcionar adequadamente.
  • Preciso fazer o download de artefatos de construção novamente? É bom que suas construções pesem uma dúzia de megabytes. E os que têm alguns gigabytes?

E outros exemplos, onde a saída é aumentar os scripts com ramificações infinitas de ifs que não podem ser adequadamente depurados e impossíveis de gerenciar.


Entre outras coisas importantes para nós, o Ansible não usa agentes para gerenciar seus hosts e máquinas. No Linux, é claro, ele roda no ssh, enquanto no Windows o WinRM é usado. Daí a conseqüência óbvia: o Ansible é multiplataforma. Ele suporta um número fantástico de plataformas, até equipamentos de rede.


E o último, mas não menos importante, é o formato de gravação de configuração YAML. Todos estão acostumados, é fácil de ler e é fácil descobrir o que está acontecendo lá.


Mas nem tudo é tão doce, há problemas:


  • O problema é duvidoso: para executar playbooks, você ainda precisa de uma máquina Linux, mesmo que toda a sua infraestrutura seja exclusivamente Windows. Embora este não seja um problema tão grande no mundo moderno, porque no Windows 10, agora existe o WSL, onde você pode executar o Ubuntu, sob o qual direciona playbooks.
  • Às vezes, os playbooks são realmente difíceis de depurar. Ansible é escrito em python, e a última coisa que quero ver é uma folha de pilha de pilha de cinco telas em python. E um erro de digitação no nome do módulo

Como isso funciona?
Primeiro, precisamos de uma máquina Linux. Na terminologia Ansible, isso é chamado de Máquina de Controle.
Os playbooks começarão a partir dele e toda a magia acontece nele.


Nesta máquina, precisaremos de:


  • Python e o gerenciador de pacotes python pip. Muitas distribuições estão prontas para uso, por isso não há surpresas aqui.
  • Instale o Ansible via pip, da maneira mais universal: pip install ansible
  • Adicione um módulo winrm para acessar as máquinas Windows: pip install pywinrm [credssp]
  • E nas máquinas que queremos controlar, precisamos ativar o winrm, porque está desativado por padrão. Há muitas maneiras de fazer isso, e todas são descritas na documentação Ansible. Mas o mais simples é pegar o script finalizado no repositório Ansible e executá-lo com a opção de autorização necessária: ConfigureRemotingForAnsible.ps1 -EnableCredSSP

A parte mais importante que precisávamos para parar de sofrer com os scripts ps foi o Inventory. Um arquivo YAML (no nosso caso), que descreve nossa infraestrutura e onde você sempre pode procurar entender onde isso está implantado. E, é claro, os próprios manuais. No futuro, o trabalho parecerá lançar um manual com o arquivo de inventário necessário e parâmetros adicionais.


 all: children: webservers: hosts: spbdotnet-test-host.dev.local: dbservers: hosts: spbdotnet-test-host.dev.local: vars: ansible_connection: winrm ansible_winrm_transport: credssp ansible_winrm_server_cert_validation: ignore ansible_user: administrator ansible_password: 123qweASD 

Tudo é simples aqui: o grupo raiz é todo e dois subgrupos, servidores da web e dbservers. Tudo o resto é intuitivo, mas chamarei sua atenção para o fato de o Ansible, por padrão, considerar o Linux em todo lugar; portanto, no Windows, você deve especificar o winrm e o tipo de autorização.


A senha de forma clara, é claro, não precisa ser armazenada no manual, aqui está apenas um exemplo. As senhas podem ser armazenadas, por exemplo, no Ansible-Vault. Usamos o TeamCity para isso, que transmite segredos por variáveis ​​de ambiente e não aciona nada.


Módulos


Tudo o que o Ansible faz, faz com a ajuda dos módulos. Módulos para Linux são escritos em python, para Windows no PowerShell. E uma reverência pela idempotência: o resultado do módulo sempre vem na forma de um arquivo json, que indica se houve alterações no host ou não.


No caso geral, executaremos uma construção da lista de módulos do arquivo de inventário do grupo de hosts ansible do formulário:



Playbooks


Um manual é uma descrição de como e onde vamos executar os módulos Ansible.


 - name: Install AWS CLI hosts: all vars: aws_cli_download_dir: c:\downloads aws_cli_msi_url: https://s3.amazonaws.com/aws-cli/AWSCLI32PY3.msi tasks: - name: Ensure target directory exists win_file: path: "{{ aws_cli_download_dir }}" state: directory - name: Download installer win_get_url: url: "{{ aws_cli_msi_url }}" dest: "{{ aws_cli_download_dir }}\\awscli.msi" force: no - name: Install AWS CLI win_package: path: "{{ aws_cli_download_dir }}\\awscli.msi" state: present 

Neste exemplo, temos três tarefas. Cada tarefa é uma chamada de módulo. Neste manual, primeiro criamos um diretório (verifique se ele existe), depois baixamos a CLI da AWS e instalamos usando o módulo win_packge.


Ao executar este manual, obtemos esse resultado.



O relatório mostra que quatro tarefas foram concluídas com êxito e três das quatro fizeram algumas alterações no host.


Mas o que acontece se você executar este manual novamente? Não escrevemos em nenhum lugar que devemos criar o diretório, baixar o arquivo do instalador e executá-lo. Simplesmente verificamos a disponibilidade de cada item e pulamos, se disponível.



Essa é a idempotência que não conseguimos com o PowerShell.


Prática


Este é um exemplo um pouco simplificado, mas, em princípio, é exatamente isso que fazemos todos os dias.
Implementaremos um aplicativo que consiste em um serviço do Windows e um aplicativo da Web no IIS.


 - name: Setup App hosts: webservers tasks: - name: Install IIS win_feature: name: - Web-Server - Web-Common-Http include_sub_features: True include_management_tools: True state: present register: win_feature - name: reboot if installing Web-Server feature requires it win_reboot: when: win_feature.reboot_required 

Primeiro, precisamos verificar se existe algum IIS no host e instalá-lo, se não houver. E seria bom adicionar imediatamente ferramentas de gerenciamento e todos os recursos dependentes. E é muito bom se o host for reiniciado, se necessário.


A primeira tarefa que resolvemos é o módulo win_feature, que está envolvido no gerenciamento de recursos do Windows. E aqui, pela primeira vez, temos as variáveis ​​de ambiente Ansible, no item de registro. Lembre-se, eu disse que as tarefas sempre retornam um objeto json? Agora, depois de concluir a tarefa Instalar IIS, a saída do módulo win_feature fica na variável win_feature (desculpe-me pela tautologia).


Na próxima tarefa, chamamos o módulo win_reboot. Mas não precisamos reiniciar nosso servidor todas as vezes. Nós o recarregaremos apenas se o módulo win_feature retornar esse requisito para nós na forma de uma variável.


O próximo passo é instalar o SQL. Um milhão de maneiras já foram inventadas para fazer isso. Estou usando o módulo win_chocolatey aqui. Este é um gerenciador de pacotes para Windows. Sim, é exatamente com isso que estamos tão acostumados no Linux. Os módulos são suportados pela comunidade e agora já existem mais de seis mil deles. Eu recomendo fortemente que você tente.


 - name: SQL Server hosts: dbservers tasks: - name: Install MS SQL Server 2014 win_chocolatey: name: mssqlserver2014express state: present 

Então, preparamos o host para o lançamento do aplicativo, vamos implantá-lo!


 - name: Deploy binaries hosts: webservers vars: myapp_artifacts: files/MyAppService.zip myapp_workdir: C:\myapp tasks: - name: Remove Service if exists win_service: name: MyAppService state: absent path: "{{ myapp_workdir }}\\MyAppService.exe" 

Por precaução, a primeira coisa que fazemos é excluir o serviço existente.


 - name: Delete old files win_file: path: "{{ myapp_workdir }}\\" state: absent - name: Copy artifacts to remote machine win_copy: src: "{{ myapp_artifacts }}" dest: "{{ myapp_workdir }}\\" - name: Unzip build artifacts win_unzip: src: "{{ myapp_workdir }}\\MyAppService.zip" dest: "{{ myapp_workdir }}" 

A próxima etapa é fazer upload de novos artefatos no host. Este manual implica que ele é executado em um servidor de construção, todos os arquivos estão em uma pasta conhecida e indicamos o caminho para eles com variáveis. Após a cópia (win_copy), os arquivos são descompactados (win_unzip). Depois, basta registrar o serviço, dizer o caminho para o exe e que ele deve ser iniciado.


  - name: Register and start the service win_service: name: ReporterService start_mode: auto state: started path: "{{ myapp_workdir }}\\MyAppService.exe" 

Feito!?


Parece que nosso serviço está pronto para o trabalho e a defesa, no entanto, existe um "mas" - não observamos o princípio da idempotência. Sempre excluímos o código existente e, em seguida, implantamos o novo.


E esse é o problema. Se excluirmos o serviço fora de serviço antigo e após algum tipo de erro e o manual não concluir seu trabalho, obteremos um host com defeito. Ou, por exemplo, implantamos vários aplicativos ao mesmo tempo, dos quais um não foi alterado, e também não precisamos implantá-lo.


O que pode ser feito? Como alternativa, você pode verificar a soma de verificação de nossos artefatos e compará-los com os do servidor.


  - name: Get arifacts checksum stat: path: "{{ myapp_artifacts }}" delegate_to: localhost register: myapp_artifacts_stat - name: Get remote artifacts checksum win_stat: path: "{{ myapp_workdir }}\\MyAppService.zip" register: myapp_remote_artifacts_stat 

Usamos o módulo stat, que fornece todos os tipos de informações sobre arquivos, incluindo a soma de verificação. Em seguida, usando o registro de diretiva familiar, escrevemos o resultado em uma variável. De interessante: delegate_to indica que isso deve ser feito na máquina local em que o manual é iniciado.


  - name: Stop play if checksums match meta: end_play when: - myapp_artifacts_stat.stat.checksum is defined - myapp_remote_artifacts_stat.stat.checksum is defined - myapp_artifacts_stat.stat.checksum == myapp_remote_artifacts_stat.stat.checksum 

E com a ajuda do meta-módulo, dizemos que precisamos terminar o manual se as somas de verificação dos artefatos nas máquinas local e remota corresponderem. Foi assim que observamos o princípio da idempotência.


  - name: Ensure that the WebApp application exists win_iis_webapplication: name: WebApp physical_path: c:\webapp site: Default Web Site state: present 

Agora, vamos olhar para o nosso aplicativo da web. Nós omitimos a parte sobre copiar arquivos, vamos direto ao ponto. Nosso servidor de criação criou o editor, carregou todos os arquivos soltos no host e usou o módulo interno para trabalhar com aplicativos IIS. Ele criará o aplicativo e o executará.


Reutilização de código


Uma das tarefas que definimos foi: permitir que qualquer engenheiro da empresa inicie facilmente uma implantação. Ele escreve seu manual a partir de módulos prontos, diz que precisa executar tal e qual produto em tal host.


Para isso, o Ansible tem funções. Isto é essencialmente uma convenção. Criamos uma pasta / functions / no servidor e colocamos nossas funções nela. Cada função é um conjunto de arquivos de configuração: uma descrição de nossos dispositivos, variáveis, arquivos de serviço etc. Geralmente, alguma entidade isolada desempenha um papel. A instalação do IIS é um ótimo exemplo se precisarmos não apenas instalá-lo, mas também configurá-lo de alguma forma ou verificá-lo com tarefas adicionais. Nós desempenhamos uma função separada e, portanto, isolamos todos os manuais relacionados ao IIS na pasta de funções. No futuro, simplesmente chamamos essa função com a diretiva include_role% role_name%.


Naturalmente, criamos funções para todos os aplicativos, deixando a oportunidade para os engenheiros de alguma forma personalizarem o processo usando parâmetros de configuração.


 - name: Run App hosts: webservers tasks: - name: "Install IIS" include_role: name: IIS - name: Run My App include_role: name: MyAppService vars: myapp_artifacts: ./buld.zip 

Neste exemplo, a função Executar Meu Aplicativo tem a capacidade de transferir algum caminho para artefatos.


Aqui você deve colocar uma palavra sobre o Ansible Galaxy - um repositório de soluções padrão comumente disponíveis. Como de costume em uma sociedade decente, muitos problemas já foram resolvidos diante de nós. E se houver a sensação de que agora começaremos a reinventar a roda, primeiro você precisará examinar a lista de módulos internos e depois mergulhar no Ansible Galaxy. É provável que o manual de que você precisa já tenha sido elaborado por outra pessoa. Há um grande número de módulos lá, para todas as ocasiões.


Mais flexibilidade


Mas e se não houver um módulo embutido ou uma função adequada no Galaxy? Existem duas opções: ou estamos fazendo algo errado ou temos realmente uma tarefa única.


No caso da segunda opção, sempre podemos escrever nosso módulo. Como mostrei a você no início, o Ansible torna possível escrever o módulo mais simples em literalmente 10 minutos, e quando você se aprofunda, documentação bastante detalhada vem em seu auxílio, cobrindo muitas perguntas.


Ci
Em nosso departamento, gostamos muito do TeamCity, mas pode haver qualquer outro servidor de CI de sua escolha. Por que precisamos compartilhá-los?


Em primeiro lugar, sempre podemos verificar a sintaxe de nossos playbooks. Embora o YAML considere as guias um erro de sintaxe, esse é um recurso muito útil.


Também no servidor de CI, executamos o ansible-lint. Este é um analisador estático de configurações ansible, que fornece uma lista de recomendações.



Por exemplo, aqui ele diz que temos um espaço extra no final da linha e, para uma tarefa, nenhum nome é dado. Isso é importante porque o nome do módulo pode ocorrer várias vezes no mesmo manual e todas as tarefas devem ser nomeadas.


Claro, você ainda pode escrever testes para playbooks. Podemos nos dar ao luxo de não fazer isso porque iremos implantar no ambiente de teste e nada crítico acontecerá. Mas se você implantar no produto, seria melhor verificar tudo. O benefício do ansible permite testar não apenas playbooks, mas também módulos individuais. Portanto, preste atenção nisso.


E o segundo principal motivo para usar o servidor de CI é lançar playbooks. Este é o mesmo botão mágico "Faça bem", o que nos dá o TeamCity. Apenas criamos algumas configurações simples para diferentes produtos, onde dizemos: ansible-playbook reporter_vm.yml -i inventário.yml -vvvv e obtemos o botão Implementar.


Conveniência de bônus: você pode criar versões dependendo das versões. Assim que algo se consolida, o TeamCity inicia o processo de reimplantação, após o qual só podemos olhar os logs se algo quebrar de repente.


Total


  • Scripts confusos e díspares do PowerShell substituídos por YAML-configs.
  • Substituímos várias implementações dos mesmos problemas por funções comuns que podem ser reutilizadas. Um repositório foi criado onde estão as funções. Se o papel combina com você, basta usá-lo. Se não combina com você, basta enviar a solicitação de pool, e combina com você =)
  • Agora você pode verificar o sucesso da implantação em um único local.
  • Todo mundo sabe onde procurar logs.
  • Os problemas de comunicação também foram resolvidos por meio de um repositório comum e do TeamCity. Todas as pessoas interessadas sabem onde estão os manuais e como eles funcionam.

PS Todos os exemplos do artigo podem ser encontrados no github .

Source: https://habr.com/ru/post/pt455604/


All Articles