Перейти к основному содержимому
Версия: 2.0.x

Selena с Helm

Цели​

Цели данного краткого руководства:

  • Развернуть Selena Kubernetes Operator и cluster Selena с помощью Helm
  • Настроить пароль для пользователя базы данных Selena root
  • Обеспечить высокую доступность с тремя FE и тремя BE
  • Хранить метаданные в постоянном хранилище
  • Хранить данные в постоянном хранилище
  • Разрешить подключение MySQL-клиентов извне cluster Kubernetes
  • Разрешить загрузку данных извне cluster Kubernetes с использованием Stream Load
  • Загрузить некоторые публичные наборы данных
  • Выполнить запросы к данным
подсказка

Наборы данных и запросы такие же, как в базовом кратком руководстве. Основное отличие здесь — развертывание с помощью Helm и Selena Operator.

Используемые данные предоставлены NYC OpenData и Национальными центрами экологической информации.

Оба набора данных большие, и поскольку это руководство предназначено для ознакомления с работой Selena, мы не будем загружать данные за последние 120 лет. Вы можете запустить это на GKE Kubernetes cluster, построенном на трех машинах e2-standard-4 (или аналогичных) с диском 80 ГБ. Для более крупных развертываний у нас есть другая документация, которую мы предоставим позже.

В этом документе много информации, и она представлена с пошаговым содержимым в начале и техническими деталями в конце. Это сделано для достижения следующих целей в указанном порядке:

  1. Развернуть систему с помощью Helm.
  2. Позволить читателю загрузить данные в Selena и проанализировать их.
  3. Объяснить основы преобразования данных во время загрузки.

Предварительные требования​

Среда Kubernetes​

Среда Kubernetes, использованная при написании этого руководства, состоит из трёх узлов с четырьмя vCPU и 16 ГБ оперативной памяти каждый (машины GCP e2-standard-4). Cluster Kubernetes был развёрнут с помощью следующей команды gcloud:

подсказка

Эта команда приведена для справки. Если вы используете AWS, Azure или любого другого провайдера Kubernetes, вам нужно будет адаптировать её для вашей среды. В Google Cloud вам нужно будет указать свой проект и соответствующее расположение.

gcloud container --project enterprise-demo-422514 \
clusters create ee-docs \
--location=southamerica-west1-b \
--machine-type e2-standard-4 --disk-size 80 --num-nodes 3

Helm​

Helm — это менеджер пакетов для Kubernetes, который упрощает развёртывание и управление приложениями. В этой лабораторной работе вы будете использовать Helm для развёртывания оператора Kubernetes CelerData Enterprise Edition и примера cluster Selena.

Установить helm

SQL-клиент​

Вы можете использовать SQL-клиент, предоставленный в среде Kubernetes, или использовать клиент на вашей системе. В этом руководстве используется mysql CLI. Многие MySQL-совместимые клиенты будут работать.

curl​

curl используется для отправки задания загрузки данных в Selena и для скачивания наборов данных. Проверьте, установлен ли он, запустив curl или curl.exe в командной строке вашей ОС. Если curl не установлен, скачайте curl здесь.


Терминология​

FE​

Узлы Frontend отвечают за управление метаданными, управление клиентскими подключениями, планирование и составление расписания запросов. Каждый FE хранит и поддерживает полную копию метаданных в своей памяти, что гарантирует одинаковое обслуживание всеми FE.

BE​

Узлы Backend отвечают как за хранение данных, так и за выполнение планов запросов.


Добавление репозитория Helm chart Selena​

Helm Chart содержит определения Selena Operator и пользовательского ресурса SelenaCluster.

  1. Добавьте репозиторий Helm Chart.

    helm repo add selena https://selena.github.io/selena-kubernetes-operator
  2. Обновите репозиторий Helm Chart до последней версии.

    helm repo update
  3. Просмотрите добавленный репозиторий Helm Chart.

    helm search repo selena
    NAME                              	CHART VERSION	APP VERSION	DESCRIPTION
    selena/kube-selena 1.9.7 3.2-latest kube-selena includes two subcharts, operator...
    selena/operator 1.9.7 1.9.7 A Helm chart for Selena operator
    selena/selena 1.9.7 3.2-latest A Helm chart for Selena cluster
    selena/warehouse 1.9.7 3.2-latest Warehouse is currently a feature of the StarRoc...

Скачивание данных​

Скачайте эти два набора данных на ваш компьютер.

Данные о ДТП в Нью-Йорке​

curl -O https://raw.githubusercontent.com/Selena/demo/master/documentation-samples/quickstart/datasets/NYPD_Crash_Data.csv

Данные о погоде​

curl -O https://raw.githubusercontent.com/Selena/demo/master/documentation-samples/quickstart/datasets/72505394728.csv

Создание файла значений Helm​

Цели для этого краткого руководства:

  1. Настроить пароль для пользователя базы данных Selena root
  2. Обеспечить высокую доступность с тремя FE и тремя BE
  3. Хранить метаданные в постоянном хранилище
  4. Хранить данные в постоянном хранилище
  5. Разрешить подключение MySQL-клиентов извне cluster Kubernetes
  6. Разрешить загрузку данных извне cluster Kubernetes с использованием Stream Load

Helm chart предоставляет опции для достижения всех этих целей, но они не настроены по умолчанию. В остальной части этого раздела рассматривается конфигурация, необходимая для достижения всех этих целей. Будет предоставлена полная спецификация значений, но сначала прочитайте детали для каждого из шести разделов, а затем скопируйте полную спецификацию.

1. Пароль для пользователя базы данных​

Этот фрагмент YAML инструктирует Selena operator установить пароль для пользователя базы данных root в значение ключа password секрета Kubernetes selena-root-pass.

selena:
initPassword:
enabled: true
# Set a password secret, for example:
# kubectl create secret generic selena-root-pass --from-literal=password='g()()dpa$$word'
passwordSecret: selena-root-pass
  • Задача: Создать секрет Kubernetes

    kubectl create secret generic selena-root-pass --from-literal=password='g()()dpa$$word'

2. Высокая доступность с 3 FE и 3 BE​

Установив selena.selenaFESpec.replicas в 3 и selena.selenaBeSpec.replicas в 3, вы получите достаточное количество FE и BE для высокой доступности. Установка низких запросов на CPU и память позволяет создавать поды в небольшой среде Kubernetes.

selena:
selenaFESpec:
replicas: 3
resources:
requests:
cpu: 1
memory: 1Gi

selenaBeSpec:
replicas: 3
resources:
requests:
cpu: 1
memory: 2Gi

3. Хранение метаданных в постоянном хранилище​

Установка значения для selena.selenaFESpec.storageSpec.name в любое значение, кроме "", приводит к:

  • Использованию постоянного хранилища
  • Использованию значения selena.selenaFESpec.storageSpec.name в качестве префикса для всех томов хранилища для сервиса.

При установке значения fe будут созданы следующие PV для FE 0:

  • fe-meta-kube-selena-fe-0
  • fe-log-kube-selena-fe-0
selena:
selenaFESpec:
storageSpec:
name: fe

4. Хранение данных в постоянном хранилище​

Установка значения для selena.selenaBeSpec.storageSpec.name в любое значение, кроме "", приводит к:

  • Использованию постоянного хранилища
  • Использованию значения selena.selenaBeSpec.storageSpec.name в качестве префикса для всех томов хранилища для сервиса.

При установке значения be будут созданы следующие PV для BE 0:

  • be-data-kube-selena-be-0
  • be-log-kube-selena-be-0

Установка storageSize в 15Gi уменьшает хранилище с 1Ti по умолчанию для соответствия меньшим квотам хранилища.

selena:
selenaBeSpec:
storageSpec:
name: be
storageSize: 15Gi

5. LoadBalancer для MySQL-клиентов​

По умолчанию доступ к сервису FE осуществляется через IP-адреса cluster. Для разрешения внешнего доступа service.type устанавливается в LoadBalancer

selena:
selenaFESpec:
service:
type: LoadBalancer

6. LoadBalancer для внешней загрузки данных​

Stream Load требует внешнего доступа как к FE, так и к BE. Запросы отправляются на FE, а затем FE назначает BE для обработки загрузки. Чтобы позволить команде curl перенаправляться на BE, необходимо включить starroclFeProxySpec и установить тип LoadBalancer.

selena:
selenaFeProxySpec:
enabled: true
service:
type: LoadBalancer

Полный файл значений​

Приведенные выше фрагменты, объединенные вместе, образуют полный файл значений. Сохраните его в my-values.yaml:

selena:
initPassword:
enabled: true
# Set a password secret, for example:
# kubectl create secret generic selena-root-pass --from-literal=password='g()()dpa$$word'
passwordSecret: selena-root-pass

selenaFESpec:
replicas: 3
service:
type: LoadBalancer
resources:
requests:
cpu: 1
memory: 1Gi
storageSpec:
name: fe

selenaBeSpec:
replicas: 3
resources:
requests:
cpu: 1
memory: 2Gi
storageSpec:
name: be
storageSize: 15Gi

selenaFeProxySpec:
enabled: true
service:
type: LoadBalancer

Установка пароля пользователя root базы данных Selena​

Для загрузки данных извне cluster Kubernetes база данных Selena будет доступна извне. Вам следует установить пароль для пользователя базы данных Selena root. Оператор применит пароль к узлам FE и BE.

kubectl create secret generic selena-root-pass --from-literal=password='g()()dpa$$word'
secret/selena-root-pass created

Развертывание оператора и cluster Selena​

helm install -f my-values.yaml selena selena/kube-selena
NAME: selena
LAST DEPLOYED: Wed Jun 26 20:25:09 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing kube-selena-1.9.7 kube-selena chart.
It will install both operator and selena cluster, please wait for a few minutes for the cluster to be ready.

Please see the values.yaml for more operation information: https://github.com/Selena/selena-kubernetes-operator/blob/main/helm-charts/charts/kube-selena/values.yaml

Проверка статуса cluster Selena​

Вы можете проверить прогресс с помощью этих команд:

kubectl --namespace default get selenacluster -l "cluster=kube-selena"
NAME             PHASE         FESTATUS      BESTATUS      CNSTATUS   FEPROXYSTATUS
kube-selena reconciling reconciling reconciling reconciling
kubectl get pods
примечание

Под kube-selena-initpwd будет проходить через состояния error и CrashLoopBackOff, пытаясь подключиться к подам FE и BE для установки пароля root Selena. Вы должны игнорировать эти ошибки и дождаться статуса Completed для этого пода.

NAME                                       READY   STATUS             RESTARTS      AGE
kube-selena-be-0 0/1 Running 0 20s
kube-selena-be-1 0/1 Running 0 20s
kube-selena-be-2 0/1 Running 0 20s
kube-selena-fe-0 1/1 Running 0 66s
kube-selena-fe-1 0/1 Running 0 65s
kube-selena-fe-2 0/1 Running 0 66s
kube-selena-fe-proxy-56f8998799-d4qmt 1/1 Running 0 20s
kube-selena-initpwd-m84br 0/1 CrashLoopBackOff 3 (50s ago) 92s
kube-selena-operator-54ffcf8c5c-xsjc8 1/1 Running 0 92s
kubectl get pvc
NAME                          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
be-data-kube-selena-be-0 Bound pvc-4ae0c9d8-7f9a-4147-ad74-b22569165448 15Gi RWO standard-rwo <unset> 82s
be-data-kube-selena-be-1 Bound pvc-28b4dbd1-0c8f-4b06-87e8-edec616cabbc 15Gi RWO standard-rwo <unset> 82s
be-data-kube-selena-be-2 Bound pvc-c7232ea6-d3d9-42f1-bfc1-024205a17656 15Gi RWO standard-rwo <unset> 82s
be-log-kube-selena-be-0 Bound pvc-6193c43d-c74f-4d12-afcc-c41ace3d5408 1Gi RWO standard-rwo <unset> 82s
be-log-kube-selena-be-1 Bound pvc-c01f124a-014a-439a-99a6-6afe95215bf0 1Gi RWO standard-rwo <unset> 82s
be-log-kube-selena-be-2 Bound pvc-136df15f-4d2e-43bc-a1c0-17227ce3fe6b 1Gi RWO standard-rwo <unset> 82s
fe-log-kube-selena-fe-0 Bound pvc-7eac524e-d286-4760-b21c-d9b6261d976f 5Gi RWO standard-rwo <unset> 2m23s
fe-log-kube-selena-fe-1 Bound pvc-38076b78-71e8-4659-b8e7-6751bec663f6 5Gi RWO standard-rwo <unset> 2m23s
fe-log-kube-selena-fe-2 Bound pvc-4ccfee60-02b7-40ba-a22e-861ea29dac74 5Gi RWO standard-rwo <unset> 2m23s
fe-meta-kube-selena-fe-0 Bound pvc-5130c9ff-b797-4f79-a1d2-4214af860d70 10Gi RWO standard-rwo <unset> 2m23s
fe-meta-kube-selena-fe-1 Bound pvc-13545330-63be-42cf-b1ca-3ed6f96a8c98 10Gi RWO standard-rwo <unset> 2m23s
fe-meta-kube-selena-fe-2 Bound pvc-609cadd4-c7b7-4cf9-84b0-a75678bb3c4d 10Gi RWO standard-rwo <unset> 2m23s

Проверка работоспособности cluster​

подсказка

Это те же команды, что и выше, но показывают желаемое состояние.

kubectl --namespace default get selenacluster -l "cluster=kube-selena"
NAME             PHASE     FESTATUS   BESTATUS   CNSTATUS   FEPROXYSTATUS
kube-selena running running running running
kubectl get pods
подсказка

Система готова, когда все поды, кроме kube-selena-initpwd, показывают 1/1 в столбце READY. Под kube-selena-initpwd должен показывать 0/1 и STATUS Completed.

NAME                                       READY   STATUS      RESTARTS   AGE
kube-selena-be-0 1/1 Running 0 57s
kube-selena-be-1 1/1 Running 0 57s
kube-selena-be-2 1/1 Running 0 57s
kube-selena-fe-0 1/1 Running 0 103s
kube-selena-fe-1 1/1 Running 0 102s
kube-selena-fe-2 1/1 Running 0 103s
kube-selena-fe-proxy-56f8998799-d4qmt 1/1 Running 0 57s
kube-selena-initpwd-m84br 0/1 Completed 4 2m9s
kube-selena-operator-54ffcf8c5c-xsjc8 1/1 Running 0 2m9s

Адреса EXTERNAL-IP в выделенных строках будут использоваться для обеспечения доступа SQL-клиента и Stream Load извне cluster Kubernetes.

kubectl get services
NAME                              TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                                       AGE
kube-selena-be-search ClusterIP None <none> 9050/TCP 78s
kube-selena-be-service ClusterIP 34.118.228.231 <none> 9060/TCP,8040/TCP,9050/TCP,8060/TCP 78s
kube-selena-fe-proxy-service LoadBalancer 34.118.230.176 34.176.12.205 8080:30241/TCP 78s
kube-selena-fe-search ClusterIP None <none> 9030/TCP 2m4s
kube-selena-fe-service LoadBalancer 34.118.226.82 34.176.215.97 8030:30620/TCP,9020:32461/TCP,9030:32749/TCP,9010:30911/TCP 2m4s
kubernetes ClusterIP 34.118.224.1 <none> 443/TCP 8h
подсказка

Сохраните адреса EXTERNAL-IP из выделенных строк в переменных окружения, чтобы они были под рукой:

export MYSQL_IP=`kubectl get services kube-selena-fe-service --output jsonpath='{.status.loadBalancer.ingress[0].ip}'`
export FE_PROXY=`kubectl get services kube-selena-fe-proxy-service --output jsonpath='{.status.loadBalancer.ingress[0].ip}'`:8080

Подключение к Selena с помощью SQL-клиента​

подсказка

Если вы используете клиент, отличный от mysql CLI, откройте его сейчас.

Эта команда запустит команду mysql в поде Kubernetes:

kubectl exec --stdin --tty kube-selena-fe-0 -- \
mysql -P9030 -h127.0.0.1 -u root --prompt="Selena > "

Если у вас установлен mysql CLI локально, вы можете использовать его вместо того, что в cluster Kubernetes:

mysql -P9030 -h $MYSQL_IP -u root --prompt="Selena > " -p

Создание таблиц​

mysql -P9030 -h $MYSQL_IP -u root --prompt="Selena > " -p

Создание базы данных​

Введите эти две строки в приглашении Selena > и нажмите Enter после каждой:

CREATE DATABASE IF NOT EXISTS quickstart;

USE quickstart;

Создание двух таблиц​

Crashdata​

Набор данных об авариях содержит гораздо больше полей, чем представлено здесь; схема была сокращена, чтобы включить только поля, которые могут быть полезны для ответа на вопросы о влиянии погоды на условия вождения.

CREATE TABLE IF NOT EXISTS crashdata (
CRASH_DATE DATETIME,
BOROUGH STRING,
ZIP_CODE STRING,
LATITUDE INT,
LONGITUDE INT,
LOCATION STRING,
ON_STREET_NAME STRING,
CROSS_STREET_NAME STRING,
OFF_STREET_NAME STRING,
CONTRIBUTING_FACTOR_VEHICLE_1 STRING,
CONTRIBUTING_FACTOR_VEHICLE_2 STRING,
COLLISION_ID INT,
VEHICLE_TYPE_CODE_1 STRING,
VEHICLE_TYPE_CODE_2 STRING
);

Weatherdata​

Аналогично данным об авариях, набор данных о погоде содержит гораздо больше столбцов (всего 125 столбцов), и в базу данных включены только те, которые могут помочь ответить на вопросы.

CREATE TABLE IF NOT EXISTS weatherdata (
DATE DATETIME,
NAME STRING,
HourlyDewPointTemperature STRING,
HourlyDryBulbTemperature STRING,
HourlyPrecipitation STRING,
HourlyPresentWeatherType STRING,
HourlyPressureChange STRING,
HourlyPressureTendency STRING,
HourlyRelativeHumidity STRING,
HourlySkyConditions STRING,
HourlyVisibility STRING,
HourlyWetBulbTemperature STRING,
HourlyWindDirection STRING,
HourlyWindGustSpeed STRING,
HourlyWindSpeed STRING
);

Выйдите из клиента MySQL или откройте новую оболочку для выполнения команд в командной строке для загрузки данных.

exit

Загрузка данных​

Существует много способов загрузки данных в Selena. Для этого руководства самый простой способ — использовать curl и Selena Stream Load.

Загрузите два набора данных, которые вы скачали ранее.

подсказка

Откройте новую оболочку, так как эти команды curl выполняются в командной строке операционной системы, а не в клиенте mysql. Команды ссылаются на скачанные наборы данных, поэтому запускайте их из директории, где вы скачали файлы.

Поскольку это новая оболочка, снова выполните команды export:


export MYSQL_IP=`kubectl get services kube-selena-fe-service --output jsonpath='{.status.loadBalancer.ingress[0].ip}'`

export FE_PROXY=`kubectl get services kube-selena-fe-proxy-service --output jsonpath='{.status.loadBalancer.ingress[0].ip}'`:8080

Вам будет предложено ввести пароль. Используйте пароль, который вы добавили в секрет Kubernetes selena-root-pass. Если вы использовали предоставленную команду, пароль — g()()dpa$$word.

Команды curl выглядят сложно, но они подробно объясняются в конце руководства. На данный момент мы рекомендуем выполнить команды и выполнить несколько SQL-запросов для анализа данных, а затем прочитать о деталях загрузки данных в конце.

curl --location-trusted -u root             \
-T ./NYPD_Crash_Data.csv \
-H "label:crashdata-0" \
-H "column_separator:," \
-H "skip_header:1" \
-H "enclose:\"" \
-H "max_filter_ratio:1" \
-H "columns:tmp_CRASH_DATE, tmp_CRASH_TIME, CRASH_DATE=str_to_date(concat_ws(' ', tmp_CRASH_DATE, tmp_CRASH_TIME), '%m/%d/%Y %H:%i'),BOROUGH,ZIP_CODE,LATITUDE,LONGITUDE,LOCATION,ON_STREET_NAME,CROSS_STREET_NAME,OFF_STREET_NAME,NUMBER_OF_PERSONS_INJURED,NUMBER_OF_PERSONS_KILLED,NUMBER_OF_PEDESTRIANS_INJURED,NUMBER_OF_PEDESTRIANS_KILLED,NUMBER_OF_CYCLIST_INJURED,NUMBER_OF_CYCLIST_KILLED,NUMBER_OF_MOTORIST_INJURED,NUMBER_OF_MOTORIST_KILLED,CONTRIBUTING_FACTOR_VEHICLE_1,CONTRIBUTING_FACTOR_VEHICLE_2,CONTRIBUTING_FACTOR_VEHICLE_3,CONTRIBUTING_FACTOR_VEHICLE_4,CONTRIBUTING_FACTOR_VEHICLE_5,COLLISION_ID,VEHICLE_TYPE_CODE_1,VEHICLE_TYPE_CODE_2,VEHICLE_TYPE_CODE_3,VEHICLE_TYPE_CODE_4,VEHICLE_TYPE_CODE_5" \
-XPUT http://$FE_PROXY/api/quickstart/crashdata/_stream_load
Enter host password for user 'root':
{
"TxnId": 2,
"Label": "crashdata-0",
"Status": "Success",
"Message": "OK",
"NumberTotalRows": 423726,
"NumberLoadedRows": 423725,
"NumberFilteredRows": 1,
"NumberUnselectedRows": 0,
"LoadBytes": 96227746,
"LoadTimeMs": 2483,
"BeginTxnTimeMs": 42,
"StreamLoadPlanTimeMs": 122,
"ReadDataTimeMs": 1610,
"WriteDataTimeMs": 2253,
"CommitAndPublishTimeMs": 65,
"ErrorURL": "http://kube-selena-be-2.kube-selena-be-search.default.svc.cluster.local:8040/api/_load_error_log?file=error_log_5149e6f80de42bcb_eab2ea77276de4ba"
}
curl --location-trusted -u root             \
-T ./72505394728.csv \
-H "label:weather-0" \
-H "column_separator:," \
-H "skip_header:1" \
-H "enclose:\"" \
-H "max_filter_ratio:1" \
-H "columns: STATION, DATE, LATITUDE, LONGITUDE, ELEVATION, NAME, REPORT_TYPE, SOURCE, HourlyAltimeterSetting, HourlyDewPointTemperature, HourlyDryBulbTemperature, HourlyPrecipitation, HourlyPresentWeatherType, HourlyPressureChange, HourlyPressureTendency, HourlyRelativeHumidity, HourlySkyConditions, HourlySeaLevelPressure, HourlyStationPressure, HourlyVisibility, HourlyWetBulbTemperature, HourlyWindDirection, HourlyWindGustSpeed, HourlyWindSpeed, Sunrise, Sunset, DailyAverageDewPointTemperature, DailyAverageDryBulbTemperature, DailyAverageRelativeHumidity, DailyAverageSeaLevelPressure, DailyAverageStationPressure, DailyAverageWetBulbTemperature, DailyAverageWindSpeed, DailyCoolingDegreeDays, DailyDepartureFromNormalAverageTemperature, DailyHeatingDegreeDays, DailyMaximumDryBulbTemperature, DailyMinimumDryBulbTemperature, DailyPeakWindDirection, DailyPeakWindSpeed, DailyPrecipitation, DailySnowDepth, DailySnowfall, DailySustainedWindDirection, DailySustainedWindSpeed, DailyWeather, MonthlyAverageRH, MonthlyDaysWithGT001Precip, MonthlyDaysWithGT010Precip, MonthlyDaysWithGT32Temp, MonthlyDaysWithGT90Temp, MonthlyDaysWithLT0Temp, MonthlyDaysWithLT32Temp, MonthlyDepartureFromNormalAverageTemperature, MonthlyDepartureFromNormalCoolingDegreeDays, MonthlyDepartureFromNormalHeatingDegreeDays, MonthlyDepartureFromNormalMaximumTemperature, MonthlyDepartureFromNormalMinimumTemperature, MonthlyDepartureFromNormalPrecipitation, MonthlyDewpointTemperature, MonthlyGreatestPrecip, MonthlyGreatestPrecipDate, MonthlyGreatestSnowDepth, MonthlyGreatestSnowDepthDate, MonthlyGreatestSnowfall, MonthlyGreatestSnowfallDate, MonthlyMaxSeaLevelPressureValue, MonthlyMaxSeaLevelPressureValueDate, MonthlyMaxSeaLevelPressureValueTime, MonthlyMaximumTemperature, MonthlyMeanTemperature, MonthlyMinSeaLevelPressureValue, MonthlyMinSeaLevelPressureValueDate, MonthlyMinSeaLevelPressureValueTime, MonthlyMinimumTemperature, MonthlySeaLevelPressure, MonthlyStationPressure, MonthlyTotalLiquidPrecipitation, MonthlyTotalSnowfall, MonthlyWetBulb, AWND, CDSD, CLDD, DSNW, HDSD, HTDD, NormalsCoolingDegreeDay, NormalsHeatingDegreeDay, ShortDurationEndDate005, ShortDurationEndDate010, ShortDurationEndDate015, ShortDurationEndDate020, ShortDurationEndDate030, ShortDurationEndDate045, ShortDurationEndDate060, ShortDurationEndDate080, ShortDurationEndDate100, ShortDurationEndDate120, ShortDurationEndDate150, ShortDurationEndDate180, ShortDurationPrecipitationValue005, ShortDurationPrecipitationValue010, ShortDurationPrecipitationValue015, ShortDurationPrecipitationValue020, ShortDurationPrecipitationValue030, ShortDurationPrecipitationValue045, ShortDurationPrecipitationValue060, ShortDurationPrecipitationValue080, ShortDurationPrecipitationValue100, ShortDurationPrecipitationValue120, ShortDurationPrecipitationValue150, ShortDurationPrecipitationValue180, REM, BackupDirection, BackupDistance, BackupDistanceUnit, BackupElements, BackupElevation, BackupEquipment, BackupLatitude, BackupLongitude, BackupName, WindEquipmentChangeDate" \
-XPUT http://$FE_PROXY/api/quickstart/weatherdata/_stream_load
Enter host password for user 'root':
{
"TxnId": 4,
"Label": "weather-0",
"Status": "Success",
"Message": "OK",
"NumberTotalRows": 22931,
"NumberLoadedRows": 22931,
"NumberFilteredRows": 0,
"NumberUnselectedRows": 0,
"LoadBytes": 15558550,
"LoadTimeMs": 404,
"BeginTxnTimeMs": 1,
"StreamLoadPlanTimeMs": 7,
"ReadDataTimeMs": 157,
"WriteDataTimeMs": 372,
"CommitAndPublishTimeMs": 23
}

Подключение с помощью MySQL-клиента​

Подключитесь с помощью MySQL-клиента, если вы еще не подключены. Не забудьте использовать внешний IP-адрес сервиса kube-selena-fe-service и пароль, который вы настроили в секрете Kubernetes selena-root-pass.

mysql -P9030 -h $MYSQL_IP -u root --prompt="Selena > " -p

Ответы на некоторые вопросы​

Эти запросы можно выполнить в вашем SQL-клиенте. Все запросы используют базу данных quickstart.

USE quickstart;

Сколько аварий происходит в час в Нью-Йорке?​

SELECT COUNT(*),
date_trunc("hour", crashdata.CRASH_DATE) AS Time
FROM crashdata
GROUP BY Time
ORDER BY Time ASC
LIMIT 200;

Вот часть вывода. Обратите внимание, что я рассматриваю более подробно 6 и 7 января, так как это понедельник и вторник обычной рабочей недели. Анализ данных за Новый год, вероятно, не показателен для обычного утра в час пик.

|       14 | 2014-01-06 06:00:00 |
| 16 | 2014-01-06 07:00:00 |
| 43 | 2014-01-06 08:00:00 |
| 44 | 2014-01-06 09:00:00 |
| 21 | 2014-01-06 10:00:00 |
| 28 | 2014-01-06 11:00:00 |
| 34 | 2014-01-06 12:00:00 |
| 31 | 2014-01-06 13:00:00 |
| 35 | 2014-01-06 14:00:00 |
| 36 | 2014-01-06 15:00:00 |
| 33 | 2014-01-06 16:00:00 |
| 40 | 2014-01-06 17:00:00 |
| 35 | 2014-01-06 18:00:00 |
| 23 | 2014-01-06 19:00:00 |
| 16 | 2014-01-06 20:00:00 |
| 12 | 2014-01-06 21:00:00 |
| 17 | 2014-01-06 22:00:00 |
| 14 | 2014-01-06 23:00:00 |
| 10 | 2014-01-07 00:00:00 |
| 4 | 2014-01-07 01:00:00 |
| 1 | 2014-01-07 02:00:00 |
| 3 | 2014-01-07 03:00:00 |
| 2 | 2014-01-07 04:00:00 |
| 6 | 2014-01-07 06:00:00 |
| 16 | 2014-01-07 07:00:00 |
| 41 | 2014-01-07 08:00:00 |
| 37 | 2014-01-07 09:00:00 |
| 33 | 2014-01-07 10:00:00 |

Похоже, что в понедельник или вторник утром в час пик происходит около 40 аварий, и примерно столько же в 17:00.

Какова средняя температура в Нью-Йорке?​

SELECT avg(HourlyDryBulbTemperature),
date_trunc("hour", weatherdata.DATE) AS Time
FROM weatherdata
GROUP BY Time
ORDER BY Time ASC
LIMIT 100;

Вывод:

Обратите внимание, что это данные за 2014 год; в последнее время в Нью-Йорке не было так холодно.

+-------------------------------+---------------------+
| avg(HourlyDryBulbTemperature) | Time |
+-------------------------------+---------------------+
| 25 | 2014-01-01 00:00:00 |
| 25 | 2014-01-01 01:00:00 |
| 24 | 2014-01-01 02:00:00 |
| 24 | 2014-01-01 03:00:00 |
| 24 | 2014-01-01 04:00:00 |
| 24 | 2014-01-01 05:00:00 |
| 25 | 2014-01-01 06:00:00 |
| 26 | 2014-01-01 07:00:00 |

Безопасно ли ездить в Нью-Йорке при плохой видимости?​

Давайте посмотрим на количество аварий при плохой видимости (от 0 до 1,0 мили). Чтобы ответить на этот вопрос, используем JOIN двух таблиц по столбцу DATETIME.

SELECT COUNT(DISTINCT c.COLLISION_ID) AS Crashes,
truncate(avg(w.HourlyDryBulbTemperature), 1) AS Temp_F,
truncate(avg(w.HourlyVisibility), 2) AS Visibility,
max(w.HourlyPrecipitation) AS Precipitation,
date_format((date_trunc("hour", c.CRASH_DATE)), '%d %b %Y %H:%i') AS Hour
FROM crashdata c
LEFT JOIN weatherdata w
ON date_trunc("hour", c.CRASH_DATE)=date_trunc("hour", w.DATE)
WHERE w.HourlyVisibility BETWEEN 0.0 AND 1.0
GROUP BY Hour
ORDER BY Crashes DESC
LIMIT 100;

Наибольшее количество аварий за один час при низкой видимости составляет 129. Есть несколько факторов, которые следует учитывать:

  • 3 февраля 2014 года был понедельник
  • 8 утра — час пик
  • Шёл дождь (0,12 дюйма осадков за этот час)
  • Температура составляла 32 градуса по Фаренгейту (точка замерзания воды)
  • Видимость была плохой — 0,25 мили, нормальная для Нью-Йорка — 10 миль
+---------+--------+------------+---------------+-------------------+
| Crashes | Temp_F | Visibility | Precipitation | Hour |
+---------+--------+------------+---------------+-------------------+
| 129 | 32 | 0.25 | 0.12 | 03 Feb 2014 08:00 |
| 114 | 32 | 0.25 | 0.12 | 03 Feb 2014 09:00 |
| 104 | 23 | 0.33 | 0.03 | 09 Jan 2015 08:00 |
| 96 | 26.3 | 0.33 | 0.07 | 01 Mar 2015 14:00 |
| 95 | 26 | 0.37 | 0.12 | 01 Mar 2015 15:00 |
| 93 | 35 | 0.75 | 0.09 | 18 Jan 2015 09:00 |
| 92 | 31 | 0.25 | 0.12 | 03 Feb 2014 10:00 |
| 87 | 26.8 | 0.5 | 0.09 | 01 Mar 2015 16:00 |
| 85 | 55 | 0.75 | 0.20 | 23 Dec 2015 17:00 |
| 85 | 20 | 0.62 | 0.01 | 06 Jan 2015 11:00 |
| 83 | 19.6 | 0.41 | 0.04 | 05 Mar 2015 13:00 |
| 80 | 20 | 0.37 | 0.02 | 06 Jan 2015 10:00 |
| 76 | 26.5 | 0.25 | 0.06 | 05 Mar 2015 09:00 |
| 71 | 26 | 0.25 | 0.09 | 05 Mar 2015 10:00 |
| 71 | 24.2 | 0.25 | 0.04 | 05 Mar 2015 11:00 |

А как насчёт вождения в условиях гололёда?​

Водяной пар может десублимироваться в лёд при температуре 40 градусов по Фаренгейту; этот запрос рассматривает температуры от 0 до 40 градусов по Фаренгейту.

SELECT COUNT(DISTINCT c.COLLISION_ID) AS Crashes,
truncate(avg(w.HourlyDryBulbTemperature), 1) AS Temp_F,
truncate(avg(w.HourlyVisibility), 2) AS Visibility,
max(w.HourlyPrecipitation) AS Precipitation,
date_format((date_trunc("hour", c.CRASH_DATE)), '%d %b %Y %H:%i') AS Hour
FROM crashdata c
LEFT JOIN weatherdata w
ON date_trunc("hour", c.CRASH_DATE)=date_trunc("hour", w.DATE)
WHERE w.HourlyDryBulbTemperature BETWEEN 0.0 AND 40.5
GROUP BY Hour
ORDER BY Crashes DESC
LIMIT 100;

Результаты для минусовых температур меня немного удивили — я не ожидал большого трафика в воскресенье утром в городе в холодный январский день. Быстрый просмотр weather.com показал, что в тот день был сильный шторм с множеством аварий, как и видно из данных.

+---------+--------+------------+---------------+-------------------+
| Crashes | Temp_F | Visibility | Precipitation | Hour |
+---------+--------+------------+---------------+-------------------+
| 192 | 34 | 1.5 | 0.09 | 18 Jan 2015 08:00 |
| 170 | 21 | NULL | | 21 Jan 2014 10:00 |
| 145 | 19 | NULL | | 21 Jan 2014 11:00 |
| 138 | 33.5 | 5 | 0.02 | 18 Jan 2015 07:00 |
| 137 | 21 | NULL | | 21 Jan 2014 09:00 |
| 129 | 32 | 0.25 | 0.12 | 03 Feb 2014 08:00 |
| 114 | 32 | 0.25 | 0.12 | 03 Feb 2014 09:00 |
| 104 | 23 | 0.7 | 0.04 | 09 Jan 2015 08:00 |
| 98 | 16 | 8 | 0.00 | 06 Mar 2015 08:00 |
| 96 | 26.3 | 0.33 | 0.07 | 01 Mar 2015 14:00 |

Водите осторожно!

exit

Очистка​

Выполните эту команду, если вы закончили и хотите удалить cluster Selena и Selena operator.

helm delete selena

Резюме​

В этом руководстве вы:

  • Развернули Selena с помощью Helm и Selena Operator
  • Загрузили данные о ДТП, предоставленные городом Нью-Йорк, и данные о погоде, предоставленные NOAA
  • Проанализировали данные с использованием SQL JOIN, чтобы выяснить, что вождение при плохой видимости или на обледенелых дорогах — плохая идея

Есть еще много чего изучить; мы намеренно опустили преобразование данных, выполняемое во время Stream Load. Подробности об этом находятся в примечаниях к командам curl ниже.


Примечания к командам curl​

Selena Stream Load и curl принимают множество аргументов. Здесь описаны только те, которые используются в этом руководстве, остальные будут указаны в разделе дополнительной информации.

--location-trusted​

Настраивает curl для передачи учётных данных на любые перенаправленные URL.

-u root​

Имя пользователя для входа в Selena

-T filename​

T означает transfer (передача), имя файла для передачи.

label:name-num​

Метка, связанная с этим заданием Stream Load. Метка должна быть уникальной, поэтому если вы запускаете задание несколько раз, вы можете добавить номер и продолжать его увеличивать.

column_separator:,​

Если вы загружаете файл, использующий одиночную ,, установите её, как показано выше; если вы используете другой разделитель, укажите его здесь. Распространённые варианты: \t, , и |.

skip_header:1​

Некоторые CSV-файлы имеют одну строку заголовка со всеми именами столбцов, а некоторые добавляют вторую строку с типами данных. Установите skip_header в 1 или 2, если у вас одна или две строки заголовка, и установите в 0, если их нет.

enclose:\"​

Обычно строки, содержащие встроенные запятые, заключаются в двойные кавычки. Образцы наборов данных, используемые в этом руководстве, содержат геолокации с запятыми, поэтому параметр enclose установлен в \". Не забудьте экранировать " с помощью \.

max_filter_ratio:1​

Это позволяет некоторые ошибки в данных. В идеале это должно быть установлено в 0, и задание должно завершиться с ошибкой при любых ошибках. Установлено в 1, чтобы разрешить ошибки во всех строках во время отладки.

columns:​

Сопоставление столбцов CSV-файла со столбцами таблицы Selena. Вы заметите, что в CSV-файлах гораздо больше столбцов, чем в таблице. Любые столбцы, не включённые в таблицу, пропускаются.

Вы также заметите, что в строке columns: для набора данных об авариях включено некоторое преобразование данных. Очень часто даты и время в CSV-файлах не соответствуют стандартам. Вот логика преобразования данных CSV для времени и даты аварии в тип DATETIME:

Строка columns​

Это начало одной записи данных. Дата в формате MM/DD/YYYY, а время в формате HH:MI. Поскольку DATETIME обычно имеет формат YYYY-MM-DD HH:MI:SS, нам нужно преобразовать эти данные.

08/05/2014,9:10,BRONX,10469,40.8733019,-73.8536375,"(40.8733019, -73.8536375)",

Это начало параметра columns::

-H "columns:tmp_CRASH_DATE, tmp_CRASH_TIME, CRASH_DATE=str_to_date(concat_ws(' ', tmp_CRASH_DATE, tmp_CRASH_TIME), '%m/%d/%Y %H:%i')

Это указывает Selena:

  • Присвоить содержимое первого столбца CSV-файла переменной tmp_CRASH_DATE
  • Присвоить содержимое второго столбца CSV-файла переменной tmp_CRASH_TIME
  • concat_ws() объединяет tmp_CRASH_DATE и tmp_CRASH_TIME с пробелом между ними
  • str_to_date() создаёт DATETIME из объединённой строки
  • сохранить полученный DATETIME в столбце CRASH_DATE

Дополнительная информация​

values.yaml по умолчанию

Stream Load

Набор данных Motor Vehicle Collisions - Crashes предоставлен городом Нью-Йорк в соответствии с этими условиями использования и политикой конфиденциальности.

Local Climatological Data(LCD) предоставлены NOAA с этим отказом от ответственности и этой политикой конфиденциальности.

Helm — это менеджер пакетов для Kubernetes. Helm Chart — это пакет Helm, содержащий все определения ресурсов, необходимые для запуска приложения в cluster Kubernetes.

selena-kubernetes-operator и kube-selena Helm Chart.