mirror of
https://github.com/slurm-personal/school-dev-k8s.git
synced 2026-06-27 13:50:24 +00:00
Add 17th practice
This commit is contained in:
@@ -0,0 +1,224 @@
|
|||||||
|
### HPA v1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**1. Запускаем Metric server (!!! только при выполнении практики на собственном кластере - Minikube и тд)**
|
||||||
|
|
||||||
|
* Применяем манифесты Metric server
|
||||||
|
|
||||||
|
Поскольку Metric server не устанавливается в Kubernetes кластер по умолчанию, первое что необходимо сделать - это установить его. Все необходимые манифесты находятся в каталоге `for-minikube-only-metric-server` и их можно сразу применить в кластер. Для этого необходимо в консоли выполнить команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f for-minikube-only-metrics-server/ -n kube-system
|
||||||
|
```
|
||||||
|
|
||||||
|
* Проверяем работу Metric server
|
||||||
|
|
||||||
|
Metric server собирает данные с kubelet c периодичностью 1 раз в минуту. После установки необходимо подождать 1-2 минуты и выполнить команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl top node
|
||||||
|
```
|
||||||
|
|
||||||
|
Данная команда выведет текущую нагрузку на ноды. В результате выполнения команды на экран будут выведены примерно следующие данные:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
|
||||||
|
master-1.s000000.slurm.io 122m 12% 1693Mi 44%
|
||||||
|
master-2.s000000.slurm.io 114m 11% 1489Mi 38%
|
||||||
|
master-3.s000000.slurm.io 97m 9% 1423Mi 37%
|
||||||
|
node-1.s000000.slurm.io 59m 5% 1505Mi 39%
|
||||||
|
node-2.s000000.slurm.io 357m 35% 1389Mi 36%
|
||||||
|
```
|
||||||
|
|
||||||
|
Важной особенностью Metric Server является то, что он не хранит полученные данные, а только отображает последние полученные. По этому расценивать его как полноценную систему мониторинга нельзя.
|
||||||
|
|
||||||
|
**2. Запускаем тестовое приложение**
|
||||||
|
|
||||||
|
В качестве тестового приложения будет использоваться специальное приложение, предназначенное для тестирования HPA. Приложение написано на PHP, и при запросах генерирует высокую нагрузку. Для начала применим Deployment в кластер, выполнив команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f deploy/deployment.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Для работы HPA обязательным является наличие у Pod выставленных `request`. Обратите внимание на [deployment.yml](deploy/deployment.yml), в нем указано:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
```
|
||||||
|
|
||||||
|
Теперь создадим Service. Для этого мы не будем использовать готовые манифесты, а воспользуемся ключом `expose` для kubectl. Данный ключ позволяет создать Service для Deployment без написания манифеста. В итоге получается следующая команда, которую необходимо выполнить в консоли:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl expose deployment php-apache --port 80
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Устанавливаем HPA**
|
||||||
|
|
||||||
|
Для запуска HPA так же воспользуемся возможностями kubectl. Для создания абстракции HPA без манифеста можно использовать ключ `autoscale`. Выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=5
|
||||||
|
```
|
||||||
|
|
||||||
|
В результате выполнения команды будет создан HPA, который отслеживает состояние Deployment с именем `php-apache`. При достижении средней нагрузки на все Pod 50% (для расчетов суммируется процент нагрузки на каждый Pod и делится на их количество) scaling будет производиться в границах от 1-го Pod до 5 Pod.
|
||||||
|
|
||||||
|
**4. Проверяем работу**
|
||||||
|
|
||||||
|
* Смотрим на текущее количество Pod
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get pod
|
||||||
|
```
|
||||||
|
|
||||||
|
Должен быть запущен один Pod
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
php-apache-566d7644df-z9dtt 1/1 Running 0 15s
|
||||||
|
```
|
||||||
|
|
||||||
|
* Смотрим на HPA
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get hpa
|
||||||
|
```
|
||||||
|
|
||||||
|
Видим созданный HPA
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
|
||||||
|
php-apache Deployment/php-apache 1%/50% 1 5 1 32s
|
||||||
|
```
|
||||||
|
|
||||||
|
Она будет скейлить Pod, как только их использование cpu начнет составлять 50% от request.
|
||||||
|
|
||||||
|
* Создаем нагрузку
|
||||||
|
|
||||||
|
Для генерации нагрузки создадим еще один Pod из образа busybox. Внутри Pod в цикле будет запущена утилита wget, которая будет обращаться к тестовому приложению по имени Service. В итоге получается следующая команда, которую необходимо выполнить в консоли:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl run load-generator --image=busybox -- /bin/sh -c "while true; do wget -q -O- http://php-apache; done"
|
||||||
|
```
|
||||||
|
|
||||||
|
* Проверяем текущее потребление cpu Pod
|
||||||
|
|
||||||
|
Metric server может отдавать не только нагрузку по Node, но и по Pod. Для вывода информации по нагрузке от Pod выполните команду:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl top pod
|
||||||
|
```
|
||||||
|
|
||||||
|
Видим, что нагрузка начинает увеличиваться.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAME CPU(cores) MEMORY(bytes)
|
||||||
|
php-apache-566d7644df-z9dtt 936m 11Mi
|
||||||
|
```
|
||||||
|
|
||||||
|
* Ждем когда начнет работать Autoscaling
|
||||||
|
|
||||||
|
У kubectl есть ключ `-w`, который позволяет выводить в режиме реального времени все изменения для нашего текущего запроса. Выполним следующую команду в консоли, чтобы отслеживать изменения количества Pod:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get pod -w
|
||||||
|
```
|
||||||
|
|
||||||
|
Спустя несколько минут количество Pod должно увеличиться до 5-ти.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
load-generator-6b9cf94758-5qmbx 1/1 Running 0 2m16s
|
||||||
|
php-apache-566d7644df-4zvv7 1/1 Running 0 108s
|
||||||
|
php-apache-566d7644df-kv662 1/1 Running 0 93s
|
||||||
|
php-apache-566d7644df-tg8qw 1/1 Running 0 108s
|
||||||
|
php-apache-566d7644df-z9dtt 1/1 Running 0 13m
|
||||||
|
php-apache-566d7644df-zlwd7 1/1 Running 0 108s
|
||||||
|
```
|
||||||
|
|
||||||
|
Отлично, autoscaling сработал!
|
||||||
|
|
||||||
|
* Проверяем работу в обратную сторону
|
||||||
|
|
||||||
|
Удаляем Pod с тестовой нагрузкой выполнив команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete pod load-generator
|
||||||
|
```
|
||||||
|
|
||||||
|
* Проверяем нагрузку на поды
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl top pod
|
||||||
|
```
|
||||||
|
|
||||||
|
Через какое-то время замечаем, что она упала
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAME CPU(cores) MEMORY(bytes)
|
||||||
|
php-apache-566d7644df-4zvv7 1m 11Mi
|
||||||
|
php-apache-566d7644df-kv662 1m 11Mi
|
||||||
|
php-apache-566d7644df-tg8qw 1m 11Mi
|
||||||
|
php-apache-566d7644df-z9dtt 1m 11Mi
|
||||||
|
php-apache-566d7644df-zlwd7 1m 11Mi
|
||||||
|
```
|
||||||
|
|
||||||
|
* Проверяем, как autoscaling отработает в обратную сторону
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get pod -w
|
||||||
|
```
|
||||||
|
|
||||||
|
Видим, что ненужные поды умирают (в течение 5 минут). После снижения нагрузки scale down не происходит слишком быстро, чтобы избежать ситуации, когда значения по потреблению находятся в пограничном состоянии.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
php-apache-566d7644df-4zvv7 0/1 Terminating 0 8m59s
|
||||||
|
php-apache-566d7644df-kv662 0/1 Terminating 0 8m44s
|
||||||
|
php-apache-566d7644df-tg8qw 0/1 Terminating 0 8m59s
|
||||||
|
php-apache-566d7644df-z9dtt 1/1 Running 0 20m
|
||||||
|
php-apache-566d7644df-zlwd7 0/1 Terminating 0 8m59s
|
||||||
|
```
|
||||||
|
|
||||||
|
Autoscaling вернул все к первоначальному варианту с одним Pod.
|
||||||
|
|
||||||
|
**5. Чистим за собой кластер**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete all --all
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Troubleshooting
|
||||||
|
|
||||||
|
* Проверяем, что Metric server запущен
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get po -n kube-system | grep metrics-server
|
||||||
|
```
|
||||||
|
|
||||||
|
Поды должны быть в состоянии `STATUS: Running` и `READY 1/1`. Если Pod отсутствует, начинаем практику с первого пункта. Если состояние не `Running` или `0/1`, то смотрим причины, выполнив команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl describe po -n kube-system metrics-server-<TAB>
|
||||||
|
```
|
||||||
|
|
||||||
|
* Проверяем, что метрики доступны
|
||||||
|
|
||||||
|
Для проверки доступности метрик выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl top node
|
||||||
|
```
|
||||||
|
|
||||||
|
Если не выводится потребления по Node, но в прошлом шаге не выявлено ошибок, то пробуем установить еще раз все абстракции, выполнив команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f ~/slurm/practice/8.hpa/v1/metrics-server -n kube-system
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Полезные ссылки
|
||||||
|
|
||||||
|
1. [k8s doc: HPA v1](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/)
|
||||||
|
2. [Metric server](https://github.com/kubernetes-sigs/metrics-server)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: php-apache
|
||||||
|
name: php-apache
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: php-apache
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: php-apache
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: k8s.gcr.io/hpa-example
|
||||||
|
name: hpa-example
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
...
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
kind: ClusterRole
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: system:aggregated-metrics-reader
|
||||||
|
labels:
|
||||||
|
rbac.authorization.k8s.io/aggregate-to-view: "true"
|
||||||
|
rbac.authorization.k8s.io/aggregate-to-edit: "true"
|
||||||
|
rbac.authorization.k8s.io/aggregate-to-admin: "true"
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["metrics.k8s.io"]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: metrics-server:system:auth-delegator
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: system:auth-delegator
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: metrics-server
|
||||||
|
namespace: kube-system
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: metrics-server-auth-reader
|
||||||
|
namespace: kube-system
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: extension-apiserver-authentication-reader
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: metrics-server
|
||||||
|
namespace: kube-system
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiregistration.k8s.io/v1beta1
|
||||||
|
kind: APIService
|
||||||
|
metadata:
|
||||||
|
name: v1beta1.metrics.k8s.io
|
||||||
|
spec:
|
||||||
|
service:
|
||||||
|
name: metrics-server
|
||||||
|
namespace: kube-system
|
||||||
|
group: metrics.k8s.io
|
||||||
|
version: v1beta1
|
||||||
|
insecureSkipTLSVerify: true
|
||||||
|
groupPriorityMinimum: 100
|
||||||
|
versionPriority: 100
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: metrics-server
|
||||||
|
namespace: kube-system
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: metrics-server
|
||||||
|
namespace: kube-system
|
||||||
|
labels:
|
||||||
|
k8s-app: metrics-server
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
k8s-app: metrics-server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
name: metrics-server
|
||||||
|
labels:
|
||||||
|
k8s-app: metrics-server
|
||||||
|
spec:
|
||||||
|
serviceAccountName: metrics-server
|
||||||
|
volumes:
|
||||||
|
# mount in tmp so we can safely use from-scratch images and/or read-only containers
|
||||||
|
- name: tmp-dir
|
||||||
|
emptyDir: {}
|
||||||
|
containers:
|
||||||
|
- name: metrics-server
|
||||||
|
args:
|
||||||
|
- --kubelet-preferred-address-types=InternalIP
|
||||||
|
- --kubelet-insecure-tls=true
|
||||||
|
image: k8s.gcr.io/metrics-server-amd64:v0.3.3
|
||||||
|
imagePullPolicy: Always
|
||||||
|
volumeMounts:
|
||||||
|
- name: tmp-dir
|
||||||
|
mountPath: /tmp
|
||||||
|
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: metrics-server
|
||||||
|
namespace: kube-system
|
||||||
|
labels:
|
||||||
|
kubernetes.io/name: "Metrics-server"
|
||||||
|
kubernetes.io/cluster-service: "true"
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
k8s-app: metrics-server
|
||||||
|
ports:
|
||||||
|
- port: 443
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 443
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: system:metrics-server
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
- nodes
|
||||||
|
- nodes/stats
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: system:metrics-server
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: system:metrics-server
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: metrics-server
|
||||||
|
namespace: kube-system
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
### HPA v2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### С чем будем работать
|
||||||
|
|
||||||
|
* `Prometheus` устанавливается из Helm репозитория
|
||||||
|
* `Prometheus adapter` устанавливается из Helm репозитория
|
||||||
|
* `HPA v2` является стандартной абстракцией кластера Kubernetes
|
||||||
|
* Каталог `deploy` содержит необходимые для прохождения практики манифесты
|
||||||
|
* Бинарный файл `wrk` - утилита для генерации нагрузки на тестовое приложение
|
||||||
|
* В качестве тестового приложения будет выступать `nginx`
|
||||||
|
|
||||||
|
#### Где будем выполнять практику
|
||||||
|
|
||||||
|
* Данная практика выполняется на собственном кластере Kubernetes - Minikube и тд
|
||||||
|
|
||||||
|
#### Практика
|
||||||
|
|
||||||
|
**1. Подготовка кластера**
|
||||||
|
|
||||||
|
* Устанавливаем Helm репозиторий
|
||||||
|
|
||||||
|
Переходим к установке Prometheus. Сначала необходимо установить Helm репозиторий, в котором находится Prometheus Helm chart. Для этого выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add stable https://charts.helm.sh/stable
|
||||||
|
```
|
||||||
|
|
||||||
|
* Устанавливаем Prometheus
|
||||||
|
|
||||||
|
Для прохождения практики нам потребуется только сам Prometheus и kube-state-metrics экспортер. Все остальные компоненты лучше отключить, сделать это можно через `values.yml` или прямое переопределение переменных через ключ `--set`. В итоге получается следующая команда, которую необходимо выполнить в консоли:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm upgrade --install prometheus stable/prometheus --namespace monitoring --create-namespace --set alertmanager.enabled=false --set pushgateway.enabled=false --set nodeExporter.enabled=false --set server.persistentVolume.enabled=false
|
||||||
|
```
|
||||||
|
|
||||||
|
* Ставим Prometheus adapter
|
||||||
|
|
||||||
|
Устанавливаем Prometheus adapter, который необходим для доступа к метрикам Prometheus через kube-api (HPA умеет получать метрики только из kube-api). Он также устанавливается с помощью Helm chart. Через ключ `--set` указываем, по какому адресу и порту доступен Prometheus. Так как они находятся в одном namespace, можно указать просто имя сервиса. В итоге получается следующая команда, которую необходимо выполнить в консоли:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm upgrade --install prometheus-adapter stable/prometheus-adapter --namespace monitoring --set prometheus.url=http://prometheus-server --set prometheus.port=80
|
||||||
|
```
|
||||||
|
|
||||||
|
* Проверяем, что всё заработало
|
||||||
|
|
||||||
|
Проверяем, что все поды запустились. Для этого выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get po -n monitoring
|
||||||
|
```
|
||||||
|
|
||||||
|
Эта команда выведет данные обо всех Pod в namespace monitoring. Все Pod должны быть в состояние `STATUS: Running` и `READY 1/1` или `READY 2/2` в зависимости от количества контейнеров в Pod. Если какие-то Pod не в этом состояние, стоит повторить команду через 1-2 минуты.
|
||||||
|
|
||||||
|
Теперь проверяем, что метрики Prometheus доступны через kube-api. Для этого можно послать прямой запрос к kube-api. C использованием утилиты `kubectl` и указав ключ `--raw` можно выполнить запрос к любому kube-api endpoint. Получим список доступных метрик, выполнив следующую команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1
|
||||||
|
```
|
||||||
|
|
||||||
|
На экран будет выведен список всех доступных метрик. Список должен быть длинным.
|
||||||
|
|
||||||
|
Теперь проверим, что Prometheus адаптер зарегистрировался в kube-api. Для этого выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io
|
||||||
|
```
|
||||||
|
|
||||||
|
Результат должен быть следующим:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAME SERVICE AVAILABLE AGE
|
||||||
|
v1beta1.custom.metrics.k8s.io monitoring/prometheus-adapter True 1m
|
||||||
|
```
|
||||||
|
|
||||||
|
Данный результат говорит, что при обращении к kube-api на endpoint `v1beta1.custom.metrics.k8s.io` запросы будут перенаправлены в Service с именем `prometheus-adapter` в namespace `monitoring`. Данный Service доставляет запросы в Pod с prometheus-adapter, который в свою очередь, преобразует метрики из вида Prometheus к виду kube-api.
|
||||||
|
|
||||||
|
**2. Запускаем тестовое приложение**
|
||||||
|
|
||||||
|
В качестве тестового приложения будет выступать Nginx, у которого мы будем запрашивать default page. Доступ к Pod будет открыт через Ingress. Для реализации данной схемы необходимо создать: Pod, Service и Ingress.
|
||||||
|
|
||||||
|
* Создаем Deployment и Service
|
||||||
|
|
||||||
|
Для начала применим Deployment в кластер, выполнив команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f deploy/deployment.yml -n default
|
||||||
|
```
|
||||||
|
|
||||||
|
Теперь создадим Service, для этого мы не будем использовать готовые манифесты, а воспользуемся ключом `expose` для kubectl. Данный ключ позволяет создать Service для Deployment без написания манифеста. В итоге получается следующая команда, которую необходимо выполнить в консоли:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl expose deployment hpa-v2-test --port 80 -n default
|
||||||
|
```
|
||||||
|
|
||||||
|
В результате выполнения данной команды будет создан Deployment и запущен Pod c Nginx версии 1.13. А так же будет создан Service, через который будет доступен данный Pod.
|
||||||
|
|
||||||
|
* Создаем Ingress
|
||||||
|
|
||||||
|
Зададим имя, по которому будет принимать запросы Ingress, для этого в файле `deploy/ingress.yml` необходимо заменить <Ваш номер студента> на номер своего студента. И применим данный манифест в кластер Kubernetes, выполнив команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f deploy/ingress.yml -n default
|
||||||
|
```
|
||||||
|
|
||||||
|
* Проверяем результат
|
||||||
|
|
||||||
|
Для проверки, что все настроено верно, выполним запрос на `hpa-v2-test.<External Ingress IP>.nip.io`. Например, выполнив команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -I hpa-v2-test.<External Ingress IP>.nip.io
|
||||||
|
```
|
||||||
|
|
||||||
|
Ответ должен быть примерно таким:
|
||||||
|
```bash
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Tue, 19 May 2020 19:57:28 GMT
|
||||||
|
Content-Type: text/html
|
||||||
|
Content-Length: 612
|
||||||
|
Connection: keep-alive
|
||||||
|
Vary: Accept-Encoding
|
||||||
|
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
|
||||||
|
ETag: "5acb8e45-264"
|
||||||
|
Accept-Ranges: bytes
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Настройка правил Prometheus**
|
||||||
|
|
||||||
|
* Для начала попросим прометеус собирать метрики с ингресс контроллеров. Для этого
|
||||||
|
отредактируем деплоймент ингресса
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl edit deployment -n ingress-nginx ingress-nginx-controller
|
||||||
|
```
|
||||||
|
|
||||||
|
В него нужно добавить на уровне темплейта пода две аннотации:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 25%
|
||||||
|
maxUnavailable: 25%
|
||||||
|
type: RollingUpdate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations: # <--- вот отсюда
|
||||||
|
prometheus.io/port: "10254"
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
```
|
||||||
|
|
||||||
|
Для того чтобы поды смогли пересоздаться, придется вручную заскейлить
|
||||||
|
деплоймент до одной реплики
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl scale deployment -n ingress-nginx --replicas=1 ingress-nginx-controller
|
||||||
|
```
|
||||||
|
|
||||||
|
Дождаться когда одна реплика обновится и после этого заскейлить обратно до двух реплик.
|
||||||
|
|
||||||
|
* Обновляем настройки Prometheus
|
||||||
|
|
||||||
|
Ingress-controller отдает в Prometheus метрику с общим количеством запросов, а не за промежуток времени. В то же время HPA не умеет работать с функциями для обработки метрик Prometheus, поэтому нам необходимо дописать в Prometheus `recording rule` для получения нужной нам метрики.
|
||||||
|
|
||||||
|
Для этого получаем текущие значения Helm values для запущенного у нас Prometheus
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm get values --all prometheus -n monitoring > values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Далее находим в файле `rules: {}` и заменяем на правило:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
rules:
|
||||||
|
groups:
|
||||||
|
- name: Ingress
|
||||||
|
rules:
|
||||||
|
- record: nginx_ingress_controller_requests_per_second
|
||||||
|
expr: rate(nginx_ingress_controller_requests[5m])
|
||||||
|
```
|
||||||
|
|
||||||
|
Не забудьте убрать пустой словарь `(скобки {})` после rules.
|
||||||
|
|
||||||
|
Применяем изменения, для этого выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm upgrade --install prometheus stable/prometheus --namespace monitoring -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
После применения изменений в Prometheus появится новая метрика с именем `nginx_ingress_controller_requests_per_second`.
|
||||||
|
|
||||||
|
Проверяем, что метрика `nginx_ingress_controller_requests_per_second` доступна через kube-api.
|
||||||
|
|
||||||
|
Prometheus `начинает считать` данную метрику только после прохождения трафика через Ingress. Поэтому выполним несколько тестовых запросов, повторив 2-3 раза команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -I hpa-v2-test.<External Ingress IP>.nip.io
|
||||||
|
```
|
||||||
|
|
||||||
|
Теперь проверим доступность метрики `nginx_ingress_controller_requests_per_second` через kube-api. Для этого выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | grep nginx_ingress_controller_requests_per_second
|
||||||
|
```
|
||||||
|
|
||||||
|
В результате выполнения этой команды на экран будет выведено: `nginx_ingress_controller_requests_per_second`.
|
||||||
|
|
||||||
|
**3. Создаем HPA**
|
||||||
|
|
||||||
|
Осталось добавить в кластер объект типа HPA. Важной особенностью HPA является то, что он не является cluster-wide, проще говоря он может взаимодействовать с Deployment только в том же namespace. Манифест для HPA уже подготовлен, и теперь его необходимо применить в кластер. Для этого выполните команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f deploy/hpa-v2.yml -n default
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверяем, что манифест применился, для этого выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get hpa -n default
|
||||||
|
```
|
||||||
|
|
||||||
|
В результате выполнения этой команды на экран будет выведен список всех объектов типа HPA. В списке должен присутствовать HPA с именем: `hpa-v2-test`.
|
||||||
|
|
||||||
|
**4. Тестирование работы HPA**
|
||||||
|
|
||||||
|
* Создаем тестовую нагрузку
|
||||||
|
|
||||||
|
Для создания тестовой нагрузки будем использовать утилиту wrk из текущего каталога. Для запуска выполним команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./wrk -c 5 -t 2 -d 15m --latency http://hpa-v2-test.<External Ingress IP>.nip.io
|
||||||
|
```
|
||||||
|
|
||||||
|
* Проверка результата
|
||||||
|
|
||||||
|
Через 5-10 минут (в другой консоли) проверьте, что HPA успешно отработал и Pod стало больше. Для этого выполните команду:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get po -n default
|
||||||
|
```
|
||||||
|
|
||||||
|
Количество Pod `hpa-v2-test-XXX` должно было увеличиться.
|
||||||
|
|
||||||
|
* Отключаем тестовую нагрузку
|
||||||
|
|
||||||
|
Для отключения тестовой нагрузки в консоли, где запущен wrk, выполните: `CTRL + C`.
|
||||||
|
|
||||||
|
Обратите внимание, что количество Pod уменьшится не сразу после прекращения нагрузки. Это связано с тем, что HPA производит scale down не сразу, что бы избежать ситуации, когда нагрузка находится у пороговых значений. Количество Pod будет уменьшено в течение нескольких минут.
|
||||||
|
|
||||||
|
**5. Чистим за собой кластер**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete all --all -n default
|
||||||
|
kubectl delete apiservice v1beta1.custom.metrics.k8s.io
|
||||||
|
kubectl delete ns monitoring
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Troubleshooting
|
||||||
|
|
||||||
|
* Проверяем, что Prometheus запущен
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get po -n monitoring
|
||||||
|
```
|
||||||
|
|
||||||
|
Эта команда выведет данные о всех Pod в namespace monitoring. Все Pod должны быть в состоянии `STATUS: Running` и `READY 1/1` или `READY 2/2` в зависимости от количества контейнеров в Pod. Если какие-то Pod не в этом состоянии, стоит повторить команду через 1-2 минуты. Если что-то не работает, надо смотреть причину: `kubectl describe po -n monitoring <Pod name>`. Часто причина заключается в нехватке ресурсов, в этом случае необходимо удалить абстракции прошлых практик.
|
||||||
|
|
||||||
|
* Проверяем, что метрики доступны
|
||||||
|
|
||||||
|
!Перед проверкой доступности метрики необходимо выполнить несколько запросов к приложению.!
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | grep nginx_ingress_controller_requests_per_second
|
||||||
|
```
|
||||||
|
|
||||||
|
В результате выполнения этой команды на экран будет выведено: `nginx_ingress_controller_requests_per_second`.
|
||||||
|
|
||||||
|
Если метрики недоступны, проверяем наличие и корректность добавления правил в Prometheus. Пункт 3.
|
||||||
|
|
||||||
|
#### Полезные ссылки
|
||||||
|
|
||||||
|
1. [k8s doc: HPA](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics)
|
||||||
|
2. [github: HPA](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/autoscaling/hpa-v2.md)
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: hpa-v2-test
|
||||||
|
name: hpa-v2-test
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: hpa-v2-test
|
||||||
|
strategy: {}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
app: hpa-v2-test
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.13
|
||||||
|
name: nginx
|
||||||
|
resources: {}
|
||||||
|
status: {}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
apiVersion: autoscaling/v2beta2
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: hpa-v2-test
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: hpa-v2-test
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 10
|
||||||
|
metrics:
|
||||||
|
- type: Object
|
||||||
|
object:
|
||||||
|
metric:
|
||||||
|
name: nginx_ingress_controller_requests_per_second
|
||||||
|
describedObject:
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
name: hpa-v2-test
|
||||||
|
target:
|
||||||
|
type: AverageValue
|
||||||
|
averageValue: 10
|
||||||
|
...
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: hpa-v2-test
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: hpa-v2-test.<External Ingress IP>.nip.io
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: /
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: hpa-v2-test
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
...
|
||||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,5 @@
|
|||||||
|
#### Список практических работ
|
||||||
|
|
||||||
|
[1. HPA v1](01.hpa_v1/README.md)
|
||||||
|
|
||||||
|
[2. HPA v2](02.hpa_v2/README.md)
|
||||||
Reference in New Issue
Block a user