„Нови Билини“. Ядем слона на парчета

„Нови Билини“. Ядем слона на парчета

В тази статия ще настроя работна среда за разработка на играта „Билини“ и ще разделя самата игра на части, подходящи за използване в OpenFaaS. Всички действия ще извърша на Linux, като ще стартирам Kubernetes в minikube, използвайки VirtualBox. В моята работна машина има 2 процесорни ядра и 12GB оперативна памет, а за системен диск използвам SSD. Основната система за разработка ще бъде debian 8 с инсталирани пакети emacs, sudo, git и virtualbox, а всичко остално ще инсталирам чрез изтегляне от GitHub и други източници. Тези приложения ще инсталирам в /usr/local/bin, освен ако не е указано друго. Да започваме!

Подготовка на работната среда

Инсталиране на Go

Следваме инструкциите от официалния сайт:

$ 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

Проверяваме работоспособността:

$ 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

Инсталиране на faas-cli

Следваме инструкциите от официалния сайт:

$ curl -sSL https://cli.openfaas.com | sudo -E sh
x86_64
Сваляне на пакета https://github.com/openfaas/faas-cli/releases/download/0.11.3/faas-cli в /tmp/faas-cli
Свалянето завърши.

Работя с достатъчни права, за да преместя faas-cli в /usr/local/bin
Нова версия на faas-cli е инсталирана в /usr/local/bin
Създаване на псевдоним 'faas' за 'faas-cli'.
  ___                   _____           ____
 / _  _ __   ___ _ __ |  ___|_ _  __ _/ ___|
| | | | '_  / _  '_ | |_ / _` |/ _` ___ 
| |_| | |_) |  __/ | | |  _| (_| | (_| |___) |
 ___/| .__ / ___|_| |_|_|  __,_|__,_|____/
      |_|

CLI:
 commit:  73004c23e5a4d3fdb7352f953247473477477a64
 версия: 0.11.3

Допълнително можете да активирате bash-completion:

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

Инсталиране и настройка на Kubernetes

За разработка е достатъчен minikube, така че ще го инсталираме заедно с kubelet в /usr/local/bin, а за инсталиране на приложения ще инсталираме helm:

$ 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

Стартиране на minikube:

$ minikube start
  minikube v1.6.2 на Debian 8.11
  Автоматично избран драйвер 'virtualbox' (алтернативи: [])
  Изтегляне на изображение за стартиране на 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
  Създаване на виртуална машина с virtualbox (CPU=2, Памет=8192MB, Диск=20000MB) ...
  Подготовка на Kubernetes v1.17.0 на Docker '19.03.5' ...
  Изтегляне на kubeadm v1.17.0
  Изтегляне на kubelet v1.17.0
  Изтегляне на изображения ...
  Стартиране на Kubernetes ... Чакане кластерът да стане онлайн ...
  Готово! kubectl сега е конфигуриран да използва "minikube"

Проверяваме:

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

Инсталиране на OpenFaaS

Разработчиците препоръчват да се създадат 2 namespace за работа:

$ kubectl apply -f https://raw.githubusercontent.com/openfaas/faas-netes/master/namespaces.yml
namespace/openfaas създаден
namespace/openfaas-fn създаден

Добавяме хранилище за helm:

$ helm repo add openfaas https://openfaas.github.io/faas-netes/
"openfaas" е добавен към вашите хранилища

В чарта има възможност да зададете парола преди инсталацията, ще се възползваме от нея и ще запазим данните за достъп под формата на секрет 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 създаден

Изпълняваме разгръщането:

$ helm repo update
Задръжте, докато получим последното от вашите хранилища за чарове...
...Успешно получихме актуализация от хранилището на "openfaas"
Актуализацията е завършена. Щастливо Helming!
$ helm upgrade openfaas --install openfaas/openfaas --namespace openfaas --set functionNamespace=openfaas-fn --set generateBasicAuth=false
Release "openfaas" не съществува. Инсталира се сега.
NAME: openfaas
LAST DEPLOYED: Fri Dec 25 10:28:22 2019
NAMESPACE: openfaas
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
За да проверите, че openfaas е стартирал, изпълнете:

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

След известно време стартираме предложената команда:

$ 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

Проверяваме работоспособността:

$ kubectl rollout status -n openfaas deploy/gateway
deployment "gateway" successfully rolled out
$ kubectl port-forward -n openfaas svc/gateway 8080:8080 &
[1] 6985
Forwarding from 127.0.0.1:8080 -> 8080
$ echo -n $PASSWORD | faas-cli login --username admin --password-stdin
Calling the OpenFaaS server to validate the credentials...
Handling connection for 8080
WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.
credentials saved for admin http://127.0.0.1:8080
$ faas-cli list
Function                        Invocations     Replicas

Инсталиране на Mongodb

Инсталираме всичко с помощта на helm:

$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/
"stable" has been added to your repositories
$ helm install stable/mongodb --generate-name
NAME: mongodb-1577466908
LAST DEPLOYED: Fri Dec 25 11:15:11 2019
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
** Моля, бъдете търпеливи, докато графикът се инсталира **

MongoDB може да се достъпи през порт 27017 на следното DNS име от вашия клъстер:

    mongodb-1577466908.default.svc.cluster.local

За да получите кореновата парола, изпълнете:

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

За да се свържете с базата данни, изпълнете следната команда:

    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

За да се свържете с базата данни извън клъстера, изпълнете следните команди:

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

Проверяваме:

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)
Ако не виждате команден ред, опитайте да натиснете Enter.

> db.version();
4.0.14

Натиснете ctrl+D, за да излезете от контейнера.

Настройка на emacs

По принцип всичко вече беше настроено в тази статия, затова няма да описвам подробно.

Разделяне на играта на функции

Взаимодействието с функциите се осъществява чрез HTTP протокол, а задната аутентификация между различните функции се осигурява чрез JWT. За съхранение на токени, а също и на състоянието на играта, данните на играчите, последователностите на ходовете от всички игри и друга информация се използва mongodb. Нека да разгледаме по-подробно най-интересните функции.

Регистрация

На входа на тази функция - JSON с игровия псевдоним и паролата. При извикването на тази функция се извършва проверка за отсъствието на този псевдоним в базата данни; при успешна проверка, псевдонимът и хешът на паролата се вмъкват в базата. Регистрацията е необходима за активно участие в играта.

Вход

На входа на функцията постъпва JSON с игровия псевдоним и паролата; при наличие на псевдонима в базата и успешна проверка на паролата, се връща JWT, който трябва да се предаде на другите функции при техния извикване. Освен това, се извършва вмъкване в базата на различни служебни записи, например времето на последния вход и т.н.

Преглед на списъка с игри

Всеки неавторизиран потребител може да поиска списък на всички игри, с изключение на активните. Авторизираният потребител също така вижда и списъка с активни игри. Резултатът от функцията е JSON, съдържащ списъци с игри (идентификатор на играта, човекоразбираемо име и т.н.).

Създаване на игра

Функцията работи само с авторизирани потребители; на входа се приема максималния брой играчи, а също така параметри на играта (например, кои персонажи да бъдат активирани в тази игра, максималния брой играчи и т.н.). Отделен параметър на играта е наличието на парола за присъединяване, което позволява създаването на непублични игри. По подразбиране се създава публична игра. Резултатът от изпълнението на функцията е JSON, в който има поле за успех на създаването, уникален идентификатор на играта, а също така и други параметри.

Присъединяване към игра

Функцията работи само с авторизирани потребители; на входа – идентификатор на играта и нейния парола, ако това е непублична игра; на изхода – JSON със параметри на играта. Авторизираният потребител, който се е присъединил към играта, както и създателя на играта, се наричат участници в играта.

Преглед на събитията в играта

Всеки неавторизиран потребител може да поиска списък на събития от неактивни игри, а авторизираният - да получи списък на събития от всяка активна игра. Допълнителен параметър на функцията може да бъде номер на събитие, което потребителят вече има. В този случай в списъка ще се върнат само тези събития, които са се случили по-късно. Периодично, стартирайки тази функция, авторизираният потребител разглежда какво се случва в играта. Тази функция също така връща искане за действие, на което потребителят може да реагира чрез функцията за изпращане на събитие от играта.

Изпращане на събитие от играта

Функцията работи само за участниците в играта: предоставя възможност да стартирате играта, да направите ход, да гласувате, да напишете текстово съобщение, което се показва в списъка с събития от играта и т.н.
Авторизираният потребител, който е създал играта, стартира разпределението на роли на всички участници, включително себе си; те трябва да потвърдят ролята си чрез същата функция. След като всички роли са потвърдени, играта автоматично преминава в режим нощ.

Статистика на играта

Функцията работи само за участниците в играта, показва състоянието на играта, списъка и броя на играчите (псевдоними), ролите и техния статус (извършен ход или не), както и друга информация. Както и при предишната функция, всичко работи само за участниците в играта.

Периодично стартирани функции

Ако играта не е била стартирана в рамките на определеното време при създаването на играта — тя автоматично ще бъде премахната от списъка с активни игри чрез функцията за почистване.

Още една периодична задача — принудително превключване на режима на играта от нощ в ден и обратно за игри, при които това не е станало по време на хода (например, играч, който трябва да реагира на игрово събитие, не е изпратил своето решение по някакви причини).

Анонс

  • Въведение
  • Настройка на околната среда за разработка, разбиване на задачата на функции
  • Работи по бекенд
  • Работи по фронтенд
  • Настройка на CICD, организация на тестването
  • Стартиране на пробна сесия на играта
  • Итог

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster