MariaDB
 sql >> база данни >  >> RDS >> MariaDB

ProxySQL собствени клъстери с Kubernetes

ProxySQL поддържа собствени клъстери от v1.4.2. Това означава, че множество екземпляри на ProxySQL са наясно с клъстери; те са наясно със състоянието на всеки друг и могат да се справят автоматично с промените в конфигурацията, като синхронизират до най-актуалната конфигурация въз основа на версията на конфигурацията, времевата марка и стойността на контролната сума. Вижте тази публикация в блога, която демонстрира как да конфигурирате поддръжка на клъстери за ProxySQL и как бихте очаквали да се държи.

ProxySQL е децентрализирано прокси, което се препоръчва да се внедри по-близо до приложението. Този подход се мащабира доста добре дори до стотици възли, тъй като е проектиран да бъде лесно преконфигурируем по време на изпълнение. За ефективно управление на множество възли на ProxySQL, трябва да се уверите, че всички промени, извършени на един от възлите, трябва да се прилагат към всички възли във фермата. Без собствено клъстериране, човек трябва ръчно да експортира конфигурациите и да ги импортира в другите възли (макар че бихте могли да автоматизирате това сами).

В предишната публикация в блога разгледахме клъстерирането на ProxySQL чрез Kubernetes ConfigMap. Този подход е повече или по-малко доста ефективен с подхода за централизирано конфигуриране в ConfigMap. Каквото и да е заредено в ConfigMap, ще бъде монтирано в pods. Актуализирането на конфигурацията може да се извърши чрез управление на версиите (променете съдържанието на proxysql.cnf и го заредете в ConfigMap с друго име) и след това натиснете към модулите в зависимост от планирането на метода на разгръщане и стратегията за актуализиране.

Въпреки това, в бързо променяща се среда, този подход на ConfigMap вероятно не е най-добрият метод, тъй като за да се зареди новата конфигурация, е необходимо разсрочване на модула за повторно монтиране на тома ConfigMap и това може да застраши услугата ProxySQL като цяло. Например, да кажем, че в нашата среда нашата строга политика за пароли изисква принудително изтичане на потребителската парола за MySQL на всеки 7 дни, което ще трябва да актуализираме ProxySQL ConfigMap за новата парола на седмична база. Като странична бележка, потребителят на MySQL вътре в ProxySQL изисква потребител и парола, които да съвпадат с тази на сървърите на сървъра на MySQL. Това е мястото, където трябва да започнем да използваме поддръжката на ProxySQL за клъстериране в Kubernetes, за да приложим автоматично промените в конфигурацията, без да се притеснявате от версията на ConfigMap и пренасрочването на модула.

В тази публикация в блога ще ви покажем как да стартирате ProxySQL роден клъстер с безглавна услуга на Kubernetes. Нашата архитектура на високо ниво може да бъде илюстрирана по-долу:

Имаме 3 възела на Galera, работещи върху гола метална инфраструктура, разгърната и управлявана от ClusterControl:

  • 192.168.0.21
  • 192.168.0.22
  • 192.168.0.23

Всички наши приложения работят като модули в Kubernetes. Идеята е да се въведат две копия на ProxySQL между приложението и нашия клъстер от база данни, които да служат като обратен прокси. След това приложенията ще се свържат с ProxySQL модули чрез услугата Kubernetes, която ще бъде балансирана на натоварването и ще бъде преодоляна при отказ в редица реплики на ProxySQL.

Следното е обобщение на нашата настройка на Kubernetes:

[email protected]:~# kubectl get nodes -o wide
NAME    STATUS   ROLES    AGE     VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
kube1   Ready    master   5m      v1.15.1   192.168.100.201   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7
kube2   Ready    <none>   4m1s    v1.15.1   192.168.100.202   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7
kube3   Ready    <none>   3m42s   v1.15.1   192.168.100.203   <none>        Ubuntu 18.04.1 LTS   4.15.0-39-generic   docker://18.9.7

Конфигуриране на ProxySQL чрез ConfigMap

Нека първо подготвим нашата базова конфигурация, която ще бъде заредена в ConfigMap. Създайте файл, наречен proxysql.cnf, и добавете следните редове:

datadir="/var/lib/proxysql"

admin_variables=
{
    admin_credentials="proxysql-admin:adminpassw0rd;cluster1:secret1pass"
    mysql_ifaces="0.0.0.0:6032"
    refresh_interval=2000
    cluster_username="cluster1"
    cluster_password="secret1pass"
    cluster_check_interval_ms=200
    cluster_check_status_frequency=100
    cluster_mysql_query_rules_save_to_disk=true
    cluster_mysql_servers_save_to_disk=true
    cluster_mysql_users_save_to_disk=true
    cluster_proxysql_servers_save_to_disk=true
    cluster_mysql_query_rules_diffs_before_sync=3
    cluster_mysql_servers_diffs_before_sync=3
    cluster_mysql_users_diffs_before_sync=3
    cluster_proxysql_servers_diffs_before_sync=3
}

mysql_variables=
{
    threads=4
    max_connections=2048
    default_query_delay=0
    default_query_timeout=36000000
    have_compress=true
    poll_timeout=2000
    interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
    default_schema="information_schema"
    stacksize=1048576
    server_version="5.1.30"
    connect_timeout_server=10000
    monitor_history=60000
    monitor_connect_interval=200000
    monitor_ping_interval=200000
    ping_interval_server_msec=10000
    ping_timeout_server=200
    commands_stats=true
    sessions_sort=true
    monitor_username="proxysql"
    monitor_password="proxysqlpassw0rd"
    monitor_galera_healthcheck_interval=2000
    monitor_galera_healthcheck_timeout=800
}

mysql_galera_hostgroups =
(
    {
        writer_hostgroup=10
        backup_writer_hostgroup=20
        reader_hostgroup=30
        offline_hostgroup=9999
        max_writers=1
        writer_is_also_reader=1
        max_transactions_behind=30
        active=1
    }
)

mysql_servers =
(
    { address="192.168.0.21" , port=3306 , hostgroup=10, max_connections=100 },
    { address="192.168.0.22" , port=3306 , hostgroup=10, max_connections=100 },
    { address="192.168.0.23" , port=3306 , hostgroup=10, max_connections=100 }
)

mysql_query_rules =
(
    {
        rule_id=100
        active=1
        match_pattern="^SELECT .* FOR UPDATE"
        destination_hostgroup=10
        apply=1
    },
    {
        rule_id=200
        active=1
        match_pattern="^SELECT .*"
        destination_hostgroup=20
        apply=1
    },
    {
        rule_id=300
        active=1
        match_pattern=".*"
        destination_hostgroup=10
        apply=1
    }
)

mysql_users =
(
    { username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
    { username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)

proxysql_servers =
(
    { hostname = "proxysql-0.proxysqlcluster", port = 6032, weight = 1 },
    { hostname = "proxysql-1.proxysqlcluster", port = 6032, weight = 1 }
)

Някои от горните конфигурационни редове са обяснени в раздел по-долу:

административни_променливи

Обърнете внимание на admin_credentials променлива, където използвахме потребител, който не е по подразбиране, който е "proxysql-admin". ProxySQL запазва потребителя по подразбиране "admin" за локална връзка само чрез localhost. Следователно трябва да използваме други потребители за отдалечен достъп до екземпляра на ProxySQL. В противен случай ще получите следната грешка:

ERROR 1040 (42000): User 'admin' can only connect locally

Добавихме и cluster_username и cluster_password стойност в admin_credentials ред, разделени с точка и запетая, за да се позволи автоматично синхронизиране. Всички променливи с префикс с cluster_* са свързани с родния клъстер на ProxySQL и се разбират сами.

mysql_galera_hostgroups

Това е нова директива, въведена за ProxySQL 2.x (нашето ProxySQL изображение работи на 2.0.5). Ако искате да работите на ProxySQL 1.x, премахнете тази част и вместо това използвайте таблицата на планировчика. Вече обяснихме подробностите за конфигурацията в тази публикация в блога, Как да стартирате и конфигурирате ProxySQL 2.0 за MySQL Galera Cluster на Docker под „Поддръжка на ProxySQL 2.x за Galera Cluster“.

mysql_servers

Всички редове се обясняват сами, което се основава на три сървъра на бази данни, работещи в MySQL Galera Cluster, както е обобщено в следната екранна снимка на топологията, взета от ClusterControl:

proxysql_servers

Тук ние дефинираме списък с партньори на ProxySQL:

  • име на хост – име на хост/IP адрес на партньор
  • порт – Администраторски порт на Peer
  • тегло – в момента не се използва, но в пътната карта за бъдещи подобрения
  • коментар – поле за коментар в свободна форма

В средата на Docker/Kubernetes има множество начини да откриете и свържете имена на хостове или IP адреси на контейнери и да ги вмъкнете в тази таблица, или чрез използване на ConfigMap, ръчно вмъкване, чрез скриптове на entrypoint.sh, променливи на средата или по някакъв друг начин. В Kubernetes, в зависимост от използвания ReplicationController или метод за разгръщане, предварителното отгатване на разрешаваемото име на хост на модула е малко трудно, освен ако не работите на StatefulSet.

Вижте този урок за порядковия индекс на StatefulState, който предоставя стабилно разрешимо име на хост за създадените модули. Комбинирайте това с услугата без глава (обяснено по-долу), форматът на име на хост ще бъде:

{app_name}-{index_number}.{service}

Където {service} е услуга без глава, която обяснява откъде идват "proxysql-0.proxysqlcluster" и "proxysql-1.proxysqlcluster". Ако искате да имате повече от 2 реплики, добавете съответно повече записи, като добавите нарастващ индексен номер спрямо името на приложението StatefulSet.

Сега сме готови да натиснем конфигурационния файл в ConfigMap, който ще бъде монтиран във всеки ProxySQL модул по време на внедряването:

$ kubectl create configmap proxysql-configmap --from-file=proxysql.cnf

Проверете дали нашата ConfigMap е заредена правилно:

$ kubectl get configmap
NAME                 DATA   AGE
proxysql-configmap   1      7h57m

Създаване на потребител за наблюдение на ProxySQL

Следващата стъпка, преди да започнем внедряването, е да създадем потребител за мониторинг на ProxySQL в нашия клъстер от база данни. Тъй като работим в клъстера Galera, изпълнете следните оператори на един от възлите на Galera:

mysql> CREATE USER 'proxysql'@'%' IDENTIFIED BY 'proxysqlpassw0rd';
mysql> GRANT USAGE ON *.* TO 'proxysql'@'%';

Ако не сте създали потребителите на MySQL (както е посочено в секцията mysql_users по-горе), ние също трябва да ги създадем:

mysql> CREATE USER 'wordpress'@'%' IDENTIFIED BY 'passw0rd';
mysql> GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'%';
mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
mysql> GRANT ALL PRIVILEGES ON sbtest.* TO 'proxysql'@'%';

Това е. Вече сме готови да започнем внедряването.

Разгръщане на StatefulSet

Ще започнем със създаване на две копия на ProxySQL или реплики за целите на излишъка, използвайки StatefulSet.

Нека започнем със създаване на текстов файл, наречен proxysql-ss-svc.yml и добавяне на следните редове:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: proxysql
  labels:
    app: proxysql
spec:
  replicas: 2
  serviceName: proxysqlcluster
  selector:
    matchLabels:
      app: proxysql
      tier: frontend
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: proxysql
        tier: frontend
    spec:
      restartPolicy: Always
      containers:
      - image: severalnines/proxysql:2.0.4
        name: proxysql
        volumeMounts:
        - name: proxysql-config
          mountPath: /etc/proxysql.cnf
          subPath: proxysql.cnf
        ports:
        - containerPort: 6033
          name: proxysql-mysql
        - containerPort: 6032
          name: proxysql-admin
      volumes:
      - name: proxysql-config
        configMap:
          name: proxysql-configmap
---
apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    app: proxysql
    tier: frontend
  name: proxysql
spec:
  ports:
  - name: proxysql-mysql
    nodePort: 30033
    port: 6033
    protocol: TCP
    targetPort: 6033
  - name: proxysql-admin
    nodePort: 30032
    port: 6032
    protocol: TCP
    targetPort: 6032
  selector:
    app: proxysql
    tier: frontend
  type: NodePort

Има два раздела от горната дефиниция - StatefulSet и Service. StatefulSet е дефиницията на нашите модули или реплики и точката на монтиране за нашия том ConfigMap, заредена от proxysql-configmap. Следващият раздел е дефиницията на услугата, където дефинираме как модулите трябва да бъдат изложени и маршрутизирани за вътрешната или външната мрежа.

Създайте ProxySQL набор и услуга с проследяване на състоянието:

$ kubectl create -f proxysql-ss-svc.yml

Проверете състоянието на модула и услугата:

$ kubectl get pods,svc
NAME             READY   STATUS    RESTARTS   AGE
pod/proxysql-0   1/1     Running   0          4m46s
pod/proxysql-1   1/1     Running   0          2m59s

NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE
service/kubernetes        ClusterIP   10.96.0.1        <none>        443/TCP                         10h
service/proxysql          NodePort    10.111.240.193   <none>        6033:30033/TCP,6032:30032/TCP   5m28s

Ако погледнете дневника на модула, ще забележите, че сме наводнени с това предупреждение:

$ kubectl logs -f proxysql-0
...
2019-08-01 19:06:18 ProxySQL_Cluster.cpp:215:ProxySQL_Cluster_Monitor_thread(): [WARNING] Cluster: unable to connect to peer proxysql-1.proxysqlcluster:6032 . Error: Unknown MySQL server host 'proxysql-1.proxysqlcluster' (0)

Горното просто означава, че proxysql-0 не е успял да разреши "proxysql-1.proxysqlcluster" и да се свърже с него, което се очаква, тъй като не сме създали нашата безглавна услуга за DNS записи, които ще са необходими за комуникация между ProxySQL.

Услуга без глава Kubernetes

За да могат ProxySQL модулите да разрешат очакваното FQDN и да се свържат директно с него, процесът на разрешаване трябва да може да търси присвоения IP адрес на целеви модул, а не виртуалния IP адрес. Тук се появява услугата без глава. Когато създавате услуга без глава чрез настройка на "clusterIP=None", не се конфигурира балансиране на натоварването и не се разпределя IP на клъстер (виртуален IP) за тази услуга. Само DNS се конфигурира автоматично. Когато стартирате DNS заявка за безглавна услуга, ще получите списък с IP адресите на pods.

Ето как изглежда, ако потърсим DNS записите на услугата без глава за "proxysqlcluster" (в този пример имахме 3 екземпляра на ProxySQL):

$ host proxysqlcluster
proxysqlcluster.default.svc.cluster.local has address 10.40.0.2
proxysqlcluster.default.svc.cluster.local has address 10.40.0.3
proxysqlcluster.default.svc.cluster.local has address 10.32.0.2

Докато следният изход показва DNS записа за стандартната услуга, наречена "proxysql", която се разрешава до clusterIP:

$ host proxysql
proxysql.default.svc.cluster.local has address 10.110.38.154

За да създадете услуга без глава и да я прикачите към pods, трябва да дефинирате ServiceName в декларацията StatefulSet, а дефиницията на услугата трябва да има "clusterIP=None", както е показано по-долу. Създайте текстов файл, наречен proxysql-headless-svc.yml и добавете следните редове:

apiVersion: v1
kind: Service
metadata:
  name: proxysqlcluster
  labels:
    app: proxysql
spec:
  clusterIP: None
  ports:
  - port: 6032
    name: proxysql-admin
  selector:
    app: proxysql

Създайте услугата без глава:

$ kubectl create -f proxysql-headless-svc.yml

Само за потвърждение, в този момент имаме работещи следните услуги:

$ kubectl get svc
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP                         8h
proxysql          NodePort    10.110.38.154   <none>        6033:30033/TCP,6032:30032/TCP   23m
proxysqlcluster   ClusterIP   None            <none>        6032/TCP                        4s

Сега вижте един от регистрационните файлове на нашия модул:

$ kubectl logs -f proxysql-0
...
2019-08-01 19:06:19 ProxySQL_Cluster.cpp:215:ProxySQL_Cluster_Monitor_thread(): [WARNING] Cluster: unable to connect to peer proxysql-1.proxysqlcluster:6032 . Error: Unknown MySQL server host 'proxysql-1.proxysqlcluster' (0)
2019-08-01 19:06:19 [INFO] Cluster: detected a new checksum for mysql_query_rules from peer proxysql-1.proxysqlcluster:6032, version 1, epoch 1564686376, checksum 0x3FEC69A5C9D96848 . Not syncing yet ...
2019-08-01 19:06:19 [INFO] Cluster: checksum for mysql_query_rules from peer proxysql-1.proxysqlcluster:6032 matches with local checksum 0x3FEC69A5C9D96848 , we won't sync.

Ще забележите, че компонентът Cluster е в състояние да разрешава, свързва и открива нова контролна сума от другия партньор, proxysql-1.proxysqlcluster на порт 6032 чрез безглавната услуга, наречена "proxysqlcluster". Имайте предвид, че тази услуга разкрива порт 6032 само в мрежата на Kubernetes, поради което е недостъпен отвън.

На този етап внедряването ни вече е завършено.

Свързване с ProxySQL

Има няколко начина за свързване с ProxySQL услуги. Балансираните по натоварване MySQL връзки трябва да се изпращат до порт 6033 от мрежата на Kubernetes и да използват порт 30033, ако клиентът се свързва от външна мрежа.

За да се свържем с администраторския интерфейс на ProxySQL от външна мрежа, можем да се свържем с порта, дефиниран в раздел NodePort, 30032 (192.168.100.203 е основният IP адрес на хост kube3.local):

$ mysql -uproxysql-admin -padminpassw0rd -h192.168.100.203 -P30032

Използвайте clusterIP 10.110.38.154 (дефиниран в услугата „proxysql“) на порт 6032, ако искате да получите достъп до него от други модули в мрежата на Kubernetes.

След това извършете промените в конфигурацията на ProxySQL, както желаете, и ги заредете във времето за изпълнение:

mysql> INSERT INTO mysql_users (username,password,default_hostgroup) VALUES ('newuser','passw0rd',10);
mysql> LOAD MYSQL USERS TO RUNTIME;

Ще забележите следните редове в един от модулите, които показват, че синхронизирането на конфигурацията е завършено:

$ kubectl logs -f proxysql-0
...
2019-08-02 03:53:48 [INFO] Cluster: detected a peer proxysql-1.proxysqlcluster:6032 with mysql_users version 2, epoch 1564718027, diff_check 4. Own version: 1, epoch: 1564714803. Proceeding with remote sync
2019-08-02 03:53:48 [INFO] Cluster: detected peer proxysql-1.proxysqlcluster:6032 with mysql_users version 2, epoch 1564718027
2019-08-02 03:53:48 [INFO] Cluster: Fetching MySQL Users from peer proxysql-1.proxysqlcluster:6032 started
2019-08-02 03:53:48 [INFO] Cluster: Fetching MySQL Users from peer proxysql-1.proxysqlcluster:6032 completed

Имайте предвид, че автоматичното синхронизиране се случва само ако има промяна в конфигурацията в времето за изпълнение на ProxySQL. Ето защо е жизненоважно да изпълните оператор "LOAD ... TO RUNTIME", преди да можете да видите действието. Не забравяйте да запазите промените в ProxySQL на диска за постоянство:

mysql> SAVE MYSQL USERS TO DISK;

Ограничение

Имайте предвид, че има ограничение за тази настройка, тъй като ProxySQL не поддържа запазване/експортиране на активната конфигурация в текстов конфигурационен файл, който бихме могли да използваме по-късно за зареждане в ConfigMap за постоянство. Има заявка за функция за това. Междувременно можете да натиснете ръчно модификациите в ConfigMap. В противен случай, ако модулите бъдат изтрити случайно, ще загубите текущата си конфигурация, защото новите модули ще бъдат заредени от всичко, дефинирано в ConfigMap.

Специални благодарности на Sampath Kamineni, който предизвика идеята за тази публикация в блога и предостави информация за случаите на използване и прилагането.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Лесният начин за внедряване на MySQL Galera Cluster в AWS

  2. Подготовка на MySQL или MariaDB сървър за производство - част втора

  3. Как работи DEGREES() в MariaDB

  4. Как REPEAT() работи в MariaDB

  5. Как работи COALESCE() в MariaDB