Skip to content

otus-devops-2019-02/antonLytkin18_microservices

Repository files navigation

antonLytkin18_microservices

antonLytkin18 microservices repository

Build Status

Домашнее задание №12

  1. Для сохранения списка образов в файл, необходимо выполнить команду:

$ docker images > docker-monolith/docker-1.log

  1. Основные различия между образом и контейнером описаны в файле docker-monolith/docker-1.log.

Домашнее задание №13

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

Домашнее задание №14

  1. Для переопределения переменных окружения, заданных в 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
  1. Для создания отдельного хранилища и подключения его к контейнеру, необходимо выполнить команды:
$ 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

Домашнее задание №15

  1. Для изменения префикса сущностей при запуске контейнеров с помощью docker-compose, необходимо выполнить команду:

$ docker-compose -p my_reddit up -d

Однако следует помнить, что остановка запущенных контейнеров должна производиться с указанием того же префикса.

Иначе docker-compose будет пытаться найти контейнеры в сетях, имеющих префикс по умолчанию:

$ docker-compose -p my_reddit down

  1. Чтобы иметь возможность редактирования кода, необходимо в docker-compose.override.yml добавить соответствия томов для каждого из инстансов:
volumes:
  - ./ui:/app
  1. Для запуска puma в режиме отладки, необходимо для каждого инстанса добавить конструкцию command в docker-compose.override.yml:
command: ["puma", "--debug", "-w", "2"]

Домашнее задание №16

  1. Для создания инстанса под 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
  1. Открываем необходимые для 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 
  1. Добавляем переменную окружения, хранящую ip инстанса. Будет использоваться в docker-compose.yml: $ export GITLAB_HOST=$(docker-machine ip gitlab-host)

  2. Запускаем контейнеры:

$ eval $(docker-machine env gitlab-host)
$ docker-compose up -d
  1. Запускаем контейнер с 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 
  1. Запускаем runner и вводим все запрашиваемые параметры:

$ docker exec -it gitlab-runner gitlab-runner register --run-untagged --locked=false

  1. Для того, чтобы 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

  1. Добавляем переменные, используемые в .gitlab.ci.yml в настройках Gitlab'а:
DOCKER_HUB_USERNAME
DOCKER_HUB_PASSWORD
VERSION
SSH_PRIVATE_KEY
STAGING_IP
  1. При каждом пуше будет запущена сборка docker-образа и по требованию деплой окружения stage.

Домашнее задание №17

  1. Создадим правила файрвола и инстанс в 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)
  1. Соберем образ mongodb-exporter:
$ git clone https://github.com/percona/mongodb_exporter.git && cd mongodb_exporter/ && make docker
$ cd ../ && rm -rf mongodb_exporter/
  1. Соберем образ blackbox-exporter:
$ docker build -t $USER_NAME/blackbox-exporter monitoring/blackbox-exporter
  1. Соберем образ prometheus:
$ export USER_NAME=antonlytkin
$ docker build -t $USER_NAME/prometheus monitoring/prometheus
  1. Запустим контейнеры:
$ cd docker/ && docker-compose up -d
  1. Образы хранятся в DockerHub'е.

Домашнее задание №18

  1. Создадим необходимые переменные окружения, правила файрвола и инстанс в 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)
  1. Соберем необходимые образы:
$ 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/
  1. Для того, чтобы получать метрики от docker'а напрямую, необходимо подключиться к удаленной машине и создать файл /etc/docker/daemon.json со следующим содержимым:
{
  "metrics-addr" : "0.0.0.0:9323",
  "experimental" : true
}

После чего перезагрузить docker:

$ service docker restart

  1. Для того, чтобы prometheus мог отслеживать метрики от docker'а, необходимо добавить строки в prometheus.yml:
  - job_name: "docker"
    static_configs:
      - targets:
          - "172.17.0.1:9323"

После чего пересобрать образ prometheus'а:

$ docker build -t $USER_NAME/prometheus monitoring/prometheus

  1. Для grafana был импортирован dashboard, работающий с метриками docker'а:

monitoring/grafana/dashboards/DockerEngineMetrics.json

  1. Запустим контейнеры с микросервисами и мониторингом:
$ cd docker/ && docker-compose up -d && docker-compose -f docker-compose-monitoring.yml up -d
  1. Собранные образы хранятся в DockerHub'е.

Домашнее задание №19

  1. Создадим необходимые переменные окружения, правила файрвола и инстанс в 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)
  1. Соберем необходимые образы:
$ for i in ui post comment; do cd src/$i; bash docker_build.sh; cd -; done
$ docker build -t $USER_NAME/fluentd logging/fluentd
  1. Запустим контейнеры с микросервисами и логированием: $ cd docker/ && docker-compose -f docker-compose-logging.yml up -d && docker-compose up -d

  2. Для парсинга неструктурированного лога необходимо добавить 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>
  1. Проблема в долгих запросах заключалась в трехсекундном ожидании ответа от сервиса post:
time.sleep(3)

Домашнее задание №20

  1. После прохождения туториала 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
  1. В качестве тестирования доступности микросервиса 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/

Домашнее задание №21

  1. Для создания kubernetes-кластера в GKE, необходимо выполнить команду:
$ cd kubernetes/terraform/ && terraform init && terraform apply
  1. Переключим контекст kubectl на созданный кластер в GKE:
$ gcloud container clusters get-credentials my-gke-cluster --zone us-central1-a --project docker-245017
  1. Добавим namespace и применим конфигурацию:
$ cd ../../
$ kubectl apply -f kubernetes/reddit/dev-namespace.yml
$ kubectl apply -n dev -f kubernetes/reddit/
  1. Получим ip и port ноды, на котором запущено приложение:
$ kubectl get nodes -o wide
$ kubectl describe service ui -n dev | grep NodePort
  1. Для доступа к kubernetes-dashboard выполним команду:
$ kubectl proxy

Затем перейдем по ссылке:

http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/

  1. Для получения токена авторизации в kubernetes-dashboard, необходимо выполнить:
$ kubectl -n kube-system get secret | grep kubernetes-dashboard-token
$ kubectl -n kube-system describe secrets kubernetes-dashboard-token-275cf | grep token:

Домашнее задание №22

  1. Перед применением конфигурации необходимо включить 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
  1. Создадим диск:
$ gcloud compute disks create --size=25GB --zone=us-central1-a reddit-mongo-disk
  1. Сгенерируем 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
  1. Добавим namespace и применим конфигурацию:
$ kubectl apply -f kubernetes/reddit/dev-namespace.yml
$ kubectl apply -n dev -f kubernetes/reddit/

Домашнее задание №23

  1. Для создания kubernetes-кластера в GKE, необходимо выполнить команду:
$ cd kubernetes/terraform/ && terraform init && terraform apply
  1. Переключим контекст kubectl на созданный кластер в GKE:
$ gcloud container clusters get-credentials my-gke-cluster --zone us-central1-a --project docker-245017
  1. Установим конфигурацию пользователя для tiller'а и запустим его:
$ kubectl apply -f kubernetes/tiller.yml
$ helm init --service-account tiller
  1. Установим 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
  1. Пропишем ip-адрес для ingressgitlab'а в /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
  1. После регистрации в gitlab'е и создания новой группы, необходимо прописать переменные окружения с логином / паролем от Docker Hub'а для деплоя:

Переменные не должны быть приватными

CI_REGISTRY_USER = antonlytkin
CI_REGISTRY_PASSWORD = *******
  1. Создадим репозиторий приложения:
$ 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
  1. Создадим репозитории для каждого из микросервисов:
$ 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'ы в каждом из репозиториев

  1. Почистим репозиторий и удалим кластер:
$ rm -rf src/ui/.git src/post/.git src/comment/.git kubernetes/Charts/.git
$ cd kubernetes/terraform/ && terraform destroy

Домашнее задание №24

  1. Для создания kubernetes-кластера в GKE, необходимо выполнить команду:
$ cd kubernetes/terraform/ && terraform init && terraform apply
  1. Переключим контекст kubectl на созданный кластер в GKE:
$ gcloud container clusters get-credentials my-gke-cluster --zone us-central1-a --project docker-245017
  1. Установим конфигурацию пользователя для tiller'а и запустим его:
$ kubectl apply -f kubernetes/tiller.yml
$ helm init --service-account tiller
  1. Установим nginx:
$ helm install stable/nginx-ingress --name nginx
  1. Пропишем 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
  1. Установим prometheus:
$ cd kubernetes/Charts && helm fetch --untar stable/prometheus
$ cd prometheus/ && helm upgrade prom . -f custom_values.yaml --install
  1. Запустим окружения с приложением:
$ 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
  1. Установим grafana:
{
helm upgrade --install grafana stable/grafana \
  --set adminPassword="admin" \
  --set service.type="NodePort" \
  --set ingress.enabled="true" \
  --set ingress.hosts="{reddit-grafana}"
}
  1. Dashboard, отображающий метрики в разрезе окружения, расположен по пути:

kubernetes/grafana/dashboards/ui_service.json

  1. Пометим node'у, на которой будет расположен ElasticSearch и установим манифесты:
$ kubectl label node gke-my-gke-cluster-my-node-pool-ea2a05dd-3kb9 elastichost=true 
$ kubectl apply -f ./efk
  1. Установим 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
}