«Novas Epopéias». Comemos o elefante em partes

«Novas Epopéias». Comemos o elefante em partes

Neste artigo, configurarei o ambiente de desenvolvimento para o jogo "Býliny", além de dividir o próprio jogo em partes utilizáveis no OpenFaaS. Todas as operações serão feitas no Linux, usando Kubernetes que será implantado no minikube com o VirtualBox. Minha máquina de trabalho possui 2 núcleos de processador e 12 GB de RAM, e utilizo um SSD como disco do sistema. Para o desenvolvimento, usarei o Debian 8, com os pacotes emacs, sudo, git e virtualbox instalados, e todo o restante será instalado através do download do GitHub e outras fontes. Estarei instalando essas aplicações em /usr/local/bin, salvo indicação em contrário. Vamos começar!

Preparação do Ambiente de Trabalho

Instalação do Go

Siga as instruções do site oficial:

$ curl -L0 https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz -o go.tar.gz
$ sudo tar -C /usr/local -xzf go.tar.gz
$ echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile

Verificamos a funcionalidade:

$ mkdir -p ~/go/src/hello && cd ~/go/src/hello
$ echo 'package main

import "fmt"

func main() {
fmt.Printf("hello, worldn")
}' > hello.go
$ go build
$ ./hello
hello, world

Instalação do faas-cli

Siga as instruções do site oficial:

$ curl -sSL https://cli.openfaas.com | sudo -E sh
x86_64
Baixando pacote https://github.com/openfaas/faas-cli/releases/download/0.11.3/faas-cli como /tmp/faas-cli
Download completo.

Executando com permissões suficientes para mover faas-cli para /usr/local/bin
Nova versão do faas-cli instalada em /usr/local/bin
Criando alias 'faas' para 'faas-cli'.
  ___                   _____           ____
 / _  _ __   ___ _ __ |  ___|_ _  __ _/ ___|
| | | | '_  / _  '_ | |_ / _` |/ _` ___ 
| |_| | |_) |  __/ | | |  _| (_| | (_| |___) |
 ___/| .__ / ___|_| |_|_|  __,_|__,_|____/
      |_|

CLI:
 commit:  73004c23e5a4d3fdb7352f953247473477477a64
 versão: 0.11.3

Adicionalmente, você pode ativar o bash-completion:

faas-cli completion --shell bash | sudo tee /etc/bash_completion.d/faas-cli

Instalação e Configuração do Kubernetes

Para o desenvolvimento, é suficiente o minikube, então iremos instalá-lo junto com o kubelet em /usr/local/bin, também instalaremos o helm para instalação de aplicações:

$ curl https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 -o minikube && chmod +x minikube && sudo mv minikube /usr/local/bin/
$ curl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl -o kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
$ curl https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz | tar -xzvf - linux-amd64/helm --strip-components=1; sudo mv helm /usr/local/bin

Iniciando o minikube:

$ minikube start
  minikube v1.6.2 no Debian 8.11
  Driver 'virtualbox' selecionado automaticamente (alternativas: [])
  Baixando imagem de inicialização da VM ...
    > minikube-v1.6.0.iso.sha256: 65 B / 65 B [--------------] 100.00% ? p/s 0s
    > minikube-v1.6.0.iso: 150.93 MiB / 150.93 MiB [-] 100.00% 5.67 MiB p/s 27s
  Criando VM virtualbox (CPUs=2, Memória=8192MB, Disco=20000MB) ...
  Preparando Kubernetes v1.17.0 no Docker '19.03.5' ...
  Baixando kubeadm v1.17.0
  Baixando kubelet v1.17.0
  Puxando imagens ...
  Lançando Kubernetes ...  Aguardando o cluster ficar online ...
  Concluído! kubectl agora está configurado para usar "minikube"

Verificamos:

$ kubectl get pods --all-namespaces
NAMESPACE     NAME                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-6955765f44-knlcb           1/1     Em execução   0          29m
kube-system   coredns-6955765f44-t9cpn           1/1     Em execução   0          29m
kube-system   etcd-minikube                      1/1     Em execução   0          28m
kube-system   kube-addon-manager-minikube        1/1     Em execução   0          28m
kube-system   kube-apiserver-minikube            1/1     Em execução   0          28m
kube-system   kube-controller-manager-minikube   1/1     Em execução   0          28m
kube-system   kube-proxy-hv2wc                   1/1     Em execução   0          29m
kube-system   kube-scheduler-minikube            1/1     Em execução   0          28m
kube-system   storage-provisioner                1/1     Em execução   1          29m

Instalação do OpenFaaS

Os desenvolvedores recomendam criar 2 namespaces para trabalhar:

$ kubectl apply -f https://raw.githubusercontent.com/openfaas/faas-netes/master/namespaces.yml
namespace/openfaas criado
namespace/openfaas-fn criado

Adicionando o repositório para helm:

$ helm repo add openfaas https://openfaas.github.io/faas-netes/
"openfaas" foi adicionado aos seus repositórios

No chart, é possível definir uma senha antes da instalação, vamos usá-la e salvar os dados de acesso como um segredo k8s:

$ PASSWORD=verysecurerandompasswordstring
$ kubectl -n openfaas create secret generic basic-auth --from-literal=basic-auth-user=admin --from-literal=basic-auth-password="$PASSWORD"
secret/basic-auth criado

Executando o desdobramento:

$ helm repo update
Aguarde enquanto pegamos o mais recente dos seus repositórios de gráfico...
...Atualização bem-sucedida do repositório de gráficos "openfaas"
Atualização Completa.  Feliz Helm!
$ helm upgrade openfaas --install openfaas/openfaas --namespace openfaas --set functionNamespace=openfaas-fn --set generateBasicAuth=false
Release "openfaas" não existe. Instalando agora.
NAME: openfaas
ULTIMA INSTALAÇÃO: Sex Dez 25 10:28:22 2019
NAMESPACE: openfaas
STATUS: implantado
REVISION: 1
TEST SUITE: Nenhuma
NOTAS:
Para verificar se o openfaas foi iniciado, execute:

  kubectl -n openfaas get deployments -l "release=openfaas, app=openfaas"

Após algum tempo, execute o comando sugerido:

$ kubectl -n openfaas get deployments -l "release=openfaas, app=openfaas"
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
alertmanager        1/1     1            1           114s
basic-auth-plugin   1/1     1            1           114s
faas-idler          1/1     1            1           114s
gateway             1/1     1            1           114s
nats                1/1     1            1           114s
prometheus          1/1     1            1           114s
queue-worker        1/1     1            1           114s

Verificamos a funcionalidade:

$ kubectl rollout status -n openfaas deploy/gateway
deployment "gateway" foi implantado com sucesso
$ kubectl port-forward -n openfaas svc/gateway 8080:8080 &
[1] 6985
Encaminhando de 127.0.0.1:8080 -> 8080
$ echo -n $PASSWORD | faas-cli login --username admin --password-stdin
Chamando o servidor OpenFaaS para validar as credenciais...
Tratando a conexão para 8080
AVISO! A comunicação não é segura, considere usar HTTPS. Letsencrypt.org oferece certificados SSL/TLS gratuitos.
Credenciais salvas para admin http://127.0.0.1:8080
$ faas-cli list
Função                        Invocações     Réplicas

Instalação do Mongodb

Vamos instalar tudo usando helm:

$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/
"stable" foi adicionado aos seus repositórios
$ helm install stable/mongodb --generate-name
NOME: mongodb-1577466908
ULTIMA IMPLANTAÇÃO: Sex Dez 25 11:15:11 2019
NAMESPACE: default
STATUS: implantado
REVISÃO: 1
SUITE DE TESTE: Nenhuma
NOTAS:
** Por favor, tenha paciência enquanto o gráfico está sendo implantado **

O MongoDB pode ser acessado pela porta 27017 no seguinte nome DNS de dentro do seu cluster:

    mongodb-1577466908.default.svc.cluster.local

Para obter a senha do root, execute:

    export MONGODB_ROOT_PASSWORD=$(kubectl get secret --namespace default mongodb-1577466908 -o jsonpath="{.data.mongodb-root-password}" | base64 --decode)

Para conectar ao seu banco de dados, execute o seguinte comando:

    kubectl run --namespace default mongodb-1577466908-client --rm --tty -i --restart='Never' --image bitnami/mongodb --command -- mongo admin --host mongodb-1577466908 --authenticationDatabase admin -u root -p $MONGODB_ROOT_PASSWORD

Para conectar ao seu banco de dados de fora do cluster, execute os seguintes comandos:

    kubectl port-forward --namespace default svc/mongodb-1577466908 27017:27017 &
    mongo --host 127.0.0.1 --authenticationDatabase admin -p $MONGODB_ROOT_PASSWORD

Verificamos:

kubectl run --namespace default mongodb-1577466908-client --rm --tty -i --restart='Never' --image bitnami/mongodb --command -- mongo admin --host mongodb-1577466908 --authenticationDatabase admin -u root -p $(kubectl get secret --namespace default mongodb-1577466908 -o jsonpath="{.data.mongodb-root-password}" | base64 --decode)
Se você não vê um prompt de comando, tente pressionar Enter.

> db.version();
4.0.14

Pressione ctrl+D para sair do contêiner.

Configuração do emacs

Em princípio, tudo já estava configurado conforme este artigo, então não vou detalhar muito.

Divisão do jogo em funções

A interação com as funções é realizada através do protocolo http, e a autenticação entre diferentes funções é garantida pelo JWT. Para armazenar tokens, bem como o estado do jogo, dados dos jogadores, sequências de jogadas de todos os jogos e outras informações, utiliza-se o mongodb. Vamos examinar mais detalhadamente as funções mais interessantes.

Registro

O parâmetro de entrada desta função é um JSON com o apelido do jogador e a senha. Ao invocar esta função, é realizada uma verificação da inexistência desse apelido no banco de dados, e, após a verificação bem-sucedida, o apelido e o hash da senha são inseridos no banco. O registro é necessário para a participação ativa no jogo.

Entrada

A função recebe um JSON com o apelido do jogador e a senha. Se o apelido estiver no banco de dados e a senha for verificada com sucesso, retorna um JWT que deve ser passado para outras funções ao serem chamadas. Também é realizada a inserção de vários registros no banco de dados, como o horário do último login, entre outros.

Visualizar lista de jogos

Qualquer usuário não autenticado pode solicitar a lista de todos os jogos, exceto os ativos. O usuário autenticado também vê a lista de jogos ativos. O resultado da função é um JSON contendo listas de jogos (identificador do jogo, nome legível, etc.).

Criação de jogos

A função opera apenas com usuários autenticados, recebe como entrada o número máximo de jogadores e parâmetros do jogo (por exemplo, quais personagens ativar nesse jogo, número máximo de jogadores, etc.). Um parâmetro adicional do jogo é a presença de uma senha para a participação, permitindo a criação de jogos não públicos. Por padrão, é criado um jogo público. O resultado da função é um JSON que contém um campo de sucesso na criação, um identificador único do jogo e outros parâmetros.

Participar do jogo

A função opera apenas com usuários autenticados, recebe como entrada o identificador do jogo e sua senha, se se tratar de um jogo não público, e retorna um JSON com os parâmetros do jogo. O usuário autenticado que se uniu ao jogo, assim como o criador do jogo, são chamados de participantes do jogo.

Visualizar eventos do jogo

Qualquer usuário não autenticado pode solicitar a lista de eventos de jogos inativos, enquanto um usuário autenticado pode obter a lista de eventos de qualquer jogo ativo. Um parâmetro adicional da função pode ser o número do evento que o usuário já possui. Nesse caso, a lista retornará apenas os eventos que ocorreram posteriormente. Ao executar essa função periodicamente, o usuário autenticado verifica o que está acontecendo no jogo. Essa função também retorna uma solicitação de ação, à qual o usuário pode responder usando a função de envio de eventos do jogo.

Enviar evento do jogo

A função funciona apenas para os participantes do jogo: permite iniciar o jogo, realizar uma jogada, votar, enviar uma mensagem de texto, que é exibida na lista de eventos do jogo, etc.
O usuário autorizado que criou o jogo inicia a distribuição de papéis a todos os participantes do jogo, incluindo a si mesmo, e eles devem confirmar seus papéis usando esta mesma função. Assim que todos os papéis forem confirmados, o jogo passa automaticamente para o modo noite.

Estatísticas do jogo

A função funciona apenas para os participantes do jogo, mostrando o estado do jogo, a lista e o número de jogadores (pseudônimos), papéis e seu status (jogada feita ou não), bem como outras informações. Assim como na função anterior, tudo funciona apenas para os participantes do jogo.

Funções executadas periodicamente

Se o jogo não foi iniciado por um determinado período de tempo especificado ao criar o jogo, ele será automaticamente removido da lista de jogos ativos com a função de limpeza.

Outra tarefa periódica é a troca forçada do modo de jogo de noite para dia e vice-versa para jogos que não foram alternados durante a jogada (por exemplo, um jogador que precisava reagir a um evento do jogo não enviou sua decisão por qualquer motivo).

Anúncio

  • Introdução
  • Configuração do ambiente de desenvolvimento, divisão da tarefa em funções
  • Trabalhos no backend
  • Trabalhos no frontend
  • Configuração do CICD, organização de testes
  • Início de uma sessão de teste do jogo
  • Resultados

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster