You are browsing a read-only backup copy of Wikitech. The live site can be found at wikitech.wikimedia.org

Apache Traffic Server: Difference between revisions

From Wikitech-static
Jump to navigation Jump to search
imported>Ema
imported>Ema
Line 6: Line 6:
<source lang="bash">
<source lang="bash">
# /etc/trafficserver/remap.config
# /etc/trafficserver/remap.config
map http://127.0.0.1:3128/ http://$origin_server_ip/
map client_url origin_server_url
reverse_map http://$origin_server_ip/ http://127.0.0.1:3128/
</source>
</source>


The following rule can be used as a catchall for mapping any request to a given origin server:
The following rules map grafana and phabricator to their respective backends and define a catchall for requests that don't match either of the first two rules:
<source lang="bash">
<source lang="bash">
# /etc/trafficserver/remap.config
# /etc/trafficserver/remap.config
map http://grafana.wikimedia.org/ http://krypton.eqiad.wmnet/
map http://phabricator.wikimedia.org/ http://iridium.eqiad.wmnet/
map / http://deployment-mediawiki05.deployment-prep.eqiad.wmflabs/
map / http://deployment-mediawiki05.deployment-prep.eqiad.wmflabs/
</source>
</source>
Line 21: Line 22:
CONFIG proxy.config.http.cache.required_headers INT 1
CONFIG proxy.config.http.cache.required_headers INT 1
CONFIG proxy.config.url_remap.pristine_host_hdr INT 1
CONFIG proxy.config.url_remap.pristine_host_hdr INT 1
CONFIG proxy.config.disable_configuration_modification INT 1
</source>
</source>


If [https://docs.trafficserver.apache.org/en/latest/admin-guide/files/records.config.en.html#proxy-config-http-cache-required-headers proxy.config.http.cache.required] is set to 2, which is the default, the origin server is required to set an explicit lifetime, from either '''Expires''' or '''Cache-Control: max-age'''. By setting '''required_headers''' to 1, objects with '''Last-Modified''' are considered for caching too. Setting the value to 0 means that no headers are required to make documents cachable.
If [https://docs.trafficserver.apache.org/en/latest/admin-guide/files/records.config.en.html#proxy-config-http-cache-required-headers proxy.config.http.cache.required] is set to 2, which is the default, the origin server is required to set an explicit lifetime, from either '''Expires''' or '''Cache-Control: max-age'''. By setting '''required_headers''' to 1, objects with '''Last-Modified''' are considered for caching too. Setting the value to 0 means that no headers are required to make documents cachable.
=== Health checks ===
Load the `healthchecks` plugin:
<source lang="bash">
# /etc/trafficserver/plugin.config
healthchecks.so /etc/trafficserver/healtchecks.conf
</source>
Define health check:
<source lang="bash">
# /etc/trafficserver/healtchecks.conf
/check /etc/trafficserver/ts-alive text/plain 200 403
</source>
Response body:
<source lang="bash">
# /etc/trafficserver/ts-alive
All good
</source>
With the above configuration, GET requests to `/check` will result in 200 responses from ATS with the response body defined in `/etc/trafficserver/ts-alive`.
=== systemd unit ===
<source lang="bash">
# /etc/systemd/system/trafficserver.service
[Unit]
Description=Apache Traffic Server
After=network.service systemd-networkd.service network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/traffic_cop
ExecReload=/usr/bin/traffic_ctl config reload
Restart=always
RestartSec=1
LimitNOFILE=500000
LimitMEMLOCK=90000
# PrivateTmp causes the following error:
# FATAL: unable to load remap.config
# traffic_server: using root directory '/usr'
#PrivateTmp=yes
CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_IPC_LOCK CAP_KILL CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID
SystemCallFilter=~acct modify_ldt add_key adjtimex clock_adjtime delete_module fanotify_init finit_module get_mempolicy init_module io_destroy io_getevents iopl ioperm io_setup io_submit io_cancel kcmp kexec_load keyctl lookup_dcookie mbind migrate_pages mount move_pages open_by_handle_at perf_event_open pivot_root process_vm_readv process_vm_writev ptrace remap_file_pages request_key set_mempolicy swapoff swapon umount2 uselib vmsplice
MemoryDenyWriteExecute=true
ReadOnlyDirectories=/usr
ReadOnlyDirectories=/var/lib
#
#ReadOnlyDirectories=/etc
#ReadWriteDirectories=/etc/trafficserver/internal
#ReadWriteDirectories=/etc/trafficserver/snapshots
</source>


== Cheatsheet ==
== Cheatsheet ==
Line 57: Line 115:
     end
     end
end
end
</source>
As another example, the following script takes care of setting the X-Cache-Int response header:
<source lang="lua">
-- /var/tmp/ats-set-x-cache-int.lua
function cache_lookup()
    local cache_status = ts.http.get_cache_lookup_status()
    ts.ctx['cstatus'] = cache_status
end
function cache_status_to_string(status)
    if status == TS_LUA_CACHE_LOOKUP_MISS then
        return "miss"
    end
    if status == TS_LUA_CACHE_LOOKUP_HIT_FRESH then
        return "hit"
    end
    if status == TS_LUA_CACHE_LOOKUP_HIT_STALE then
        return "miss"
    end
    if status == TS_LUA_CACHE_LOOKUP_SKIPPED then
        return "pass"
    end
    return "bug"
end
function gen_x_cache_int()
    local hostname = "cp4242" -- from puppet
    local cache_status = cache_status_to_string(ts.ctx['cstatus'])
    local v = ts.client_response.header['X-Cache-Int']
    local mine = hostname .. " " .. cache_status
    if (v) then
        v = v .. ", " .. mine
    else
        v = mine
    end
    ts.client_response.header['X-Cache-Int'] = v
    ts.client_response.header['X-Cache-Status'] = cache_status
end
function do_remap()
    ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup)
    ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, gen_x_cache_int)
    return 0
end
</source>
=== Unit testing ===
The '''busted''' framework allows to test Lua scripts. It can be installed as follows:
<source lang="bash">
apt install luarocks
luarocks install busted
luarocks install luacov
</source>
The following unit tests cover some of the functionalities implemented by '''ats-set-x-cache-int.lua''':
<source lang="lua">
-- unit_test.lua
_G.ts = { client_response = {  header = {} }, ctx = {} }
describe("Busted unit testing framework", function()
  describe("script for ATS Lua Plugin", function()
    it("test - hook", function()
      stub(ts, "hook")
      require("ats-set-x-cache-int")
      local result = do_remap()
      assert.are.equals(0, result)
    end)
    it("test - gen_x_cache_hit", function()
      stub(ts, "hook")
      require("ats-set-x-cache-int")
      local result = gen_x_cache_int()
      assert.are.equals('miss', ts.client_response.header['X-Cache-Status'])
      assert.are.equals('cp4242 miss', ts.client_response.header['X-Cache-Int'])
    end)
  end)
end)
</source>
Run the tests and generate a coverage report with:
<source lang="bash">
$ busted -c unit_test.lua
●●
2 successes / 0 failures / 0 errors / 0 pending : 0.012771 seconds
$ luacov ; cat luacov.report.out
</source>
</source>



Revision as of 17:17, 23 March 2017

Apache Traffic Server is a caching proxy server.

Basic configuration

The basic changes to the default configuration required to get a caching proxy are:

# /etc/trafficserver/remap.config
map client_url origin_server_url

The following rules map grafana and phabricator to their respective backends and define a catchall for requests that don't match either of the first two rules:

# /etc/trafficserver/remap.config
map http://grafana.wikimedia.org/ http://krypton.eqiad.wmnet/
map http://phabricator.wikimedia.org/ http://iridium.eqiad.wmnet/
map / http://deployment-mediawiki05.deployment-prep.eqiad.wmflabs/
# /etc/trafficserver/records.config
CONFIG proxy.config.http.server_ports STRING 3128 3128:ipv6
CONFIG proxy.config.http.cache.required_headers INT 1
CONFIG proxy.config.url_remap.pristine_host_hdr INT 1
CONFIG proxy.config.disable_configuration_modification INT 1

If proxy.config.http.cache.required is set to 2, which is the default, the origin server is required to set an explicit lifetime, from either Expires or Cache-Control: max-age. By setting required_headers to 1, objects with Last-Modified are considered for caching too. Setting the value to 0 means that no headers are required to make documents cachable.

Health checks

Load the `healthchecks` plugin:

# /etc/trafficserver/plugin.config
healthchecks.so /etc/trafficserver/healtchecks.conf

Define health check:

# /etc/trafficserver/healtchecks.conf
/check /etc/trafficserver/ts-alive text/plain 200 403

Response body:

# /etc/trafficserver/ts-alive
All good

With the above configuration, GET requests to `/check` will result in 200 responses from ATS with the response body defined in `/etc/trafficserver/ts-alive`.

systemd unit

# /etc/systemd/system/trafficserver.service
[Unit]
Description=Apache Traffic Server
After=network.service systemd-networkd.service network-online.target 

[Service]
Type=simple
ExecStart=/usr/bin/traffic_cop
ExecReload=/usr/bin/traffic_ctl config reload
Restart=always
RestartSec=1

LimitNOFILE=500000
LimitMEMLOCK=90000

# PrivateTmp causes the following error:
# FATAL: unable to load remap.config
# traffic_server: using root directory '/usr'
#PrivateTmp=yes

CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_IPC_LOCK CAP_KILL CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID
SystemCallFilter=~acct modify_ldt add_key adjtimex clock_adjtime delete_module fanotify_init finit_module get_mempolicy init_module io_destroy io_getevents iopl ioperm io_setup io_submit io_cancel kcmp kexec_load keyctl lookup_dcookie mbind migrate_pages mount move_pages open_by_handle_at perf_event_open pivot_root process_vm_readv process_vm_writev ptrace remap_file_pages request_key set_mempolicy swapoff swapon umount2 uselib vmsplice
MemoryDenyWriteExecute=true

ReadOnlyDirectories=/usr
ReadOnlyDirectories=/var/lib
#
#ReadOnlyDirectories=/etc
#ReadWriteDirectories=/etc/trafficserver/internal
#ReadWriteDirectories=/etc/trafficserver/snapshots

Cheatsheet

Show non-default configuration values:

sudo traffic_ctl config diff

Configuration reload:

sudo traffic_ctl config reload

Lua scripting

ATS plugins can be written in Lua. As an example, this is how to choose an origin server dynamically:

# /etc/trafficserver/remap.config
map http://127.0.0.1:3128/ http://$origin_server_ip/ @plugin=/usr/lib/trafficserver/modules/tslua.so @pparam=/var/tmp/ats-set-backend.lua
reverse_map http://$origin_server_ip/ http://127.0.0.1:3128/
-- /var/tmp/ats-set-backend.lua
function do_remap()
    url = ts.client_request.get_url()
    if url:match("/api/rest_v1/") then
        ts.client_request.set_url_host('origin-server.eqiad.wmnet')
        ts.client_request.set_url_port(80)
        ts.client_request.set_url_scheme('http')
        return TS_LUA_REMAP_DID_REMAP
    end
end

As another example, the following script takes care of setting the X-Cache-Int response header:

-- /var/tmp/ats-set-x-cache-int.lua
function cache_lookup()
     local cache_status = ts.http.get_cache_lookup_status()
     ts.ctx['cstatus'] = cache_status
end

function cache_status_to_string(status)
     if status == TS_LUA_CACHE_LOOKUP_MISS then
        return "miss"
     end

     if status == TS_LUA_CACHE_LOOKUP_HIT_FRESH then
        return "hit"
     end

     if status == TS_LUA_CACHE_LOOKUP_HIT_STALE then
        return "miss"
     end

     if status == TS_LUA_CACHE_LOOKUP_SKIPPED then
        return "pass"
     end

     return "bug"
end

function gen_x_cache_int()
     local hostname = "cp4242" -- from puppet
     local cache_status = cache_status_to_string(ts.ctx['cstatus'])

     local v = ts.client_response.header['X-Cache-Int']
     local mine = hostname .. " " .. cache_status

     if (v) then
        v = v .. ", " .. mine
     else
        v = mine
     end

     ts.client_response.header['X-Cache-Int'] = v
     ts.client_response.header['X-Cache-Status'] = cache_status
end

function do_remap()
     ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup)
     ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, gen_x_cache_int)
     return 0
end

Unit testing

The busted framework allows to test Lua scripts. It can be installed as follows:

apt install luarocks
luarocks install busted
luarocks install luacov

The following unit tests cover some of the functionalities implemented by ats-set-x-cache-int.lua:

-- unit_test.lua
_G.ts = { client_response = {  header = {} }, ctx = {} }

describe("Busted unit testing framework", function()
  describe("script for ATS Lua Plugin", function()

    it("test - hook", function()
      stub(ts, "hook")

      require("ats-set-x-cache-int")
      local result = do_remap()
      assert.are.equals(0, result)
    end)

    it("test - gen_x_cache_hit", function()
      stub(ts, "hook")

      require("ats-set-x-cache-int")
      local result = gen_x_cache_int()

      assert.are.equals('miss', ts.client_response.header['X-Cache-Status'])
      assert.are.equals('cp4242 miss', ts.client_response.header['X-Cache-Int'])
    end)

  end)
end)

Run the tests and generate a coverage report with:

$ busted -c unit_test.lua 
●●
2 successes / 0 failures / 0 errors / 0 pending : 0.012771 seconds

$ luacov ; cat luacov.report.out

External links