Перейти к основному содержимому
Версия: 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.