Ysera
Assistant Engineer
Assistant Engineer
  • UID634
  • Fans0
  • Follows0
  • Posts44
Reads:40159Replies:0

Alibaba Cloud container service - custom routing and load balancing policies

Created#
More Posted time:Jan 4, 2017 17:33 PM
A simple example
Let's start with a simple example. We will deploy an acs/proxy container and configure an SLB instance at the front end for everybody to access. At the same time, an nginx server is mounted at the back-end. Here we only display the nginx homepage. The compose template is shown below:
lb:
    image:  registry.aliyuncs.com/acs/proxy:0.5
    ports:
            -  '80:80'
    restart:  always
    labels:
        # The add-on enables the proxy image with the subscription and registration center capability and to dynamically load service routers.
        aliyun.custom_addon:  "proxy"
        # Every VM is deployed with a container of this image.
        aliyun.global:  "true"
        #  Bind a SLB at the front end.
        aliyun.lb.port_80: tcp://proxy_test:80
    environment:
        #  The range of the back-end containers supporting router loading. “*” indicates the entire cluster. By default, it is the services in the application.
        ADDITIONAL_SERVICES:  "*"
appone:
    ports:
        -  80/tcp
        -  443/tcp
    image:  'nginx:latest'
    labels:
        #  Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.VIRTUAL_HOST:  "http://appone.example.com"
    restart:  always

After the service is successfully started, the page is as shown in the figure below:

Enable session persistence
lb:
    image:  registry.aliyuncs.com/acs/proxy:0.5
    ports:
            -  '80:80'
    restart:  always
    labels:
        # The add-on enables the proxy image with the subscription and registration center capability and to dynamically load service routers.
        aliyun.custom_addon:  "proxy"
        # Every VM is deployed with a container of this image.
        aliyun.global:  "true"
        #  Bind a SLB at the front end.
        aliyun.lb.port_80: tcp://proxy_test:80
    environment:
        #  The range of the back-end containers supporting router loading. “*” indicates the entire cluster. By default, it is the services in the application.
        ADDITIONAL_SERVICES:  "*"
appone:
    ports:
        -  80/tcp
        -  443/tcp
    image:  'nginx:latest'
    labels:
        #  Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.VIRTUAL_HOST:  "http://appone.example.com"
        # Here the session persistence is supported in the cookie approach. The key is CONTAINERID.
        aliyun.proxy.COOKIE: "CONTAINERID insert indirect"
    restart:  always


Customize 503 page
When we directly input the SLB's VIP address instead of the domain name, the accessed page is shown in the figure below. The 503 error page is returned.


We hope to add some prompts on the 503 page. Create a folder /errors on the VM where the container is located, and add the file /errors/503.http. The file content is as follows:
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html;charset=UTF-8

<html><body><h1>503 Service Unavailable</h1>

<h3>No server is available to handle this request.</h3>

<h3>If you see this page, it indicates that the server you are trying to access has some problems. Please troubleshoot the problem following the steps below:</h3>
<li>If you are a visitor to the app, please seek help from the app maintainer.</li>
<li>If you are the maintainer of the app, please proceed to read the following instructions.</li>
<li>You are now using a simple routing service. The request will go through SLB > acsrouting app container > your app container. Please troubleshoot the problem following the steps below.</li>
<li>Log in to the container service console. On the left side bar, select “Service”, and in the “Service List”, select the correct “Cluster”. Click the “Service” exposed to the internet to view the “Access Endpoint” of the service. Carefully check your access domain name to make sure it is consistent with the domain name you have configured in the corresponding service.</li>
<li>Locate and troubleshoot the problem following <a href="https://help.aliyun.com/knowledge_detail/42660.html">Simple Routing Service Link Troubleshooting</a>.</li>
<li>View <a href="https://help.aliyun.com/knowledge_detail/42658.html">Common Route Problems Document</a>.</li>
<li>If the problem persists after you perform the above measures, please <a href="https://workorder.console.aliyun.com/#/ticket/add?productId=1254">submit a ticket</a> to seek assistance from technical personnel. We will try our best to serve you.</li>
</body></html>

You can also edit it into the desired error page. The editing compose template is shown below:

lb:
    image:  registry.aliyuncs.com/acs/proxy:0.5
    ports:
            -  '80:80'
    restart:  always
    labels:
        # The add-on enables the proxy image with the subscription and registration center capability and to dynamically load service routers.
        aliyun.custom_addon:  "proxy"
        # Every VM is deployed with a container of this image.
        aliyun.global:  "true"
        #  Bind a SLB at the front end.
        aliyun.lb.port_80: tcp://proxy_test:80
    environment:
        #  The range of the back-end containers supporting router loading. “*” indicates the entire cluster. By default, it is the services in the application.
        ADDITIONAL_SERVICES:  "*"
        EXTRA_FRONTEND_SETTINGS_80: "errorfile 503 /usr/local/etc/haproxy/errors/503.http"
    volumes:
        - /errors/:/usr/local/etc/haproxy/errors/
appone:
    ports:
        -  80/tcp
        -  443/tcp
    image:  'nginx:latest'
    labels:
        #  Configure the URL to support the specified path. Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.VIRTUAL_HOST:  "http://appone.example.com"
    restart:  always

Input the SLB's VIP address, and the displayed 503 page is shown in the figure below:



Wildcard domain names supportedWe hope the back end of nginx can support wildcard domain names, that is, through appone.example.com we can access the nginx homepage, and through *.example.com, we can access the nginx homepage, too. To achieve this, you only need to edit the configuration as follows:
lb:
    image:  registry.aliyuncs.com/acs/proxy:0.5
    ports:
            -  '80:80'
    restart:  always
    labels:
        # The add-on enables the proxy image with the subscription and registration center capability and to dynamically load service routers.
        aliyun.custom_addon:  "proxy"
        # Every VM is deployed with a container of this image.
        aliyun.global:  "true"
        #  Bind a SLB at the front end.
        aliyun.lb.port_80: tcp://proxy_test:80
    environment:
        #  The range of the back-end containers supporting router loading. “*” indicates the entire cluster. By default, it is the services in the application.
        ADDITIONAL_SERVICES:  "*"
        EXTRA_FRONTEND_SETTINGS_80: "errorfile 503 /usr/local/etc/haproxy/errors/503.http"
    volumes:
        - /errors/:/usr/local/etc/haproxy/errors/
appone:
    ports:
        -  80/tcp
        -  443/tcp
    image:  'nginx:latest'
    labels:
        #  Configure the URL to support the specified path. Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.VIRTUAL_HOST:  "http://*.example.com"
    restart:  always


Bind the host, enter the domain name www.example.com and the nginx homepage is displayed as shown in the figure below:


Configure default back-end
Sometimes we want to access the nginx back-end through the IP address directly. To achieve this, you can remove the URL configuration, and edit the configuration as follows:
lb:
    image:  registry.aliyuncs.com/acs/proxy:0.5
    ports:
            -  '80:80'
    restart:  always
    labels:
        # The add-on enables the proxy image with the subscription and registration center capability and to dynamically load service routers.
        aliyun.custom_addon:  "proxy"
        # Every VM is deployed with a container of this image.
        aliyun.global:  "true"
        #  Bind a SLB at the front end.
        aliyun.lb.port_80: tcp://proxy_test:80
    environment:
        #  The range of the back-end containers supporting router loading. “*” indicates the entire cluster. By default, it is the services in the application.
        ADDITIONAL_SERVICES:  "*"

        # When 503 error is returned, specify the error page.
        EXTRA_FRONTEND_SETTINGS_80: "errorfile 503 /usr/local/etc/haproxy/errors/503.http"
    volumes:
        # Mount the error page from the host to inside the container.
        - /errors/:/usr/local/etc/haproxy/errors/
appone:
    ports:
        -  80/tcp
        -  443/tcp
    image:  'nginx:latest'
    labels:
        #  Configure the URL to support the specified path. Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.required: "true"
    restart:  always


Enter the SLB's VIP address and the nginx homepage is displayed as shown in the figure below:


Select the back-end through URL parameter values
Some users hope to use different back-ends based on different URL parameter values. The example below will access the appone service through http://www.example.com?backend=appone, that is, the nginx homepage, and access the apptwo service through http://www.example.com?backend=apptwo, that is, the hello world homepage. The application template code is shown as below:
lb:
    image:  registry.aliyuncs.com/acs/proxy:0.5
    ports:
            -  '80:80'
    restart:  always
    labels:
        # The add-on enables the proxy image with the subscription and registration center capability and to dynamically load service routers.
        aliyun.custom_addon:  "proxy"
        # Every VM is deployed with a container of this image.
        aliyun.global:  "true"
        #  Bind a SLB at the front end.
        aliyun.lb.port_80: tcp://proxy_test:80
    environment:
        #  The range of the back-end containers supporting router loading. “*” indicates the entire cluster. By default, it is the services in the application.
        ADDITIONAL_SERVICES:  "*"
        #  Obtain the back-end parameter values in the URL, and change the HOST header to the back-end domain name you want to match.
        EXTRA_FRONTEND_SETTINGS_80:  "  http-request set-header HOST %[urlp(backend)].example.com"
appone:
    ports:
        -  80/tcp
        -  443/tcp
    image:  'nginx:latest'
    labels:
        #  Configure the URL to support the specified path. Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.VIRTUAL_HOST:  "http://appone.example.com"
    restart:  always
apptwo:
    ports:
        -  80/tcp
    image:  'registry.cn-hangzhou.aliyuncs.com/linhuatest/hello-world:latest'
    labels:
        #  Configure the URL to support the specified path. Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.VIRTUAL_HOST:  "http://apptwo.example.com"
    restart:  always


Bind the host, and enter the link http://www.example.com?backend=appone to display the nginx homepage of the appone service, as shown below:


Bind the host and enter the link http://www.example.com?backend=apptwo to display the hello world homepage of the apptwo service, as shown below:

Record access logs
lb:
    image:  registry.aliyuncs.com/acs/proxy:0.5
    ports:
            -  '80:80'
    restart:  always
    labels:
        # The add-on enables the proxy image with the subscription and registration center capability and to dynamically load service routers.
        aliyun.custom_addon:  "proxy"
        # Every VM is deployed with a container of this image.
        aliyun.global:  "true"
        #  Bind a SLB at the front end.
        aliyun.lb.port_80: tcp://proxy_test:80
    environment:
        #  The range of the back-end containers supporting router loading. “*” indicates the entire cluster. By default, it is the services in the application.
        ADDITIONAL_SERVICES:  "*"
        EXTRA_DEFAULT_SETTINGS: "log rsyslog local0,log global,option httplog"
    links:
        - rsyslog:rsyslog
rsyslog:
    image: registry.cn-hangzhou.aliyuncs.com/linhuatest/rsyslog:latest
appone:
    ports:
        -  80/tcp
        -  443/tcp
    image:  'nginx:latest'
    labels:
        #  Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.VIRTUAL_HOST:  "http://appone.example.com"
    restart:  always


The logs will be printed into the standard output of the rsyslog container. You will be able to see the access logs of the custom routing through docker logs $rsyslog_container_name.
Inter-service load balancing
The template below creates a lb and an application service appone. They provide external services with the appone.example.com domain name as a whole.
lb:
    image:  registry.aliyuncs.com/acs/proxy:0.5
    Hostname:: proxy  # Specify the domain name of the service as proxy, that is, the proxy will be parsed to all containers deployed with this image.
    ports:
            -  '80:80'
    restart:  always
    labels:
        # The add-on enables the proxy image with the subscription and registration center capability and to dynamically load service routers.
        aliyun.custom_addon:  "proxy"
        # Every VM is deployed with a container of this image.
        aliyun.global:  "true"
        #  Bind a SLB at the front end.
        aliyun.lb.port_80: tcp://proxy_test:80
    environment:
        #  The range of the back-end containers supporting router loading. “*” indicates the entire cluster. By default, it is the services in the application.
        ADDITIONAL_SERVICES:  "*"
appone:
    ports:
        -  80/tcp
        -  443/tcp
    image:  'nginx:latest'
    labels:
        #  Here the HTTP/HTTPS/WS/WSS protocols are supported.
        aliyun.proxy.VIRTUAL_HOST:  "http://appone.example.com"
    restart:  always


The template below acts as a client to visit the appone application service. But its access path is by requesting access to the lb load balancing service and then being routed to the appone application service through reverse proxy.
restclient: # Simulate the rest service consumers.
  image: registry.aliyuncs.com/acs-sample/alpine:3.3
  command: "sh -c 'apk update; apk add curl; while true; do curl --head http://appone.example.com; sleep 1; done'" # Access the rest service to test the load balancing.
  tty: true  
  external_links:
    - "proxy:appone.example.com" # Specify the link service domain name and the alias of this domain name.


In the restclient service container, you will find the domain name of appone.example.com is parsed to all the container IP addresses of the lb load balancing service.
/ # drill appone.example.com
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 60917
;; flags: qr rd ra ; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; appone.example.com.  IN      A
;; ANSWER SECTION:
appone.example.com.     600     IN      A       172.18.3.4
appone.example.com.     600     IN      A       172.18.2.5
appone.example.com.     600     IN      A       172.18.1.5
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 0 msec
;; SERVER: 127.0.0.11
;; WHEN: Mon Sep 26 07:09:40 2016
;; MSG SIZE  rcvd: 138
Guest