HTML Diff
1 added 1 removed
Original 2026-01-01
Modified 2026-03-10
1 <p>Теги: devops, docker, terraform, инфраструктура, девопс, kubernetes, gcp, ci/cd-система, travis-ci, конфигурация</p>
1 <p>Теги: devops, docker, terraform, инфраструктура, девопс, kubernetes, gcp, ci/cd-система, travis-ci, конфигурация</p>
2 <p>В конце курса "<a>DevOps практики и инструменты</a>" студентов ждёт выполнение проекта. Это самостоятельная работа, необходимая для закрепления полученных знаний. Предлагаем вашему вниманию проект<strong>Александра Баркова</strong>, одного из лучших выпускников курса.</p>
2 <p>В конце курса "<a>DevOps практики и инструменты</a>" студентов ждёт выполнение проекта. Это самостоятельная работа, необходимая для закрепления полученных знаний. Предлагаем вашему вниманию проект<strong>Александра Баркова</strong>, одного из лучших выпускников курса.</p>
3 - <p>В своей работе Александр реализовал<strong>прототип инфраструктурной конфигурации</strong>, обеспечивающей работу и CI/CD тестового приложения. Тестовое приложение включало в себя бэкенд в виде PHP-приложения (Symfony), фронтенд (Vue.js), базу данных (Postgres). Стэк был выбран максимально близким к тому что использовался в повседневной работе, с целью обкатать инфраструктурную конфигурацию и набраться опыта, применить полученные во время обучения знания и практические наработки.</p>
3 + <p>В своей работе Александр реализовал<strong>прототип инфраструктурной конфигурации</strong>, обеспечивающй работу и CI/CD тестового приложения. Тестовое приложение включало в себя бэкенд в виде PHP-приложения (Symfony), фронтенд (Vue.js), базу данных (Postgres). Стэк был выбран максимально близким к тому что использовался в повседневной работе, с целью обкатать инфраструктурную конфигурацию и набраться опыта, применить полученные во время обучения знания и практические наработки.</p>
4 <p>Проектная работа реализовывалась с прицелом на то, чтобы потом максимально использовать её результат на основном проекте на работе - что и было успешно сделано после окончания курса.</p>
4 <p>Проектная работа реализовывалась с прицелом на то, чтобы потом максимально использовать её результат на основном проекте на работе - что и было успешно сделано после окончания курса.</p>
5 <p>Давайте рассмотрим технические особенности реализации проекта.</p>
5 <p>Давайте рассмотрим технические особенности реализации проекта.</p>
6 <h2>Описание планируемых компонент</h2>
6 <h2>Описание планируемых компонент</h2>
7 <p>1.<strong>Развёртывание кластера Kubernetes</strong>: - с помощью kubespray; - с помощью Rancher Kubernetes Engine (RKE).</p>
7 <p>1.<strong>Развёртывание кластера Kubernetes</strong>: - с помощью kubespray; - с помощью Rancher Kubernetes Engine (RKE).</p>
8 <p>2.<strong>Kuberetes-кластер</strong>, состоящий из следующих компонент: 1) Kubernetes Dashboard; 2) Cert-manager; 3) Nginx ingress controller; 4) NFS client provisioner; 5) Gitlab: - GitLab Runner; - GitLab Registry; - Minio; 6) мониторинг: - Prometheus; - Grafana; 7) логирование (EFK): - Elasticsearch; - Fluentd; - Kibana; 8) Postgres Operator (zalando); - мессенджер Mattermost; - панель управления Rancher.</p>
8 <p>2.<strong>Kuberetes-кластер</strong>, состоящий из следующих компонент: 1) Kubernetes Dashboard; 2) Cert-manager; 3) Nginx ingress controller; 4) NFS client provisioner; 5) Gitlab: - GitLab Runner; - GitLab Registry; - Minio; 6) мониторинг: - Prometheus; - Grafana; 7) логирование (EFK): - Elasticsearch; - Fluentd; - Kibana; 8) Postgres Operator (zalando); - мессенджер Mattermost; - панель управления Rancher.</p>
9 <p>3.<strong>Микросервисное приложение на стэке PHP</strong>(фрэймворк Symfony), JavaScript (Vue.js) и PostgreSQL.</p>
9 <p>3.<strong>Микросервисное приложение на стэке PHP</strong>(фрэймворк Symfony), JavaScript (Vue.js) и PostgreSQL.</p>
10 <h2>Порядок развёртывания кластера и компонент</h2>
10 <h2>Порядок развёртывания кластера и компонент</h2>
11 <h3>Развёртывание кластера с помощью kubespray</h3>
11 <h3>Развёртывание кластера с помощью kubespray</h3>
12 <ul><li>Получить инфраструктурный репозиторий:</li>
12 <ul><li>Получить инфраструктурный репозиторий:</li>
13 </ul>git clone git@github.com:bars83/symfony-k8s-boilerplate.git cd symfony-k8s-boilerplate<ul><li>В файл ./infra/kubespray-cluster-vars/inventory.ini нужно прописать доступные ноды. В проекте используется 5 ВМ, запущенных в GCP, каждая из ВМ под управлением Ubuntu 18.04 LTS со статическим внутренним IP-адресом. На одной из ВМ так же добавлен статический внешний IP-адрес. Между нодами по внутренней сети на фаерволе открыты все порты. В идеале ноды в облаке должны создаваться с помощью Terraform, но это осталось за рамками проектной работы.</li>
13 </ul>git clone git@github.com:bars83/symfony-k8s-boilerplate.git cd symfony-k8s-boilerplate<ul><li>В файл ./infra/kubespray-cluster-vars/inventory.ini нужно прописать доступные ноды. В проекте используется 5 ВМ, запущенных в GCP, каждая из ВМ под управлением Ubuntu 18.04 LTS со статическим внутренним IP-адресом. На одной из ВМ так же добавлен статический внешний IP-адрес. Между нодами по внутренней сети на фаерволе открыты все порты. В идеале ноды в облаке должны создаваться с помощью Terraform, но это осталось за рамками проектной работы.</li>
14 <li>Настройка кластера (!подразумевается наличие ключей appuser на клиенте, также эти ключи должны быть прописаниы на виртуальных машинах!):</li>
14 <li>Настройка кластера (!подразумевается наличие ключей appuser на клиенте, также эти ключи должны быть прописаниы на виртуальных машинах!):</li>
15 </ul>cd infra/kubespray &amp;&amp; ansible-playbook --flush-cache -i ../kubespray-cluster-vars/inventory.ini --become cluster.yml --private-key=~/.ssh/appuser<ul><li>Дождаться завершения (~40 минут для кластера из 5 нод).</li>
15 </ul>cd infra/kubespray &amp;&amp; ansible-playbook --flush-cache -i ../kubespray-cluster-vars/inventory.ini --become cluster.yml --private-key=~/.ssh/appuser<ul><li>Дождаться завершения (~40 минут для кластера из 5 нод).</li>
16 <li>Скопировать конфиг с конекстом для работы с кластером через kubectl:</li>
16 <li>Скопировать конфиг с конекстом для работы с кластером через kubectl:</li>
17 </ul>cp infra/kubespray-cluster-vars/artifacts/admin.conf ~/.kube/config<h3>Развёртывание кластера с помощью RKE</h3>
17 </ul>cp infra/kubespray-cluster-vars/artifacts/admin.conf ~/.kube/config<h3>Развёртывание кластера с помощью RKE</h3>
18 <ul><li>Получить инфраструктурный репозиторий:</li>
18 <ul><li>Получить инфраструктурный репозиторий:</li>
19 </ul>git clone git@github.com:bars83/symfony-k8s-boilerplate.git cd symfony-k8s-boilerplate<ul><li>В файл infra/rancher-cluster/rancher-cluster.yml прописать доступные ноды.</li>
19 </ul>git clone git@github.com:bars83/symfony-k8s-boilerplate.git cd symfony-k8s-boilerplate<ul><li>В файл infra/rancher-cluster/rancher-cluster.yml прописать доступные ноды.</li>
20 <li>На нодах должен быть предустановлен docker engine, пользователь (appuser в рамках работы) должен быть добавлен в группу docker.</li>
20 <li>На нодах должен быть предустановлен docker engine, пользователь (appuser в рамках работы) должен быть добавлен в группу docker.</li>
21 <li>Установить CLI к себе на клиента (в примере клиент для Linux/amd64):</li>
21 <li>Установить CLI к себе на клиента (в примере клиент для Linux/amd64):</li>
22 </ul>wget https://github.com/rancher/rke/releases/download/v0.3.2/rke_linux-amd64 mv rke /usr/local/bin/rke<ul><li>Развёртывание кластера:</li>
22 </ul>wget https://github.com/rancher/rke/releases/download/v0.3.2/rke_linux-amd64 mv rke /usr/local/bin/rke<ul><li>Развёртывание кластера:</li>
23 </ul>rke up --config infra/rancher-cluster/rancher-cluster.yml<h3>Настройка Helm</h3>
23 </ul>rke up --config infra/rancher-cluster/rancher-cluster.yml<h3>Настройка Helm</h3>
24 kubectl apply -f infra/rbac-tiller/rbac-config.yaml helm init --service-account tiller --upgrade<h3>Настройка NFS для хранения persistent volume claims кластера</h3>
24 kubectl apply -f infra/rbac-tiller/rbac-config.yaml helm init --service-account tiller --upgrade<h3>Настройка NFS для хранения persistent volume claims кластера</h3>
25 <ul><li>Настройка NFS сервера (в данном случае в GCP):</li>
25 <ul><li>Настройка NFS сервера (в данном случае в GCP):</li>
26 </ul>gcloud filestore instances create nfs-server \ --project=sylvan-flight-244217 \ --zone=us-central1-a \ --tier=STANDARD \ --file-share=name="vol1",capacity=1TB \ --network=name="default"<ul><li>На каждой ВМ кластера установить NFS-клиент (лучше это сделать тоже с помощью ansible, но в рамках курсовой работы сделано руками... ):</li>
26 </ul>gcloud filestore instances create nfs-server \ --project=sylvan-flight-244217 \ --zone=us-central1-a \ --tier=STANDARD \ --file-share=name="vol1",capacity=1TB \ --network=name="default"<ul><li>На каждой ВМ кластера установить NFS-клиент (лучше это сделать тоже с помощью ansible, но в рамках курсовой работы сделано руками... ):</li>
27 </ul>sudo apt update &amp;&amp; sudo apt install -y nfs-common<ul><li>Установка NFS client provisioner:</li>
27 </ul>sudo apt update &amp;&amp; sudo apt install -y nfs-common<ul><li>Установка NFS client provisioner:</li>
28 </ul>helm install --name nfs-client-provisioner --namespace kube-system --set nfs.server=10.128.15.213 --set nfs.path=/mnt/disks/sdb/common --set storageClass.defaultClass=true stable/nfs-client-provisioner<h3>Установка Nginx ingress controller</h3>
28 </ul>helm install --name nfs-client-provisioner --namespace kube-system --set nfs.server=10.128.15.213 --set nfs.path=/mnt/disks/sdb/common --set storageClass.defaultClass=true stable/nfs-client-provisioner<h3>Установка Nginx ingress controller</h3>
29 helm install --name nginx-ingress --namespace kube-system -f ./infra/k8s-ingress/custom_values.yaml stable/nginx-ingress<ul><li>Т. к. у нас нет облачного балансировщика, то на ВМ с внешним адресом нужно установить nginx, и для него применить конфигурацию из этого репозитория:</li>
29 helm install --name nginx-ingress --namespace kube-system -f ./infra/k8s-ingress/custom_values.yaml stable/nginx-ingress<ul><li>Т. к. у нас нет облачного балансировщика, то на ВМ с внешним адресом нужно установить nginx, и для него применить конфигурацию из этого репозитория:</li>
30 </ul>scp ./infra/nginx/nginx.conf 10.128.15.213:/home/appuser/nginx/ - это выполнять на клиенте sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 -p 50022:50022 -v /home/appuser/nginx/nginx.conf:/etc/nginx/nginx.conf nginx:1.14 - это на ВМ с внешним адресом<h3>Установка Cert manager для автоматического получения Letsencrypt-сертификатов</h3>
30 </ul>scp ./infra/nginx/nginx.conf 10.128.15.213:/home/appuser/nginx/ - это выполнять на клиенте sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 -p 50022:50022 -v /home/appuser/nginx/nginx.conf:/etc/nginx/nginx.conf nginx:1.14 - это на ВМ с внешним адресом<h3>Установка Cert manager для автоматического получения Letsencrypt-сертификатов</h3>
31 kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.11/deploy/manifests/00-crds.yaml helm repo add jetstack https://charts.jetstack.io helm install --name cert-manager --namespace cert-manager jetstack/cert-manager kubectl apply -f infra/k8s-letsencrypt/letsencrypt.yaml<h3>Установка Kubernetes Dashboard (требуется только в варианте с RKE, а в варианте с kubespray она уже установлена)</h3>
31 kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.11/deploy/manifests/00-crds.yaml helm repo add jetstack https://charts.jetstack.io helm install --name cert-manager --namespace cert-manager jetstack/cert-manager kubectl apply -f infra/k8s-letsencrypt/letsencrypt.yaml<h3>Установка Kubernetes Dashboard (требуется только в варианте с RKE, а в варианте с kubespray она уже установлена)</h3>
32 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml<h3>Доступ к Kubernetes Dashboard</h3>
32 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml<h3>Доступ к Kubernetes Dashboard</h3>
33 kubectl apply -f ./infra/dashboard-adminuser.yaml kubectl apply -f infra/dashboard-ingress.yaml kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}') - получение токена<ul><li>панель доступна по ссылке https://dash.kubeplay.website токен для доступа - на предыдущем шаге.</li>
33 kubectl apply -f ./infra/dashboard-adminuser.yaml kubectl apply -f infra/dashboard-ingress.yaml kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}') - получение токена<ul><li>панель доступна по ссылке https://dash.kubeplay.website токен для доступа - на предыдущем шаге.</li>
34 </ul><h3>Установка мессенджера Mattermost</h3>
34 </ul><h3>Установка мессенджера Mattermost</h3>
35 <ul><li>helm repo add mattermost https://helm.mattermost.com</li>
35 <ul><li>helm repo add mattermost https://helm.mattermost.com</li>
36 <li>helm install --namespace mattermost --name mattermost -f ./mattermost/custom.yaml mattermost/mattermost-team-edition</li>
36 <li>helm install --namespace mattermost --name mattermost -f ./mattermost/custom.yaml mattermost/mattermost-team-edition</li>
37 </ul><h2>Установка и настройка сервисов мониторинга и алертинга</h2>
37 </ul><h2>Установка и настройка сервисов мониторинга и алертинга</h2>
38 <ul><li>helm install --namespace monitoring --name prometheus -f ./infra/k8s-monitoring/prom_custom.yaml stable/prometheus</li>
38 <ul><li>helm install --namespace monitoring --name prometheus -f ./infra/k8s-monitoring/prom_custom.yaml stable/prometheus</li>
39 <li>helm install --namespace monitoring --name grafana -f ./infra/k8s-monitoring/grafana_custom.yaml stable/grafana</li>
39 <li>helm install --namespace monitoring --name grafana -f ./infra/k8s-monitoring/grafana_custom.yaml stable/grafana</li>
40 <li>kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo - пароль для доступа к Grafana</li>
40 <li>kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo - пароль для доступа к Grafana</li>
41 <li>export POD_NAME=$(kubectl get pods --namespace monitoring -l "app=prometheus,component=server" -o jsonpath="{.items[0].metadata.name}"); kubectl --namespace monitoring port-forward $POD_NAME 9095:9090 - попасть на веб-интерфейс Prometheus'а можно через http://localhost:9095</li>
41 <li>export POD_NAME=$(kubectl get pods --namespace monitoring -l "app=prometheus,component=server" -o jsonpath="{.items[0].metadata.name}"); kubectl --namespace monitoring port-forward $POD_NAME 9095:9090 - попасть на веб-интерфейс Prometheus'а можно через http://localhost:9095</li>
42 <li>Метрики для кластера:</li>
42 <li>Метрики для кластера:</li>
43 </ul>git clone https://github.com/kubernetes-incubator/metrics-server.git ./infra/k8s-metrics cp ./infra/k8s-monitoring/metrics-server-deployment.yaml ./infra/k8s-metrics/deploy/1.8+/ - оригинальный манифест немного изменён для того, чтобы экспортер мог собирать метрики с эндпоинтов с самоподписанными сертификатами kubectl apply -f ./infra/k8s-metrics/deploy/1.8+<h3>Postgres Operator (zalando/postgres-operator)</h3>
43 </ul>git clone https://github.com/kubernetes-incubator/metrics-server.git ./infra/k8s-metrics cp ./infra/k8s-monitoring/metrics-server-deployment.yaml ./infra/k8s-metrics/deploy/1.8+/ - оригинальный манифест немного изменён для того, чтобы экспортер мог собирать метрики с эндпоинтов с самоподписанными сертификатами kubectl apply -f ./infra/k8s-metrics/deploy/1.8+<h3>Postgres Operator (zalando/postgres-operator)</h3>
44 <ul><li>git clone https://github.com/zalando/postgres-operator ./infra/zalando</li>
44 <ul><li>git clone https://github.com/zalando/postgres-operator ./infra/zalando</li>
45 <li>helm install --name zalando --namespace zalando ./infra/zalando/charts/postgres-operator</li>
45 <li>helm install --name zalando --namespace zalando ./infra/zalando/charts/postgres-operator</li>
46 </ul><h3>GitLab</h3>
46 </ul><h3>GitLab</h3>
47 <ul><li>helm repo add gitlab https://charts.gitlab.io &amp;&amp; helm repo update</li>
47 <ul><li>helm repo add gitlab https://charts.gitlab.io &amp;&amp; helm repo update</li>
48 <li>При установке через kubespray:</li>
48 <li>При установке через kubespray:</li>
49 </ul>kubectl label nodes node3 gitlab-runner=true<ul><li>helm fetch gitlab/gitlab --untar --untardir ./infra/gitlab</li>
49 </ul>kubectl label nodes node3 gitlab-runner=true<ul><li>helm fetch gitlab/gitlab --untar --untardir ./infra/gitlab</li>
50 <li>cp ./infra/gitlab/runner-custom-configmap.yaml ./infra/gitlab/gitlab/charts/gitlab-runner/templates/configmap.yaml - кастомный configmap, позволяющий пробрасывать хостовый /var/run/docker.sock в под с гитлаб-раннером, для доступа к кэшу образов</li>
50 <li>cp ./infra/gitlab/runner-custom-configmap.yaml ./infra/gitlab/gitlab/charts/gitlab-runner/templates/configmap.yaml - кастомный configmap, позволяющий пробрасывать хостовый /var/run/docker.sock в под с гитлаб-раннером, для доступа к кэшу образов</li>
51 <li>helm install --namespace gitlab --name gitlab -f ./infra/gitlab/custom_values.yaml ./infra/gitlab/gitlab</li>
51 <li>helm install --namespace gitlab --name gitlab -f ./infra/gitlab/custom_values.yaml ./infra/gitlab/gitlab</li>
52 <li>kubectl get secret -n gitlab gitlab-gitlab-initial-root-password -ojsonpath='{.data.password}' | base64 --decode ; echo - пароль для доступа к GitLab</li>
52 <li>kubectl get secret -n gitlab gitlab-gitlab-initial-root-password -ojsonpath='{.data.password}' | base64 --decode ; echo - пароль для доступа к GitLab</li>
53 <li>echo 'access_key:';kubectl get secret -n gitlab gitlab-minio-secret -ojsonpath='{.data.accesskey}' | base64 --decode ; echo &amp;&amp; echo 'secret_key:'; kubectl get secret -n gitlab gitlab-minio-secret -ojsonpath='{.data.secretkey}' | base64 --decode ; echo - доступ к minio.</li>
53 <li>echo 'access_key:';kubectl get secret -n gitlab gitlab-minio-secret -ojsonpath='{.data.accesskey}' | base64 --decode ; echo &amp;&amp; echo 'secret_key:'; kubectl get secret -n gitlab gitlab-minio-secret -ojsonpath='{.data.secretkey}' | base64 --decode ; echo - доступ к minio.</li>
54 </ul><h3>Логгирование (EFK)</h3>
54 </ul><h3>Логгирование (EFK)</h3>
55 <ul><li>При установке через kubespray:</li>
55 <ul><li>При установке через kubespray:</li>
56 </ul>kubectl label nodes node3 elastichost=true for i in 1 2 3 4 5; do kubectl label nodes node${i} beta.kubernetes.io/fluentd-ds-ready=true; done<ul><li>kubectl create ns logging</li>
56 </ul>kubectl label nodes node3 elastichost=true for i in 1 2 3 4 5; do kubectl label nodes node${i} beta.kubernetes.io/fluentd-ds-ready=true; done<ul><li>kubectl create ns logging</li>
57 <li>kubectl apply -f ./infra/efk/fluentd -n logging</li>
57 <li>kubectl apply -f ./infra/efk/fluentd -n logging</li>
58 <li>helm repo add elastic https://helm.elastic.co</li>
58 <li>helm repo add elastic https://helm.elastic.co</li>
59 <li>helm install --namespace logging --name elasticsearch -f ./infra/efk/elastic_custom_values.yaml elastic/elasticsearch</li>
59 <li>helm install --namespace logging --name elasticsearch -f ./infra/efk/elastic_custom_values.yaml elastic/elasticsearch</li>
60 <li>helm install --namespace logging --name kibana -f ./infra/efk/kibana_custom_values.yaml elastic/kibana</li>
60 <li>helm install --namespace logging --name kibana -f ./infra/efk/kibana_custom_values.yaml elastic/kibana</li>
61 </ul><h3>Панель управления Rancher Kubernetes Engine (для соответствующего варианта установки)</h3>
61 </ul><h3>Панель управления Rancher Kubernetes Engine (для соответствующего варианта установки)</h3>
62 helm install --namespace cattle-system --name rancher -f ./infra/rancher-cluster/helm_custom.yaml ./infra/rancher-chart/rancher<p>Более подробно ознакомиться с особенностями реализации проекта вы можете по<a>ссылке на GitHub</a>.</p>
62 helm install --namespace cattle-system --name rancher -f ./infra/rancher-cluster/helm_custom.yaml ./infra/rancher-chart/rancher<p>Более подробно ознакомиться с особенностями реализации проекта вы можете по<a>ссылке на GitHub</a>.</p>
63  
63