Не удается подключиться к контейнеру cassandra через haproxy

Я пытаюсь подключить внешнее приложение к Cassandra, которое работает в докеризованном состоянии в кластере mesos.

Вот приложения, которые я использую на mesos:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                        NAMES
137760ce852a        cassandra:latest    "/docker-entrypoint.s"   15 minutes ago      Up 15 minutes       7000-7001/tcp, 7199/tcp, 9160/tcp, 0.0.0.0:31634->9042/tcp   mesos-1b65f33a-3d36-4bf4-8a77-32077d8d234a-S1.0db174cc-2e0c-4790-9cd7-1f142d08c6e2
fec5fc93ccfd        cassandra:latest    "/docker-entrypoint.s"   22 minutes ago      Up 22 minutes       7000-7001/tcp, 7199/tcp, 9160/tcp, 0.0.0.0:31551->9042/tcp   mesos-1b65f33a-3d36-4bf4-8a77-32077d8d234a-S1.0022a3d2-d695-43c4-b22f-f5274cbd03ce
ca729ee628bb        tobilg/mesos-dns    "./bootstrap.sh"         About an hour ago   Up About an hour                                                                 mesos-1b65f33a-3d36-4bf4-8a77-32077d8d234a-S1.12593777-2295-42fa-a56d-1d3cc9fc70ff
3921002a8a5b        python:3            "/bin/sh -c 'env >env"   About an hour ago   Up About an hour    0.0.0.0:31295->8080/tcp                                      mesos-1b65f33a-3d36-4bf4-8a77-32077d8d234a-S1.b101ab59-2538-416f-80cf-29215794bd37

приложение под названием Peek используется только для тестирования предложений. Я могу получить к нему доступ по URL-адресу: http://192.168.56.101:10001 без проблем.

2 экземпляра cassandra — это начальный и еще один для масштабирования; образуя кластер.

Описание json для развертывания приложений cassandra на марафоне выглядит следующим образом:

/cassandra-seed

{
    "id": "cassandra-seed",
    "constraints": [["hostname", "CLUSTER", "docker-sl-vm"]],
    "container": {
        "type": "DOCKER",
        "docker": {
            "image": "cassandra:latest",
            "network": "BRIDGE",
            "portMappings": [ {"containerPort": 9042,"hostPort": 0,"servicePort": 0,"protocol": "tcp"} ]
        }
    },
    "cpus": 0.5,
    "mem": 512.0,
    "instances": 1,
    "backoffSeconds": 1,
    "backoffFactor": 1.15,
    "maxLaunchDelaySeconds": 3600
}

/кассандра

{
    "id": "cassandra",
    "constraints": [["hostname", "CLUSTER", "docker-sl-vm"]],
    "container": {
        "type": "DOCKER",
        "docker": {
            "image": "cassandra:latest",
            "network": "BRIDGE",
            "portMappings": [ {"containerPort": 9042,"hostPort": 0,"servicePort": 0,"protocol": "tcp"} ]
        }
    },
    "env": {
            "CASSANDRA_SEED_COUNT": "1",
        "CASSANDRA_SEEDS": "cassandra-seed.marathon.mesos"
    },
    "cpus": 0.5,
    "mem": 512.0,
    "instances": 1,
    "backoffSeconds": 1,
    "backoffFactor": 1.15,
    "maxLaunchDelaySeconds": 3600
}

конфигурация haproxy следующая:

global
  daemon
  log 127.0.0.1 local0
  log 127.0.0.1 local1 notice
  maxconn 4096
  tune.ssl.default-dh-param 2048

defaults
  log               global
  retries           3
  maxconn           2000
  timeout connect   5s
  timeout client    50s
  timeout server    50s

listen stats
  bind 127.0.0.1:9090
  balance
  mode http
  stats enable
  stats auth admin:admin

frontend marathon_http_in
  bind *:80
  mode http

frontend marathon_http_appid_in
  bind *:81
  mode http

frontend marathon_https_in
  bind *:443 ssl crt /etc/ssl/xip.io/xip.io.pem
  mode http

frontend cassandra_10003
  bind *:10003
  mode tcp
  use_backend cassandra_10003

frontend cassandra-seed_10002
  bind *:10002
  mode tcp
  use_backend cassandra-seed_10002

frontend dns_10000
  bind *:10000
  mode tcp
  use_backend dns_10000

frontend peek_10001
  bind *:10001
  mode tcp
  use_backend peek_10001

backend cassandra_10003
  balance roundrobin
  mode tcp
  server docker-sl-vm_31634 192.168.56.102:31634

backend cassandra-seed_10002
  balance roundrobin
  mode tcp
  server docker-sl-vm_31551 192.168.56.102:31551

backend dns_10000
  balance roundrobin
  mode tcp
  server docker-sl-vm_31314 192.168.56.102:31314

backend peek_10001
  balance roundrobin
  mode tcp
  server docker-sl-vm_31295 192.168.56.102:31295

Приложение, которое я пытаюсь подключить к Cassandra, является приложением Play. Я устанавливаю это так:

akka.persistence {
  journal.plugin = "cassandra-journal"
  snapshot-store.plugin = "cassandra-snapshot-store"
}

cassandra-journal.contact-points = ["192.168.56.101:10003"]
cassandra-snapshot-store.contact-points = ["192.168.56.101:10003"]

Приложение запускается нормально, но когда я пытаюсь получить к нему доступ, я получаю следующую ошибку:

! @6o380dcg9 - Internal server error, for (GET) [/issues/list] ->

play.api.Application$$anon$1: Execution exception[[TimeoutException: deadline passed]]
        at play.api.Application$class.handleError(Application.scala:296) ~[play_2.11-2.3.10.jar:2.3.10]
        at play.api.DefaultApplication.handleError(Application.scala:402) [play_2.11-2.3.10.jar:2.3.10]
        at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$14$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:205) [play_2.11-2.3.10.jar:2.3.10]
        at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$14$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:202) [play_2.11-2.3.10.jar:2.3.10]
        at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) [scala-library-2.11.7.jar:na]
Caused by: java.util.concurrent.TimeoutException: deadline passed
        at akka.actor.dsl.Inbox$InboxActor$$anonfun$receive$1.applyOrElse(Inbox.scala:117) ~[akka-actor_2.11-2.4.0.jar:na]
        at scala.PartialFunction$AndThen.applyOrElse(PartialFunction.scala:189) ~[scala-library-2.11.7.jar:na]
        at akka.actor.Actor$class.aroundReceive(Actor.scala:480) ~[akka-actor_2.11-2.4.0.jar:na]
        at akka.actor.dsl.Inbox$InboxActor.aroundReceive(Inbox.scala:62) ~[akka-actor_2.11-2.4.0.jar:na]
        at akka.actor.ActorCell.receiveMessage(ActorCell.scala:525) ~[akka-actor_2.11-2.4.0.jar:na]
[error] c.d.d.c.Session - Error creating pool to /172.17.0.2:9042
com.datastax.driver.core.TransportException: [/172.17.0.2:9042] Cannot connect
        at com.datastax.driver.core.Connection.<init>(Connection.java:109) ~[cassandra-driver-core-2.1.5.jar:na]
        at com.datastax.driver.core.PooledConnection.<init>(PooledConnection.java:32) ~[cassandra-driver-core-2.1.5.jar:na]
        at com.datastax.driver.core.Connection$Factory.open(Connection.java:586) ~[cassandra-driver-core-2.1.5.jar:na]
        at com.datastax.driver.core.SingleConnectionPool.<init>(SingleConnectionPool.java:76) ~[cassandra-driver-core-2.1.5.jar:na]
        at com.datastax.driver.core.HostConnectionPool.newInstance(HostConnectionPool.java:35) ~[cassandra-driver-core-2.1.5.jar:na]
Caused by: org.jboss.netty.channel.ConnectTimeoutException: connection timed out: /172.17.0.2:9042
        at org.jboss.netty.channel.socket.nio.NioClientBoss.processConnectTimeout(NioClientBoss.java:139) ~[netty-3.9.9.Final.jar:na]
        at org.jboss.netty.channel.socket.nio.NioClientBoss.process(NioClientBoss.java:83) ~[netty-3.9.9.Final.jar:na]
        at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:337) ~[netty-3.9.9.Final.jar:na]
        at org.jboss.netty.channel.socket.nio.NioClientBoss.run(NioClientBoss.java:42) ~[netty-3.9.9.Final.jar:na]
        at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108) ~[netty-3.9.9.Final.jar:na]
[error] c.d.d.c.Session - Error creating pool to /172.17.0.2:9042

Кто-нибудь знает, как это исправить? Что я делаю не так?

Заранее спасибо...

ОБНОВЛЕНИЕ =============================

Интересно, что были созданы пространства ключей для моего приложения (akka, akka_snapshots):

cqlsh> describe keyspaces;
akka_snapshot  system_auth  system  system_distributed  system_traces  akka

ОБНОВЛЕНИЕ 2 =============================

Я только что заметил, что я даже не могу напрямую подключить приложение к работающей кассандре (без использования haproxy). Итак, я изменил portMapping на:

"portMappings": [ {"containerPort": 9042,"hostPort": 0,"servicePort": 9042,"protocol": "tcp"} ]

и это сработало. ОДНАКО, это позволяет мне запускать только одну машину из-за объявления servicePort.

Проблема прямо в отображении портов. Любая подсказка?


person RafaelTSCS    schedule 05.11.2015    source источник
comment
Что произойдет, если вы удалите определения hostPort и servicePort из JSON приложения Marathon?   -  person Tobi    schedule 06.11.2015
comment
Привет, Тоби! Спасибо за ответы. Я сделал то, что вы просили, но ничего не изменилось.   -  person RafaelTSCS    schedule 06.11.2015
comment
Что касается вашего обновления 2), что произойдет, если вы используете "portMappings": [ {"containerPort": 9042,"protocol": "tcp"} ], как я предложил?   -  person Tobi    schedule 09.11.2015
comment
Ничего не произошло. Он остается прежним.   -  person RafaelTSCS    schedule 09.11.2015
comment
Это не очень конкретно :-/ Бьюсь об заклад, это не совсем то же самое, потому что теперь порт 9042 уже не должен быть заблокирован. Пожалуйста, опубликуйте несколько сообщений об ошибках, иначе помочь будет невозможно.   -  person Tobi    schedule 09.11.2015
comment
Я имею в виду. Оба экземпляра поднимаются. Но я не могу подключиться ни к одному из них. Кажется, служебные порты между хостом и контейнером неизвестны. Я не получаю сообщений об ошибках, независимо от трассировки стека, упомянутой выше.   -  person RafaelTSCS    schedule 09.11.2015
comment
@RafaelTSCS: Привет, я вижу (в комментарии ниже), что вам удалось заставить узлы общаться между собой. Пытаюсь сделать подобное развертывание, однако, ноды не могут сплетничать. В режиме моста служба Cassandra запускается с IP-адреса контейнера докера, а не с IP-адреса хоста. Однако раскопки показывают мне, что IP-адрес для Cassandra-seed.marathon.mesos является IP-адресом хоста. Таким образом, я не могу предоставить действительный IP-адрес для семян в новых узлах. Я был бы признателен, если бы вы могли опубликовать окончательный json, который вы использовали для развертывания начальных и неисходных узлов?   -  person Manolis    schedule 10.01.2017
comment
Привет @Манолис. Мне жаль. Я бы хотел тебе помочь, но у меня больше нет этого. Так получилось, что пока не используем, так как система еще не в продакшене. Я думаю, что моя проблема была связана с портом и физической машиной.   -  person RafaelTSCS    schedule 11.01.2017
comment
Нет проблем @RafaelTSCS! Благодарю вас!   -  person Manolis    schedule 11.01.2017


Ответы (1)


Насколько я понимаю, вы используете haproxy для обнаружения служб кластера Cassandra. Если да, то успеха не будет, если у вас нет механизма обновления конфигурации после изменения задач из Marathon (масштабирование и т.д.).

Проблема, почему ваши узлы Cassandra не могут общаться друг с другом, предположительно заключается в том, что приложение /cassandra не имеет ссылки на /cassandra-seed .

Согласно документам образа Cassandra Docker, вы должны иметь возможность динамически настраивать параметр CASSANDRA_SEEDS env.

Чтобы иметь возможность использовать имя службы cassandra-seed.marathon.mesos, если необходимо сначала преобразовать его в IP-адрес IMHO:

"CASSANDRA_SEEDS": "$(host cassandra-seed.marathon.mesos | awk '/has address/ { print $4 }')"

будет теоретически работать (например, если ваше приложение имеет только один экземпляр).

Поскольку вы используете Mesos DNS, может возникнуть проблема, поскольку в настоящее время (v0.4.0) рекламируются только внутренние IP-адреса (см. Проблема). Возможно, вам придется вернуться к «настоящему» DNS-клиенту Mesos, который может разрешать записи SRV, чтобы правильно сопоставить их с IP-адресами и портами Mesos Slave.

Или вы можете самостоятельно проанализировать результаты dig и использовать их в качестве входных данных для параметра CASSANDRA_SEEDS env:

dig _cassandra-seed._tcp.marathon.mesos SRV

см. документацию Mesos DNS.

mesosdns-cli может справиться с этим, но требует среды выполнения Node.js в контейнере Docker, где его следует использовать. Поэтому вам придется создать собственный производный образ cassandra Docker.

person Tobi    schedule 11.11.2015
comment
Вы правы. Но как получается, что я даже не могу подключиться к кассандре, используя IP-адрес подчиненного устройства и сервисный порт? например 192.168.56.102:10003. Я могу сделать это, только если привяжу сервисный порт к 9042 и подключу приложение к 192.168.56.102:9042. - person RafaelTSCS; 11.11.2015
comment
Ну, я не знаю, но я также думаю, что это, возможно, побочный вопрос. Во-первых, вы должны убедиться, что можете подключить свои экземпляры Cassandra. - person Tobi; 11.11.2015
comment
Если я запускаю состояние nodetool внутри любого из двух контейнеров, это дает мне 2 узла. Значит, они могут говорить. Но внешнее приложение не может. - person RafaelTSCS; 11.11.2015
comment
Но если вы подключитесь к 192.168.56.102:31634 напрямую, это сработает...? - person Tobi; 13.11.2015
comment
Что ж. Извините за задержку. Меня направили к другому вопросу. Отвечая на ваш вопрос. Не работает на 192.168.56.102:31634. Это работает, только если я определяю сервисный порт как 9042 на марафоне. - person RafaelTSCS; 02.12.2015