Aceitamos 10 eventos no Yandex.Cloud. Parte 000

Olá a todos, amigos!

* Este artigo é baseado no workshop aberto REBRAIN & Yandex.Cloud, se preferir assistir ao vídeo, você pode encontrá-lo neste link - https://youtu.be/cZLezUm0ekE

Recentemente, tivemos a oportunidade de experimentar o Yandex.Cloud ao vivo. Como queríamos investigar muito, abandonamos imediatamente a ideia de lançar um blog Wordpress simples com base na nuvem - era muito chato. Depois de pensar um pouco, decidimos implantar algo semelhante a uma arquitetura de serviço de produção para receber e analisar eventos quase em tempo real.

Tenho certeza absoluta de que a grande maioria das empresas online (e não apenas) de alguma forma coleta uma montanha de informações sobre seus usuários e suas ações. No mínimo, isso é necessário para tomar certas decisões - por exemplo, se você gerencia um jogo online, pode observar as estatísticas em que nível os usuários ficam presos com mais frequência e excluem seu brinquedo. Ou por que os usuários saem do seu site sem comprar nada (olá, Yandex.Metrica).

Então, nossa história: como escrevemos um aplicativo em golang, testamos kafka vs RabbitMQ vs yqs, escrevemos streaming de dados em um cluster Clickhouse e visualizamos os dados usando Yandex Datalens. Naturalmente, tudo isso foi temperado com delícias de infraestrutura na forma de docker, terraform, gitlab ci e, claro, prometheus. Vamos!

Gostaria de fazer desde já uma ressalva que não poderemos configurar tudo de uma só vez - para isso precisaremos de vários artigos da série. Um pouco sobre a estrutura:

Parte 1 (você está lendo). Decidiremos as especificações e arquitetura da solução, e também escreveremos um aplicativo em golang.
Parte 2. Liberamos nosso aplicativo para produção, o tornamos escalonável e testamos a carga.
Parte 3. Vamos tentar descobrir por que precisamos armazenar mensagens em um buffer e não em arquivos, e também comparar o serviço de fila kafka, RabbitMQ e Yandex.
Parte 4 Implantaremos um cluster Clickhouse, escreveremos um serviço de streaming para transferir dados do buffer e configuraremos a visualização em datalens.
Parte 5 Vamos colocar toda a infraestrutura em forma adequada - configurar ci/cd usando gitlab ci, conectar monitoramento e descoberta de serviço usando prometheus e consul.

TK

Primeiro, vamos formular os termos de referência - o que exatamente queremos obter como resultado.

  1. Queremos ter um endpoint como events.kis.im (kis.im é o domínio de teste que usaremos ao longo de todos os artigos), que deverá receber eventos usando HTTPS.
  2. Os eventos são um json simples como: {“event”: “view”, “os”: “linux”, “browser”: “chrome”}. Na fase final adicionaremos um pouco mais de campos, mas isso não terá um grande papel. Se desejar, você pode mudar para o protobuf.
  3. O serviço deve ser capaz de processar 10 eventos por segundo.
  4. Deveria ser possível escalar horizontalmente simplesmente adicionando novas instâncias à nossa solução. E será bom se pudermos mover a parte frontal para diferentes geolocalizações para reduzir a latência das solicitações dos clientes.
  5. Tolerância ao erro. A solução deve ser suficientemente estável e capaz de sobreviver à queda de qualquer peça (até um certo número, é claro).

Arquitetura

Em geral, para este tipo de tarefa, há muito que foram inventadas arquiteturas clássicas que permitem um escalonamento eficiente. A figura mostra um exemplo de nossa solução.

Aceitamos 10 eventos no Yandex.Cloud. Parte 000

Então o que temos:

1. À esquerda estão nossos dispositivos que geram diversos eventos, sejam jogadores completando um nível em um brinquedo em um smartphone ou criando um pedido em uma loja online por meio de um navegador normal. Um evento, conforme especificado na especificação, é um json simples enviado ao nosso endpoint - events.kis.im.

2. Os dois primeiros servidores são balanceadores simples, suas principais tarefas são:

  • Esteja constantemente disponível. Para fazer isso, você pode usar, por exemplo, o keepalived, que irá alternar o IP virtual entre os nós em caso de problemas.
  • Encerre o TLS. Sim, encerraremos o TLS neles. Em primeiro lugar, para que a nossa solução cumpra as especificações técnicas e, em segundo lugar, para aliviar o fardo de estabelecer uma ligação encriptada a partir dos nossos servidores backend.
  • Equilibre as solicitações recebidas para servidores back-end disponíveis. A palavra-chave aqui é acessível. Com base nisso, chegamos ao entendimento de que os balanceadores de carga devem ser capazes de monitorar nossos servidores com aplicativos e parar de equilibrar o tráfego para nós com falha.

3. Após os balanceadores, temos servidores de aplicação executando uma aplicação bastante simples. Deve ser capaz de aceitar solicitações recebidas via HTTP, validar o json enviado e colocar os dados em um buffer.

4. O diagrama mostra o kafka como um buffer, embora, é claro, outros serviços semelhantes possam ser usados ​​nesse nível. Compararemos Kafka, RabbitMQ e YQS no terceiro artigo.

5. O penúltimo ponto da nossa arquitetura é Clickhouse - um banco de dados colunar que permite armazenar e processar uma grande quantidade de dados. Neste nível, precisamos transferir dados do buffer para o próprio sistema de armazenamento (mais sobre isso no artigo 4).

Este design nos permite dimensionar cada camada horizontalmente de forma independente. Os servidores back-end não aguentam - vamos acrescentar mais uma coisa - afinal, eles são aplicativos sem estado e, portanto, isso pode ser feito até de forma automática. O buffer estilo Kafka não funciona – vamos adicionar mais servidores e transferir algumas das partições do nosso tópico para eles. Clickhouse não consegue lidar com isso - é impossível :) Na verdade, também conectaremos os servidores e fragmentaremos os dados.

Já agora, se pretende implementar a parte opcional das nossas especificações técnicas e escalar em diferentes geolocalizações, então não há nada mais simples:

Aceitamos 10 eventos no Yandex.Cloud. Parte 000

Em cada geolocalização implantamos um balanceador de carga com aplicação e kafka. Em geral, bastam 2 servidores de aplicação, 3 nós kafka e um balanceador de nuvem, por exemplo, cloudflare, que irá verificar a disponibilidade dos nós da aplicação e equilibrar as solicitações por geolocalização com base no endereço IP de origem do cliente. Assim, os dados enviados por um cliente americano irão parar em servidores americanos. E os dados de África estão em África.

Então tudo é bastante simples - usamos a ferramenta de espelho do conjunto Kafka e copiamos todos os dados de todos os locais para nosso data center central localizado na Rússia. Internamente, analisamos os dados e os registramos no Clickhouse para posterior visualização.

Então, resolvemos a arquitetura - vamos começar a agitar o Yandex.Cloud!

Escrevendo um aplicativo

Antes da nuvem, você ainda precisa ter um pouco de paciência e escrever um serviço bastante simples para processar eventos recebidos. Usaremos golang porque ele se provou muito bem como uma linguagem para escrever aplicativos de rede.

Depois de passar uma hora (talvez algumas horas), obtemos algo assim: https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/main.go.

Quais são os principais pontos que gostaria de observar aqui:

1. Ao iniciar o aplicativo, você pode especificar dois sinalizadores. Um é responsável pela porta na qual ouviremos as solicitações HTTP recebidas (-addr). A segunda é para o endereço do servidor kafka onde registraremos nossos eventos (-kafka):

addr     = flag.String("addr", ":8080", "TCP address to listen to")
kafka    = flag.String("kafka", "127.0.0.1:9092", "Kafka endpoints”)

2. O aplicativo usa a biblioteca sarama ([] github.com/Shopify/sarama) para enviar mensagens ao cluster kafka. Definimos imediatamente as configurações visando a velocidade máxima de processamento:

config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForLocal
config.Producer.Compression = sarama.CompressionSnappy
config.Producer.Return.Successes = true

3. Nosso aplicativo também possui um cliente prometheus integrado, que coleta várias métricas, como:

  • número de solicitações ao nosso aplicativo;
  • quantidade de erros na execução da requisição (impossível ler post request, json quebrado, impossível escrever no Kafka);
  • tempo de processamento para uma solicitação do cliente, incluindo o tempo para escrever uma mensagem para Kafka.

4. Três endpoints que nosso aplicativo processa:

  • /status - simplesmente retorne ok para mostrar que estamos vivos. Embora você possa adicionar algumas verificações, como a disponibilidade do cluster Kafka.
  • /metrics - de acordo com este URL, o cliente prometheus retornará as métricas que coletou.
  • /post é o endpoint principal para onde as solicitações POST com json dentro serão enviadas. Nosso aplicativo verifica a validade do json e se tudo estiver bem, ele grava os dados no cluster Kafka.

Farei uma ressalva de que o código não é perfeito - pode (e deve!) ser completado. Por exemplo, você pode parar de usar o net/http integrado e mudar para o fasthttp mais rápido. Ou você pode ganhar tempo de processamento e recursos de CPU movendo a verificação de validade do json para um estágio posterior - quando os dados são transferidos do buffer para o cluster clickhouse.

Além do lado do desenvolvimento da questão, pensamos imediatamente em nossa infraestrutura futura e decidimos implantar nossa aplicação via docker. O Dockerfile final para construir o aplicativo é https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/Dockerfile. Em geral é bastante simples, o único ponto que gostaria de prestar atenção é a montagem multiestágios, que nos permite reduzir a imagem final do nosso container.

Primeiros passos na nuvem

Primeiro de tudo, cadastre-se em nuvem.yandex.ru. Após preencher todos os campos obrigatórios, será criada uma conta e será concedida uma bolsa de uma determinada quantia em dinheiro, que poderá ser usada para testar serviços em nuvem. Se quiser repetir todos os passos do nosso artigo, esta bolsa deve ser suficiente para você.

Após o registro, uma nuvem separada e um diretório padrão serão criados para você, onde você poderá começar a criar recursos de nuvem. Em geral, no Yandex.Cloud, a relação de recursos é assim:

Aceitamos 10 eventos no Yandex.Cloud. Parte 000

Você pode criar várias nuvens para uma conta. E dentro da nuvem, faça diferentes diretórios para diferentes projetos da empresa. Você pode ler mais sobre isso na documentação - https://cloud.yandex.ru/docs/resource-manager/concepts/resources-hierarchy. A propósito, frequentemente me referirei a isso abaixo no texto. Quando montei toda a infraestrutura do zero, a documentação me ajudou mais de uma vez, por isso aconselho que estude.

Para gerenciar a nuvem, você pode usar a interface da web e o utilitário do console - yc. A instalação é realizada com um comando (para Linux e Mac Os):

curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash

Se o seu especialista em segurança interna está furioso com a execução de scripts da Internet, então, em primeiro lugar, você pode abrir o script e lê-lo e, em segundo lugar, nós o executamos sob nosso usuário - sem direitos de root.

Se você deseja instalar um cliente para Windows, você pode usar as instruções aqui e então execute yc initpara personalizá-lo totalmente:

vozerov@mba:~ $ yc init
Welcome! This command will take you through the configuration process.
Please go to https://oauth.yandex.ru/authorize?response_type=token&client_id= in order to obtain OAuth token.

Please enter OAuth token:
Please select cloud to use:
 [1] cloud-b1gv67ihgfu3bp (id = b1gv67ihgfu3bpt24o0q)
 [2] fevlake-cloud (id = b1g6bvup3toribomnh30)
Please enter your numeric choice: 2
Your current cloud has been set to 'fevlake-cloud' (id = b1g6bvup3toribomnh30).
Please choose folder to use:
 [1] default (id = b1g5r6h11knotfr8vjp7)
 [2] Create a new folder
Please enter your numeric choice: 1
Your current folder has been set to 'default' (id = b1g5r6h11knotfr8vjp7).
Do you want to configure a default Compute zone? [Y/n]
Which zone do you want to use as a profile default?
 [1] ru-central1-a
 [2] ru-central1-b
 [3] ru-central1-c
 [4] Don't set default zone
Please enter your numeric choice: 1
Your profile default Compute zone has been set to 'ru-central1-a'.
vozerov@mba:~ $

Em princípio, o processo é simples - primeiro você precisa obter um token oauth para gerenciar a nuvem, selecionar a nuvem e a pasta que usará.

Se você tiver várias contas ou pastas na mesma nuvem, poderá criar perfis adicionais com configurações separadas por meio de yc config profile create e alternar entre eles.

Além dos métodos acima, a equipe Yandex.Cloud escreveu um muito bom plugin para terraform para gerenciar recursos de nuvem. De minha parte, preparei um repositório git, onde descrevi todos os recursos que serão criados no âmbito do artigo - https://github.com/rebrainme/yandex-cloud-events/. Estamos interessados ​​no branch master, vamos cloná-lo localmente:


vozerov@mba:~ $ git clone https://github.com/rebrainme/yandex-cloud-events/ events
Cloning into 'events'...
remote: Enumerating objects: 100, done.
remote: Counting objects: 100% (100/100), done.
remote: Compressing objects: 100% (68/68), done.
remote: Total 100 (delta 37), reused 89 (delta 26), pack-reused 0
Receiving objects: 100% (100/100), 25.65 KiB | 168.00 KiB/s, done.
Resolving deltas: 100% (37/37), done.
vozerov@mba:~ $ cd events/terraform/

Todas as principais variáveis ​​​​usadas no terraform são escritas no arquivo main.tf. Para começar, crie um arquivo private.auto.tfvars na pasta terraform com o seguinte conteúdo:

# Yandex Cloud Oauth token
yc_token = ""
# Yandex Cloud ID
yc_cloud_id = ""
# Yandex Cloud folder ID
yc_folder_id = ""
# Default Yandex Cloud Region
yc_region = "ru-central1-a"
# Cloudflare email
cf_email = ""
# Cloudflare token
cf_token = ""
# Cloudflare zone id
cf_zone_id = ""

Todas as variáveis ​​​​podem ser retiradas da lista de configuração do yc, pois já configuramos o utilitário do console. Aconselho você a adicionar imediatamente private.auto.tfvars a .gitignore, para não publicar acidentalmente dados privados.

Em private.auto.tfvars também especificamos dados da Cloudflare - para criar registros DNS e fazer proxy do domínio principal events.kis.im para nossos servidores. Se você não quiser usar o cloudflare, remova a inicialização do provedor cloudflare em main.tf e o arquivo dns.tf, que é responsável por criar os registros DNS necessários.

Em nosso trabalho combinaremos todos os três métodos - a interface web, o utilitário de console e o terraform.

Redes virtuais

Para ser honesto, você pode pular esta etapa, pois ao criar uma nova nuvem, você terá automaticamente uma rede separada e 3 sub-redes criadas - uma para cada zona de disponibilidade. Mas ainda gostaríamos de fazer uma rede separada para o nosso projeto com endereçamento próprio. O diagrama geral de como a rede funciona no Yandex.Cloud é mostrado na figura abaixo (retirado honestamente de https://cloud.yandex.ru/docs/vpc/concepts/)

Aceitamos 10 eventos no Yandex.Cloud. Parte 000

Assim, você cria uma rede comum dentro da qual os recursos podem se comunicar entre si. Para cada zona de disponibilidade é criada uma sub-rede com endereçamento próprio e conectada à rede geral. Como resultado, todos os recursos da nuvem podem se comunicar, mesmo que estejam em zonas de disponibilidade diferentes. Os recursos conectados a diferentes redes de nuvem só podem se ver por meio de endereços externos. A propósito, como funciona essa magia por dentro, foi bem descrito em Habré.

A criação da rede é descrita no arquivo network.tf do repositório. Lá criamos uma rede privada comum interna e conectamos três sub-redes a ela em diferentes zonas de disponibilidade - interna-a (172.16.1.0/24), interna-b (172.16.2.0/24), interna-c (172.16.3.0/24 ).

Inicialize o terraform e crie redes:

vozerov@mba:~/events/terraform (master) $ terraform init
... skipped ..

vozerov@mba:~/events/terraform (master) $ terraform apply -target yandex_vpc_subnet.internal-a -target yandex_vpc_subnet.internal-b -target yandex_vpc_subnet.internal-c

... skipped ...

Plan: 4 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

yandex_vpc_network.internal: Creating...
yandex_vpc_network.internal: Creation complete after 3s [id=enp2g2rhile7gbqlbrkr]
yandex_vpc_subnet.internal-a: Creating...
yandex_vpc_subnet.internal-b: Creating...
yandex_vpc_subnet.internal-c: Creating...
yandex_vpc_subnet.internal-a: Creation complete after 6s [id=e9b1dad6mgoj2v4funog]
yandex_vpc_subnet.internal-b: Creation complete after 7s [id=e2liv5i4amu52p64ac9p]
yandex_vpc_subnet.internal-c: Still creating... [10s elapsed]
yandex_vpc_subnet.internal-c: Creation complete after 10s [id=b0c2qhsj2vranoc9vhcq]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Ótimo! Criamos nossa rede e agora estamos prontos para criar nossos serviços internos.

Criando máquinas virtuais

Para testar o aplicativo, precisaremos apenas criar duas máquinas virtuais - precisaremos da primeira para construir e executar o aplicativo, a segunda para executar o kafka, que usaremos para armazenar as mensagens recebidas. E criaremos outra máquina onde configuraremos o prometheus para monitorar o aplicativo.

As máquinas virtuais serão configuradas usando ansible, portanto, antes de iniciar o terraform, certifique-se de ter uma das versões mais recentes do ansible. E instale as funções necessárias com o ansible galaxy:

vozerov@mba:~/events/terraform (master) $ cd ../ansible/
vozerov@mba:~/events/ansible (master) $ ansible-galaxy install -r requirements.yml
- cloudalchemy-prometheus (master) is already installed, skipping.
- cloudalchemy-grafana (master) is already installed, skipping.
- sansible.kafka (master) is already installed, skipping.
- sansible.zookeeper (master) is already installed, skipping.
- geerlingguy.docker (master) is already installed, skipping.
vozerov@mba:~/events/ansible (master) $

Dentro da pasta ansible há um exemplo de arquivo de configuração .ansible.cfg que eu uso. Pode ser útil.

Antes de criar máquinas virtuais, certifique-se de ter o agente ssh em execução e uma chave ssh adicionada, caso contrário o terraform não será capaz de se conectar às máquinas criadas. É claro que me deparei com um bug no os x: https://github.com/ansible/ansible/issues/32499#issuecomment-341578864. Para evitar que isso aconteça novamente, adicione uma pequena variável ao env antes de iniciar o Terraform:

vozerov@mba:~/events/terraform (master) $ export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

Na pasta com terraform criamos os recursos necessários:

vozerov@mba:~/events/terraform (master) $ terraform apply -target yandex_compute_instance.build -target yandex_compute_instance.monitoring -target yandex_compute_instance.kafka
yandex_vpc_network.internal: Refreshing state... [id=enp2g2rhile7gbqlbrkr]
data.yandex_compute_image.ubuntu_image: Refreshing state...
yandex_vpc_subnet.internal-a: Refreshing state... [id=e9b1dad6mgoj2v4funog]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

... skipped ...

Plan: 3 to add, 0 to change, 0 to destroy.

... skipped ...

Se tudo terminou com sucesso (e deveria ser), teremos três máquinas virtuais:

  1. build - uma máquina para testar e construir um aplicativo. Docker foi instalado automaticamente pelo Ansible.
  2. monitoramento - uma máquina de monitoramento - prometheus & grafana instalada nela. Padrão de login/senha: admin/admin
  3. kafka é uma pequena máquina com o kafka instalado, acessível na porta 9092.

Vamos ter certeza de que estão todos no lugar:

vozerov@mba:~/events (master) $ yc compute instance list
+----------------------+------------+---------------+---------+---------------+-------------+
|          ID          |    NAME    |    ZONE ID    | STATUS  |  EXTERNAL IP  | INTERNAL IP |
+----------------------+------------+---------------+---------+---------------+-------------+
| fhm081u8bkbqf1pa5kgj | monitoring | ru-central1-a | RUNNING | 84.201.159.71 | 172.16.1.35 |
| fhmf37k03oobgu9jmd7p | kafka      | ru-central1-a | RUNNING | 84.201.173.41 | 172.16.1.31 |
| fhmt9pl1i8sf7ga6flgp | build      | ru-central1-a | RUNNING | 84.201.132.3  | 172.16.1.26 |
+----------------------+------------+---------------+---------+---------------+-------------+

Os recursos estão disponíveis e a partir daqui podemos obter seus endereços IP. Ao longo do texto a seguir, usarei endereços IP para conectar via ssh e testar o aplicativo. Se você tiver uma conta cloudflare conectada ao terraform, sinta-se à vontade para usar nomes DNS recém-criados.
A propósito, ao criar uma máquina virtual, são fornecidos um IP interno e um nome DNS interno, para que você possa acessar os servidores da rede pelo nome:

ubuntu@build:~$ ping kafka.ru-central1.internal
PING kafka.ru-central1.internal (172.16.1.31) 56(84) bytes of data.
64 bytes from kafka.ru-central1.internal (172.16.1.31): icmp_seq=1 ttl=63 time=1.23 ms
64 bytes from kafka.ru-central1.internal (172.16.1.31): icmp_seq=2 ttl=63 time=0.625 ms
^C
--- kafka.ru-central1.internal ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.625/0.931/1.238/0.308 ms

Isso será útil para indicarmos à aplicação o endpoint com kafk.

Montando o aplicativo

Ótimo, existem servidores, existe um aplicativo - só falta montá-lo e publicá-lo. Para a construção usaremos o docker build usual, mas como armazenamento de imagens usaremos um serviço do Yandex - registro de contêiner. Mas primeiro as primeiras coisas.

Copiamos a aplicação para a máquina de build, fazemos login via ssh e montamos a imagem:

vozerov@mba:~/events/terraform (master) $ cd ..
vozerov@mba:~/events (master) $ rsync -av app/ [email protected]:app/

... skipped ...

sent 3849 bytes  received 70 bytes  7838.00 bytes/sec
total size is 3644  speedup is 0.93

vozerov@mba:~/events (master) $ ssh 84.201.132.3 -l ubuntu
ubuntu@build:~$ cd app
ubuntu@build:~/app$ sudo docker build -t app .
Sending build context to Docker daemon  6.144kB
Step 1/9 : FROM golang:latest AS build
... skipped ...

Successfully built 9760afd8ef65
Successfully tagged app:latest

Metade da batalha está concluída - agora podemos verificar a funcionalidade do nosso aplicativo iniciando-o e enviando-o para o kafka:

ubuntu@build:~/app$ sudo docker run --name app -d -p 8080:8080 app /app/app -kafka=kafka.ru-central1.internal:9092</code>

С локальной машинки можно отправить тестовый event и посмотреть на ответ:

<code>vozerov@mba:~/events (master) $ curl -D - -s -X POST -d '{"key1":"data1"}' http://84.201.132.3:8080/post
HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 13 Apr 2020 13:53:54 GMT
Content-Length: 41

{"status":"ok","partition":0,"Offset":0}
vozerov@mba:~/events (master) $

A aplicação respondeu com sucesso da gravação e indicando o id da partição e offset em que a mensagem foi incluída. Tudo o que resta fazer é criar um registro no Yandex.Cloud e carregar nossa imagem lá (como fazer isso usando três linhas está descrito no arquivo Registry.tf). Crie um armazenamento:

vozerov@mba:~/events/terraform (master) $ terraform apply -target yandex_container_registry.events

... skipped ...

Plan: 1 to add, 0 to change, 0 to destroy.

... skipped ...

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Existem várias maneiras de autenticar no registro de contêiner: usando um token oauth, um token iam ou uma chave de conta de serviço. Mais detalhes sobre esses métodos podem ser encontrados na documentação. https://cloud.yandex.ru/docs/container-registry/operations/authentication. Usaremos a chave da conta de serviço, então criamos uma conta:

vozerov@mba:~/events/terraform (master) $ terraform apply -target yandex_iam_service_account.docker -target yandex_resourcemanager_folder_iam_binding.puller -target yandex_resourcemanager_folder_iam_binding.pusher

... skipped ...

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Agora só falta fazer uma chave para isso:

vozerov@mba:~/events/terraform (master) $ yc iam key create --service-account-name docker -o key.json
id: ajej8a06kdfbehbrh91p
service_account_id: ajep6d38k895srp9osij
created_at: "2020-04-13T14:00:30Z"
key_algorithm: RSA_2048

Recebemos informações sobre o id do nosso armazenamento, transferimos a chave e fazemos login:

vozerov@mba:~/events/terraform (master) $ scp key.json [email protected]:
key.json                                                                                                                    100% 2392   215.1KB/s   00:00

vozerov@mba:~/events/terraform (master) $ ssh 84.201.132.3 -l ubuntu

ubuntu@build:~$ cat key.json | sudo docker login --username json_key --password-stdin cr.yandex
WARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
ubuntu@build:~$

Para fazer upload da imagem para o registro, precisamos do ID do registro do contêiner, pegamos do utilitário yc:

vozerov@mba:~ $ yc container registry get events
id: crpdgj6c9umdhgaqjfmm
folder_id:
name: events
status: ACTIVE
created_at: "2020-04-13T13:56:41.914Z"

Depois disso, marcamos nossa imagem com um novo nome e carregamos:

ubuntu@build:~$ sudo docker tag app cr.yandex/crpdgj6c9umdhgaqjfmm/events:v1
ubuntu@build:~$ sudo docker push cr.yandex/crpdgj6c9umdhgaqjfmm/events:v1
The push refers to repository [cr.yandex/crpdgj6c9umdhgaqjfmm/events]
8c286e154c6e: Pushed
477c318b05cb: Pushed
beee9f30bc1f: Pushed
v1: digest: sha256:1dd5aaa9dbdde2f60d833be0bed1c352724be3ea3158bcac3cdee41d47c5e380 size: 946

Podemos verificar se a imagem foi carregada com sucesso:

vozerov@mba:~/events/terraform (master) $ yc container repository list
+----------------------+-----------------------------+
|          ID          |            NAME             |
+----------------------+-----------------------------+
| crpe8mqtrgmuq07accvn | crpdgj6c9umdhgaqjfmm/events |
+----------------------+-----------------------------+

A propósito, se você instalar o utilitário yc em uma máquina Linux, poderá usar o comando

yc container registry configure-docker

para configurar a janela de encaixe.

Conclusão

Trabalhamos muito e como resultado:

  1. Criamos a arquitetura do nosso serviço futuro.
  2. Escrevemos um aplicativo em golang que implementa nossa lógica de negócios.
  3. Nós o coletamos e colocamos em um registro de contêiner privado.

Na próxima parte, passaremos para as coisas interessantes - lançaremos nosso aplicativo em produção e, finalmente, iniciaremos a carga nele. Não mude!

Este material está na gravação de vídeo do workshop aberto REBRAIN & Yandex.Cloud: Aceitamos 10 solicitações por segundo no Yandex Cloud - https://youtu.be/cZLezUm0ekE

Se você estiver interessado em participar desses eventos on-line e tirar dúvidas em tempo real, conecte-se a DevOps pelo canal REBRAIN.

Gostaríamos de agradecer especialmente ao Yandex.Cloud pela oportunidade de sediar tal evento. Link para eles - https://cloud.yandex.ru/prices

Se você precisa migrar para a nuvem ou tem dúvidas sobre sua infraestrutura, Sinta-se à vontade para enviar uma solicitação.

PS Temos 2 auditorias gratuitas por mês, talvez o seu projeto seja uma delas.

Fonte: habr.com

Adicionar um comentário