antonLytkin18 microservices repository
- Для сохранения списка образов в файл, необходимо выполнить команду:
$ docker images > docker-monolith/docker-1.log
- Основные различия между образом и контейнером описаны в файле
docker-monolith/docker-1.log
.
1.1. Для создания инстанса в GCP и дальнейших манипуляций с ним с помощью docker-machine
, необходимо выполнить команды:
$ export GOOGLE_PROJECT=docker-245017
$ docker-machine create --driver google \
--google-machine-image https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/family/ubuntu-1604-lts \
--google-machine-type n1-standard-1 \
--google-zone europe-west1-b \
docker-host
1.2. Для того, чтобы открыть порт 9292
для доступа извне, необходимо выполнить команду:
$ gcloud compute firewall-rules create reddit-app \
--allow tcp:9292 \
--target-tags=docker-machine \
--description="Allow PUMA connections" \
--direction=INGRESS
1.3. Сменить хост на удаленный:
$ eval $(docker-machine env docker-host)
1.4. Скачать заранее подготовленный образ и запустить контейнер с приложением:
$ docker run --name reddit -d -p 9292:9292 antonlytkin/otus-reddit:1.0
2.1. Перед сборкой образа packer
'ом, необходимо скачать сторонние роли ansible
:
$ ansible-galaxy install -r docker-monolith/infra/ansible/requirements.yml
$ packer build -var-file docker-monolith/infra/packer/variables.json docker-monolith/infra/packer/docker.json
2.2. Для создания инстанса с установленным docker
'ом, необходимо воспользоваться командой:
$ cd docker-monolith/infra/terraform/ && terraform init && terraform apply
2.3. Для деплоя приложения необходимо выполнить команду:
$ cd docker-monolith/infra/ansible/ && ansible-playbook playbooks/deploy.yml
- Для переопределения переменных окружения, заданных в
Dockerfile
'е, необходимо воспользоваться параметром-e
:
$ docker run -d --network=reddit --network-alias=post_db_another --network-alias=comment_db_another mongo:latest
$ docker run -d --network=reddit --network-alias=post_another -e POST_DATABASE_HOST=post_db_another antonlytkin/post:1.0
$ docker run -d --network=reddit --network-alias=comment_another -e COMMENT_DATABASE_HOST=comment_db_another antonlytkin/comment:1.0
$ docker run -d --network=reddit -p 9292:9292 -e POST_SERVICE_HOST=post_another -e COMMENT_SERVICE_HOST=comment_another antonlytkin/ui:1.0
- Для создания отдельного хранилища и подключения его к контейнеру, необходимо выполнить команды:
$ docker volume create reddit_db
$ docker run -d --network=reddit --network-alias=post_db_another --network-alias=comment_db_another -v reddit_db:/data/db mongo:latest
- Для изменения префикса сущностей при запуске контейнеров с помощью
docker-compose
, необходимо выполнить команду:
$ docker-compose -p my_reddit up -d
Однако следует помнить, что остановка запущенных контейнеров должна производиться с указанием того же префикса.
Иначе docker-compose
будет пытаться найти контейнеры в сетях, имеющих префикс по умолчанию:
$ docker-compose -p my_reddit down
- Чтобы иметь возможность редактирования кода, необходимо в
docker-compose.override.yml
добавить соответствия томов для каждого из инстансов:
volumes:
- ./ui:/app
- Для запуска
puma
в режиме отладки, необходимо для каждого инстанса добавить конструкциюcommand
вdocker-compose.override.yml
:
command: ["puma", "--debug", "-w", "2"]
- Для создания инстанса под gitlab, необходимо выполнить команды:
$ export GOOGLE_PROJECT=docker-245017
$ docker-machine create --driver google \
--google-machine-image https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/family/ubuntu-1604-lts \
--google-machine-type n1-standard-1 \
--google-zone europe-west1-b \
gitlab-host
- Открываем необходимые для
Gitlab
'а порты:
$ gcloud compute firewall-rules create gitlab-app \
--allow tcp:80,tcp:443,tcp:2222\
--target-tags=docker-machine \
--description="Allow Gitlab connections" \
--direction=INGRESS
-
Добавляем переменную окружения, хранящую
ip
инстанса. Будет использоваться вdocker-compose.yml
:$ export GITLAB_HOST=$(docker-machine ip gitlab-host)
-
Запускаем контейнеры:
$ eval $(docker-machine env gitlab-host)
$ docker-compose up -d
- Запускаем контейнер с
runner
'ом, который будет запускать команды для всех стадийpipeline
'а:
$ docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
- Запускаем
runner
и вводим все запрашиваемые параметры:
$ docker exec -it gitlab-runner gitlab-runner register --run-untagged --locked=false
- Для того, чтобы
runner
смог поднять контейнер вdocker
'е, необходимо сделать доступным файл сокета путем замены строк в файле конфигурацииrunner
'а:
$ sed -i 's/volumes = \["\/cache"]/volumes = ["\/var\/run\/docker.sock:\/var\/run\/docker.sock", "\/cache"]/g' /srv/gitlab-runner/config/config.toml
- Добавляем переменные, используемые в
.gitlab.ci.yml
в настройкахGitlab
'а:
DOCKER_HUB_USERNAME
DOCKER_HUB_PASSWORD
VERSION
SSH_PRIVATE_KEY
STAGING_IP
- При каждом пуше будет запущена сборка
docker
-образа и по требованию деплой окруженияstage
.
- Создадим правила файрвола и инстанс в GCP, после чего подключимся к удаленному окружению:
$ gcloud compute firewall-rules create prometheus-default --allow tcp:9090
$ gcloud compute firewall-rules create puma-default --allow tcp:9292
$ export GOOGLE_PROJECT=docker-245017
$ docker-machine create --driver google \
--google-machine-image https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/family/ubuntu-1604-lts \
--google-machine-type n1-standard-1 \
--google-zone europe-west1-b \
docker-host
$ eval $(docker-machine env docker-host)
- Соберем образ
mongodb-exporter
:
$ git clone https://github.com/percona/mongodb_exporter.git && cd mongodb_exporter/ && make docker
$ cd ../ && rm -rf mongodb_exporter/
- Соберем образ
blackbox-exporter
:
$ docker build -t $USER_NAME/blackbox-exporter monitoring/blackbox-exporter
- Соберем образ
prometheus
:
$ export USER_NAME=antonlytkin
$ docker build -t $USER_NAME/prometheus monitoring/prometheus
- Запустим контейнеры:
$ cd docker/ && docker-compose up -d
- Образы хранятся в DockerHub'е.
- Создадим необходимые переменные окружения, правила файрвола и инстанс в GCP, после чего подключимся к удаленному окружению:
$ export GOOGLE_PROJECT=docker-245017
$ export USER_NAME=antonlytkin
$ gcloud compute firewall-rules create cadvisor-default --allow tcp:8080
$ gcloud compute firewall-rules create grafana-default --allow tcp:3000
$ gcloud compute firewall-rules create alertmanager-default --allow tcp:9093
$ docker-machine create --driver google \
--google-machine-image https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/family/ubuntu-1604-lts \
--google-machine-type n1-standard-1 \
--google-zone europe-west1-b \
docker-host
$ eval $(docker-machine env docker-host)
- Соберем необходимые образы:
$ docker build -t $USER_NAME/alertmanager monitoring/alertmanager
$ docker build -t $USER_NAME/blackbox-exporter monitoring/blackbox-exporter
$ git clone https://github.com/percona/mongodb_exporter.git && cd mongodb_exporter/ && make docker
$ cd ../ && rm -rf mongodb_exporter/
- Для того, чтобы получать метрики от
docker
'а напрямую, необходимо подключиться к удаленной машине и создать файл/etc/docker/daemon.json
со следующим содержимым:
{
"metrics-addr" : "0.0.0.0:9323",
"experimental" : true
}
После чего перезагрузить docker
:
$ service docker restart
- Для того, чтобы
prometheus
мог отслеживать метрики отdocker
'а, необходимо добавить строки вprometheus.yml
:
- job_name: "docker"
static_configs:
- targets:
- "172.17.0.1:9323"
После чего пересобрать образ prometheus
'а:
$ docker build -t $USER_NAME/prometheus monitoring/prometheus
- Для
grafana
был импортированdashboard
, работающий с метрикамиdocker
'а:
monitoring/grafana/dashboards/DockerEngineMetrics.json
- Запустим контейнеры с микросервисами и мониторингом:
$ cd docker/ && docker-compose up -d && docker-compose -f docker-compose-monitoring.yml up -d
- Собранные образы хранятся в DockerHub'е.
- Создадим необходимые переменные окружения, правила файрвола и инстанс в GCP, после чего подключимся к удаленному окружению:
$ export GOOGLE_PROJECT=docker-245017
$ export USER_NAME=antonlytkin
$ docker-machine create --driver google \
--google-machine-image https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/family/ubuntu-1604-lts \
--google-machine-type n1-standard-1 \
--google-open-port 5601/tcp \
--google-open-port 9292/tcp \
--google-open-port 9411/tcp \
logging
$ eval $(docker-machine env logging)
- Соберем необходимые образы:
$ for i in ui post comment; do cd src/$i; bash docker_build.sh; cd -; done
$ docker build -t $USER_NAME/fluentd logging/fluentd
-
Запустим контейнеры с микросервисами и логированием:
$ cd docker/ && docker-compose -f docker-compose-logging.yml up -d && docker-compose up -d
-
Для парсинга неструктурированного лога необходимо добавить
grok
-шаблон в конфигурациюfluentd
, после чего пересобрать образ:
<filter service.ui>
@type parser
format grok
grok_pattern service=%{WORD:service} \| event=%{WORD:event} \| path=%{GREEDYDATA:path} \| request_id=%{GREEDYDATA:request_id} \| remote_addr=%{IPORHOST:remote_addr} \| method=%{GREEDYDATA:method} \| response_status=%{POSINT:response_status}
key_name message
reserve_data true
</filter>
- Проблема в долгих запросах заключалась в трехсекундном ожидании ответа от сервиса
post
:
time.sleep(3)
- После прохождения туториала Kubernetes The Hard Way необходимо запустить
deployment
'ы:
$ kubectl apply -f kubernetes/reddit/mongo-deployment.yml
$ kubectl apply -f kubernetes/reddit/post-deployment.yml
$ kubectl apply -f kubernetes/reddit/comment-deployment.yml
$ kubectl apply -f kubernetes/reddit/ui-deployment.yml
- В качестве тестирования доступности микросервиса
ui
, необходимо выполнить команды:
$ POD_NAME=$(kubectl get pods -l app=ui -o jsonpath="{.items[0].metadata.name}")
$ kubectl port-forward $POD_NAME 8080:9292
Сервис должен быть доступен по ссылке: http://localhost:8080/
- Для создания
kubernetes
-кластера вGKE
, необходимо выполнить команду:
$ cd kubernetes/terraform/ && terraform init && terraform apply
- Переключим контекст
kubectl
на созданный кластер вGKE
:
$ gcloud container clusters get-credentials my-gke-cluster --zone us-central1-a --project docker-245017
- Добавим
namespace
и применим конфигурацию:
$ cd ../../
$ kubectl apply -f kubernetes/reddit/dev-namespace.yml
$ kubectl apply -n dev -f kubernetes/reddit/
- Получим
ip
иport
ноды, на котором запущено приложение:
$ kubectl get nodes -o wide
$ kubectl describe service ui -n dev | grep NodePort
- Для доступа к
kubernetes-dashboard
выполним команду:
$ kubectl proxy
Затем перейдем по ссылке:
http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/
- Для получения токена авторизации в
kubernetes-dashboard
, необходимо выполнить:
$ kubectl -n kube-system get secret | grep kubernetes-dashboard-token
$ kubectl -n kube-system describe secrets kubernetes-dashboard-token-275cf | grep token:
- Перед применением конфигурации необходимо включить
Network Policy
вGKE
:
Конфигурация типа
NetworkPolicy
не работает с типом нодыg1-small
$ gcloud beta container clusters update my-gke-cluster --zone=us-central1-a --update-addons=NetworkPolicy=ENABLED
$ gcloud beta container clusters update my-gke-cluster --zone=us-central1-a --enable-network-policy
- Создадим диск:
$ gcloud compute disks create --size=25GB --zone=us-central1-a reddit-mongo-disk
- Сгенерируем
tls
-сертификат и приватный ключ, затем вставим их содержимое в конфигурациюkubernetes/reddit/ui-secret.yml
:
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=35.241.45.81"
$ cat tls.crt | base64
$ cat tls.key | base64
- Добавим
namespace
и применим конфигурацию:
$ kubectl apply -f kubernetes/reddit/dev-namespace.yml
$ kubectl apply -n dev -f kubernetes/reddit/
- Для создания
kubernetes
-кластера вGKE
, необходимо выполнить команду:
$ cd kubernetes/terraform/ && terraform init && terraform apply
- Переключим контекст
kubectl
на созданный кластер вGKE
:
$ gcloud container clusters get-credentials my-gke-cluster --zone us-central1-a --project docker-245017
- Установим конфигурацию пользователя для
tiller
'а и запустим его:
$ kubectl apply -f kubernetes/tiller.yml
$ helm init --service-account tiller
- Установим
gitlab
:
В случае, если
chart
отсутствует, необходимо выполнить:
$ helm repo add gitlab https://charts.gitlab.io
$ cd kubernetes/Charts/
$ helm fetch gitlab/gitlab-omnibus --version 0.1.37 --untar
Если
chart
уже получен, нужно его установить:
$ cd gitlab-omnibus/
$ helm install --name gitlab . -f values.yaml
- Пропишем
ip
-адрес дляingress
'аgitlab
'а в/etc/hosts
:
$ echo "34.68.100.30 gitlab-gitlab staging production antonlytkin-ui-feature-3 antonlytkin-post-feature-3 antonlytkin-comment-feature-3" >> /etc/hosts
Для просмотра
ip
, по которому должен быть доступенgitlab
, необходимо выполнить:
$ kubectl get ingresses -n nginx-ingress nginx
- После регистрации в
gitlab
'е и создания новой группы, необходимо прописать переменные окружения с логином / паролем отDocker Hub
'а для деплоя:
Переменные не должны быть приватными
CI_REGISTRY_USER = antonlytkin
CI_REGISTRY_PASSWORD = *******
- Создадим репозиторий приложения:
$ cd kubernetes/Charts/ && git init
$ git remote add origin http://gitlab-gitlab/antonlytkin/reddit-deploy.git
$ git add . && git reset -- gitlab-omnibus
$ git commit -m "Init" && git push origin master
- Создадим репозитории для каждого из микросервисов:
$ cd src/ui/ && git init
$ git remote add origin http://gitlab-gitlab/antonlytkin/ui.git
$ git add .
$ git commit -m "Init"
$ git checkout -b master && git push origin master
$ git checkout -b feature/3 && git push origin feature/3
Далее необходимо перезапустить
pipeline
'ы в каждом из репозиториев
- Почистим репозиторий и удалим кластер:
$ rm -rf src/ui/.git src/post/.git src/comment/.git kubernetes/Charts/.git
$ cd kubernetes/terraform/ && terraform destroy
- Для создания
kubernetes
-кластера вGKE
, необходимо выполнить команду:
$ cd kubernetes/terraform/ && terraform init && terraform apply
- Переключим контекст
kubectl
на созданный кластер вGKE
:
$ gcloud container clusters get-credentials my-gke-cluster --zone us-central1-a --project docker-245017
- Установим конфигурацию пользователя для
tiller
'а и запустим его:
$ kubectl apply -f kubernetes/tiller.yml
$ helm init --service-account tiller
- Установим
nginx
:
$ helm install stable/nginx-ingress --name nginx
- Пропишем
ip
-адрес сервиса, по которому доступенnginx
в/etc/hosts
:
$ echo "35.226.19.239 reddit reddit-prometheus reddit-grafana reddit-non-prod production reddit-kibana staging prod" >> /etc/hosts
Для получения
ip
, по которому должен быть доступенnginx
, необходимо выполнить:
$ kubectl get svc nginx-nginx-ingress-controller
- Установим
prometheus
:
$ cd kubernetes/Charts && helm fetch --untar stable/prometheus
$ cd prometheus/ && helm upgrade prom . -f custom_values.yaml --install
- Запустим окружения с приложением:
$ cd ../
$ helm dep build reddit
$ helm upgrade reddit-test ./reddit --install
$ helm upgrade production --namespace production ./reddit --install
$ helm upgrade staging --namespace staging ./reddit --install
- Установим
grafana
:
{
helm upgrade --install grafana stable/grafana \
--set adminPassword="admin" \
--set service.type="NodePort" \
--set ingress.enabled="true" \
--set ingress.hosts="{reddit-grafana}"
}
Dashboard
, отображающий метрики в разрезе окружения, расположен по пути:
kubernetes/grafana/dashboards/ui_service.json
- Пометим
node
'у, на которой будет расположенElasticSearch
и установим манифесты:
$ kubectl label node gke-my-gke-cluster-my-node-pool-ea2a05dd-3kb9 elastichost=true
$ kubectl apply -f ./efk
- Установим
kibana
:
{
helm upgrade --install kibana stable/kibana \
--set ingress.enabled="true" \
--set ingress.hosts="{reddit-kibana}" \
--set env.ELASTICSEARCH_URL="http://elasticsearch-logging:9200" \
--version 0.1.1
}