yahoo / CMAK

CMAK is a tool for managing Apache Kafka clusters
Apache License 2.0
11.84k stars 2.51k forks source link

How to use KM behind a proxy? #218

Open dwu-zingbox opened 8 years ago

dwu-zingbox commented 8 years ago

I'd like to use KM behind Nginx proxy with the app root path different from /. What should I do to fix all thoserouting? Nginx config might read as,

location /kafka-manager/ { proxy_pass http://localhost:9000/; }

dwu-zingbox commented 8 years ago

Problems are these static hosted files,

http://my.server.com/vassets/stylesheets/2b56540dba204490b0a8b01818b05991-index.min.css http://my.server.com/vassets/dataTables/stylesheets/49765a39721f9ac7365f6a01962c52ef-dataTables.bootstrap.css http://my.server.com/vassets/dataTables/javascripts/280ff6aaaba888ccb486e669fd200b8e-jquery.dataTables.min.js http://my.server.com/vassets/chartist/stylesheets/0dd8d6c6dca261528d9be38904d656d3-chartist.min.css http://my.server.com/vassets/chartist/javascripts/c7d17af297af222b85192c2df48b8390-chartist.min.js http://my.server.com/webjars/jquery/2.1.4/jquery.min.js http://my.server.com/webjars/bootstrap/3.3.5/js/bootstrap.min.js http://my.server.com/vassets/dataTables/javascripts/8e519890a2e2499da2b753c65a5dc27c-dataTables.bootstrap.js http://my.server.com/vassets/images/2af62f58ee2baf495c9b3a9a1c30ce03-favicon.png http://my.server.com/webjars/bootstrap/3.3.5/css/bootstrap.min.css http://my.server.com/vassets/dataTables/stylesheets/49765a39721f9ac7365f6a01962c52ef-dataTables.bootstrap.css http://my.server.com/vassets/chartist/stylesheets/0dd8d6c6dca261528d9be38904d656d3-chartist.min.css http://my.server.com/vassets/stylesheets/2b56540dba204490b0a8b01818b05991-index.min.css

patelh commented 8 years ago

Would this help? https://www.playframework.com/documentation/2.4.x/HTTPServer#Set-up-with-nginx

dwu-zingbox commented 8 years ago

Thank you. But that's not enough. Lots of requests from browser still reference to / which make server side routing really difficult. Lots of code need to eliminate the absolute path.

hotstepper13 commented 8 years ago

Same problem on Apache. The vassets and webjars directrories can be mapped but the application itself uses hardcoded / as link target (if you click on cluster->list) or /addCluster (if you click on cluster->add) and i am sure that all other action will use / as target :(

Because I use the same apache as reverseproxy for many tools (complete mesos cluster administration) I cannot map all requests to kafka.

I will try to play around with some rewrite rules dependant of the refferer (uuhhh....)

dwu-zingbox commented 8 years ago

Lots of rewrite rules to be made. They might interfere with other services. Will spend more time to dig into codes.

dwu-zingbox commented 8 years ago

Spent some more time and found a cure:

1, Modify all routes in the conf/routes by adding desired routing, /kafka-manager as below. This will force both FE and BE code running under /kafka-manager/.

GET         /kafka-manager/                                             controllers.Application.index
GET         /kafka-manager/clusters/:c                                  controllers.Cluster.cluster(c:String)
GET         /kafka-manager/clusters/:c/topics                           controllers.Topic.topics(c:String)
GET         /kafka-manager/clusters/:c/topics/addPartitions             controllers.Topic.addPartitionsToMultipleTopics(c:String)

# Versioned Assets
GET         /kafka-manager/vassets/*file          controllers.Assets.versioned(path="/public", file: Asset)

# Unversioned Assets
GET         /kafka-manager/assets/*file           controllers.Assets.at(path="/public", file)

# WebJars
GET         /kafka-manager/webjars/*file          controllers.WebJarAssets.at(file)
  1. Nginx is configured as below.
server {
        ......
        location /kafka-manager/ {
                proxy_pass http://localhost:9001/kafka-manager/;
                proxy_connect_timeout   2;
                proxy_redirect off;
                proxy_buffering off;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

Now enjoy your KM at /kafka-manager/

patelh commented 8 years ago

Might consider defaulting everything to /kafka-manager/*. Let me think about it, don't want to impact existing users.

hotstepper13 commented 8 years ago

To be honest, I think the best way would be to have a configuration value for this or maybe the whole base-url.

This would allow existing users to work without the new context and other could just turn it on. I didnt know scala but I a sure that there are ways to archive this without much additional effort.

aadrian commented 8 years ago

The best way would be to make KM a webapplication (a WAR see request #166 ) This way everything can be relative to the context (that can be renamed) and it's also trivial to integrate it correctly with NginX or Apache.

hotstepper13 commented 8 years ago

@dwu-zingbox

I have tried your solution with the routes file and it didnt work for me. Is there anything else that need to be changed?

I tried both variants (just adding the custom file to container and building with the customized file) without any success

dwu-zingbox commented 8 years ago

@hotstepper13

A few thing you can double check,

  1. Did you compile it again after modifying the routes file? 2, If the modified routes works, you should be able to see if at <your_server>:<km_port>/your_route/ first.
  2. Open the dev mode of your browser and see if any link returns 404.
  3. If your KM works fine on its port with the new routing. Try curl through your proxy and see what the first page you can get

Good luck

hotstepper13 commented 8 years ago

@dwu-zingbox That for your reply. I use Docker to server the application. I have created a modified routes file.

The process is, Download and extract the sources from master, overwrite the routes file with the modified one, start the sbt script.

I choose the prefix /kafka/ for my services.

The process is based on https://github.com/sheepkiller/kafka-manager-docker/blob/master/Dockerfile and the only change is that i add my custom routes file which makes it look like:

ENV ZK_HOSTS=localhost:2181 \
    KM_VERSION=1.3.0.7 \
    KM_REVISION=4b57fc9b65e6f9ac88fff4391994fd06bb782663 \
    KM_CONFIGFILE="conf/application.conf"

COPY routes /ttt/

RUN apk --update add --no-cache git bash && \
    mkdir -p /tmp && \
    cd /tmp && \
    git clone https://github.com/yahoo/kafka-manager && \
    cd /tmp/kafka-manager && \
    git checkout ${KM_REVISION} && \
    cp /ttt/routes /tmp/kafka-manager/conf/ && \
    echo 'scalacOptions ++= Seq("-Xmax-classfile-name", "200")' >> build.sbt && \
    ./sbt clean dist && \
    unzip  -d / ./target/universal/kafka-manager-${KM_VERSION}.zip && \
    rm -fr /tmp/* /root/.sbt /root/.ivy2 && \
    printf '#!/bin/sh\nexec ./bin/kafka-manager -Dconfig.file=${KM_CONFIGFILE} "${KM_ARGS}" "${@}"\n' > /kafka-manager-${KM_VERSION}/km.sh && \
    chmod +x /kafka-manager-${KM_VERSION}/km.sh && \
    rm -fr /kafka-manager-${KM_VERSION}/share \
    apk del git

I can see that my modified routes finally ended up in /kafka-manager-1.3.0.7/conf and contain my changes. Therefore it looks as it would be used. But as i access the application, it says "action not found "For request 'GET /kafka/'"

[UPDATE] While debugging this i found a variable prefix that seems to be available in the routes files. I found a scala file that will be generated out of the routes. However I have no clue how to set it. For now I try a different approach in building outside of docker without any additional scala properties and then add the build zip file to the container. Maybe this will help.

[UPDATE2] nah, it didnt work. But it looks like as if i have a problem with my kafka installation as it seems to report the containerid as hostname. This leads to rmi exceptions within kafka-manager. I will try to fix that first.

[UPDATE3] Nevermind... it was my fault. The image I ran on the server was not properly updated. It is working as expected with your tipps. Thank you very much!

dwu-zingbox commented 8 years ago

@hotstepper13 Glad you sorted it out. I also tried your idea and it worked fine for me. Only difference is that I broke the RUN command into two pieces and insert COPY command to use customized routes and application.conf file.

FROM centos:7

MAINTAINER Clement Laforet <sheepkiller@cultdeadsheep.org>

RUN yum update -y && \
    yum install -y git wget unzip which && \
    yum clean all

ENV JAVA_MAJOR=8 \
    JAVA_UPDATE=73 \
    JAVA_BUILD=02 

RUN wget -nv --no-cookies --no-check-certificate \
    --header "Cookie: oraclelicense=accept-securebackup-cookie" \
    "http://download.oracle.com/otn-pub/java/jdk/${JAVA_MAJOR}u${JAVA_UPDATE}-b${JAVA_BUILD}/jdk-${JAVA_MAJOR}u${JAVA_UPDATE}-linux-x64.rpm" -O /tmp/jdk-${JAVA_MAJOR}u${JAVA_UPDATE}-linux-x64.rpm && \
     yum localinstall -y /tmp/jdk-${JAVA_MAJOR}u${JAVA_UPDATE}-linux-x64.rpm && \
     rm -f /tmp/jdk-${JAVA_MAJOR}u${JAVA_UPDATE}-linux-x64.rpm

ENV JAVA_HOME=/usr/java/jdk1.8.0_${JAVA_UPDATE} \
#    ZK_HOSTS=localhost:2181 \
    KM_VERSION=1.3.0.7 \
    KM_REVISION=4b57fc9b65e6f9ac88fff4391994fd06bb782663 \
    KM_CONFIGFILE="conf/application.conf"

RUN mkdir -p /tmp && \
    cd /tmp && \
    git clone https://github.com/yahoo/kafka-manager && \
    cd /tmp/kafka-manager && \
    git checkout ${KM_REVISION} && \
    echo 'scalacOptions ++= Seq("-Xmax-classfile-name", "200")' >> build.sbt

COPY routes /tmp/kafka-manager/conf
COPY application.conf /tmp/kafka-manager/conf

RUN cd /tmp/kafka-manager && \
    ./sbt clean dist && \
    unzip  -d / ./target/universal/kafka-manager-${KM_VERSION}.zip && \
    rm -fr /tmp/* /root/.sbt /root/.ivy2 && \
    printf '#!/bin/sh\nexec ./bin/kafka-manager -Dconfig.file=${KM_CONFIGFILE} "${KM_ARGS}" "${@}"\n' > /kafka-manager-${KM_VERSION}/km.sh && \
    chmod +x /kafka-manager-${KM_VERSION}/km.sh

WORKDIR /kafka-manager-${KM_VERSION}

EXPOSE 9000
ENTRYPOINT ["./km.sh"]
patelh commented 8 years ago

This might be the answer : http://www.cakesolutions.net/teamblogs/all-you-need-to-know-about-plays-routing-dsl

gquintana commented 8 years ago

There is a play.http.context in Play 2.4 which seems dedicated to changing the base URL. However in KM it's not taken into account :'( , adding this to application.conffile doesn't help:

play.http.context="/kafka-manager/"

https://github.com/playframework/playframework/issues/4084

ashishsachdeva commented 7 years ago

Hi, I am struggling on the same thing. Though changing conf/routes works for cases where base url is static, my base url is kind of dynamic like /kafka-manager/ , where id is provided at run time that means i cannot compile the code everytime.

Is there anything I can do to unblock this situation.? @dwu-zingbox @hotstepper13

gquintana commented 7 years ago

This fixed since PR #249 you can configure context path with play.http.context config

ashishsachdeva commented 7 years ago

@gquintana I had tried that. I am running KM behind a proxy server which is reachable via curl call. When I add the relative path to above field, my call to access KM fails with:

java.net.MalformedURLException: unknown protocol: data

without that field, the curl call is succeeding but KM is not working. So I am kind of stuck. Is there any other setting I need to set.? Have you ever seen this behaviour? or can help me out on this?

gquintana commented 7 years ago

@ashishsachdeva To make myself clearer, with default configuration you can do:

curl http://localhost:9000/api/status/clusters

After setting in application.conf:

play.http.context = "/kafka-manager/"

you can do instead

http://localhost:9000/kafka-manager/api/status/clusters
ashishsachdeva commented 7 years ago

@gquintana I have understood this part.. what I am saying is, after changing this settings: play.http.context = "/kafka-manager/"

my curl call has started to throw exception: java.net.MalformedURLException: unknown protocol: data

thats where I am kind of stuck at and asking if there is any other setting or something I am missing.?

adamdecaf commented 6 years ago

I'm running into this on KM 1.3.3.14 (Play 2.4.6). I've tried the following, but nothing works. There are several requests still hitting the root path (example: /webjars/bootstrap/3.3.5/css/bootstrap.min.css).

cc https://github.com/playframework/playframework/issues/4084#issuecomment-199470315

adamdecaf commented 6 years ago

Got it working with -Dplay.http.context=/kafka-manager. I had a LB rewrite rule that was stripping off the /kafka-manager path when proxying.

cinhtau commented 6 years ago

@gquintana :+1: Works like a charm with adjusting play.http.context = "/kafka-manager/".