{"id":18403761,"url":"https://github.com/russellluo/caddy-mesh","last_synced_at":"2025-09-11T02:34:12.328Z","repository":{"id":59013260,"uuid":"529826549","full_name":"RussellLuo/caddy-mesh","owner":"RussellLuo","description":"Caddy service mesh based on the host/node architecture.","archived":false,"fork":false,"pushed_at":"2022-09-10T16:30:25.000Z","size":106,"stargazers_count":20,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-22T08:27:08.324Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RussellLuo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-28T10:14:59.000Z","updated_at":"2023-01-17T11:29:31.000Z","dependencies_parsed_at":"2022-09-10T23:10:32.969Z","dependency_job_id":null,"html_url":"https://github.com/RussellLuo/caddy-mesh","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/RussellLuo/caddy-mesh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fcaddy-mesh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fcaddy-mesh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fcaddy-mesh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fcaddy-mesh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RussellLuo","download_url":"https://codeload.github.com/RussellLuo/caddy-mesh/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RussellLuo%2Fcaddy-mesh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274568261,"owners_count":25309280,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-11T02:00:13.660Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T02:48:07.765Z","updated_at":"2025-09-11T02:34:12.279Z","avatar_url":"https://github.com/RussellLuo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Caddy Mesh\n\n[Caddy][1] service mesh based on [the host/node architecture][2].\n\n\n![architecture](docs/architecture.png)\n\n\n## Features\n\n- [x] [Timeouts](#timeouts)\n- [x] [Retries](#retries)\n- [ ] Circuit Breaking\n- [x] [Rate Limiting](#rate-limiting)\n- [x] [Traffic Splitting](#traffic-splitting)\n\n\n## Installation\n\n### Prerequisites\n\nBuild the image for Caddy Mesh controller:\n\n```console\n$ make build-image tag=v0.1.0\n```\n\nIf using any plugins, you need to build the Caddy image locally:\n\n```console\n$ make build-caddy-image tag=2.6.0-beta.3-custom\n```\n\n### Install the Helm Chart\n\n```console\n$ make helm-install\n```\n\n\n## Configuration\n\nAll features provided by Caddy Mesh can be enabled by using [annotations][3] on Kubernetes services.\n\n### Timeouts\n\nTimeouts can be enabled by using the following annotations:\n\n```\nmesh.caddyserver.com/timeout-dial-timeout: \"\u003cduration\u003e\"\nmesh.caddyserver.com/timeout-read-timeout: \"\u003cduration\u003e\"\nmesh.caddyserver.com/timeout-write-timeout: \"\u003cduration\u003e\"\n```\n\nParameters:\n\n- `timeout-dial-timeout`: How long to wait before timing out trying to connect to an upstream. Default: `3s`. (See [dial_timeout](https://caddyserver.com/docs/json/apps/http/servers/routes/handle/reverse_proxy/transport/http/dial_timeout/).)\n- `timeout-read-timeout`: The maximum time to wait for next read from backend. Default: no timeout. (Requires Caddy [v2.6.0-beta.3](https://github.com/caddyserver/caddy/releases/tag/v2.6.0-beta.3).)\n- `timeout-write-timeout`: The maximum time to wait for next write to backend. Default: no timeout. (Requires Caddy [v2.6.0-beta.3](https://github.com/caddyserver/caddy/releases/tag/v2.6.0-beta.3).)\n\n### Retries\n\nRetries can be enabled by using the following annotations:\n\n```\nmesh.caddyserver.com/retry-count: \"\u003ccount\u003e\"\nmesh.caddyserver.com/retry-duration: \"\u003cduration\u003e\"\nmesh.caddyserver.com/retry-on: \"\u003cexpression\u003e\"\n```\n\nParameters:\n\n- `retry-count`: How many times to retry selecting available backends for each request if the next available host is down. Default: disabled. (Requires Caddy [v2.6.0-beta.3](https://github.com/caddyserver/caddy/releases/tag/v2.6.0-beta.3).)\n    + If `retry-duration` is also configured, then retries may stop early if the duration is reached.\n- `retry-duration`: How long to try selecting available backends for each request if the next available host is down. Default: disabled. (See [try_duration](https://caddyserver.com/docs/json/apps/http/servers/routes/handle/reverse_proxy/load_balancing/try_duration/).)\n- `retry-on`: An [expression](https://caddyserver.com/docs/caddyfile/matchers#expression) matcher that restricts with which requests retries are allowed. Default: `\"\"`. (See [retry_match](https://caddyserver.com/docs/json/apps/http/servers/routes/handle/reverse_proxy/load_balancing/retry_match/).)\n    + If either `retry-count` or `retry-duration` is specified, `retry-on` will default to `\"true\"`.\n\n### Rate Limiting\n\nRate limiting can be enabled by using the following annotations:\n\n```\nmesh.caddyserver.com/rate-limit-key: \"\u003ckey\u003e\"\nmesh.caddyserver.com/rate-limit-rate: \"\u003crate\u003e\"\nmesh.caddyserver.com/rate-limit-zone-size: \"\u003czone_size\u003e\"\n```\n\nNote that this feature requires the [caddy-ext/ratelimit](https://github.com/RussellLuo/caddy-ext/tree/master/ratelimit) plugin.\n\n### Traffic Splitting\n\nTraffic splitting can be enabled by using the following annotations:\n\n```\nmesh.caddyserver.com/traffic-split-expression: \"\u003cexpression\u003e\"\nmesh.caddyserver.com/traffic-split-new-service: \"\u003cname\u003e\"\nmesh.caddyserver.com/traffic-split-old-service: \"\u003cname\u003e\"\n```\n\nParameters:\n\n- `traffic-split-expression`: An [expression](https://caddyserver.com/docs/caddyfile/matchers#expression) matcher that restricts with which requests will be redirected to the new service (or, if unmatched, to the old service). Default: `\"\"`.\n- `traffic-split-new-service`: The name of the new Kubernetes Service. Default: `\"\"`.\n- `traffic-split-old-service`: The name of the old Kubernetes Service. Default: `\"\"`.\n\n#### Workflow\n\n(This workflow is inspired by [SMI TrafficSplit][3].)\n\nIn this example workflow, the user has previously created the following resources:\n\n- Deployment named `server-v1`, with labels: `app: server` and `version: v1`.\n- Service named `server`, with a selector of `app: server`.\n- Service named `server-v1`, with selectors: `app: server` and `version: v1`.\n- Clients use the FQDN of `server` to communicate.\n    + To leverage Caddy Mesh, clients must use `server.test.caddy.mesh` (instead of `server.test.svc.cluster.local`).\n\nIn order to update an application, the user will perform the following actions:\n\n- Enable Traffic splitting on `server` (without redirecting traffic to `server-v2`).\n\n    ```diff\n    ---\n    kind: Service\n    apiVersion: v1\n    metadata:\n      name: server\n      namespace: test\n      labels:\n        app: server\n    + annotations:\n    +   mesh.caddyserver.com/traffic-split-expression: \"false\"\n    +   mesh.caddyserver.com/traffic-split-new-service: server-v2\n    +   mesh.caddyserver.com/traffic-split-old-service: server-v1\n    spec:\n      ...\n    ```\n  \n- Create a new deployment named `server-v2`, with labels: `app: server` and `version: v2`.\n- Create a new service named `server-v2`, with selectors: `app: server` and `version: v2`.\n- Once the deployment is healthy, spot check by sending manual requests to the `server-v2`.\n\nWhen ready, the user begins to redirect traffic to `server-v2`:\n\n- For example, the user first route Chrome consumers to `server-v2`:\n\n    ```diff\n    ---\n    kind: Service\n    apiVersion: v1\n    metadata:\n      name: server\n      namespace: test\n      labels:\n        app: server\n      annotations:\n    -   mesh.caddyserver.com/traffic-split-expression: \"false\"\n    +   mesh.caddyserver.com/traffic-split-expression: \"header({'User-Agent': '*Chrome*'})\"\n        mesh.caddyserver.com/traffic-split-new-service: server-v2\n        mesh.caddyserver.com/traffic-split-old-service: server-v1\n    spec:\n      ...\n    ```\n  \n- Verify health metrics and become comfortable with the new version.\n- The user decides to redirect all traffic to the new version:\n\n    ```diff\n    ---\n    kind: Service\n    apiVersion: v1\n    metadata:\n      name: server\n      namespace: test\n      labels:\n        app: server\n      annotations:\n    -   mesh.caddyserver.com/traffic-split-expression: \"header({'User-Agent': '*Chrome*'})\"\n    +   mesh.caddyserver.com/traffic-split-expression: \"true\"\n        mesh.caddyserver.com/traffic-split-new-service: server-v2\n        mesh.caddyserver.com/traffic-split-old-service: server-v1\n    spec:\n      ...\n    ```\n\nWhen completed, cleanup the old resources:\n\n- Delete the old `server-v1` deployment.\n- Delete the old `server-v1` service.\n- Remove the Traffic splitting annotations as it is no longer needed.\n\n\n[1]: https://caddyserver.com/\n[2]: https://traefik.io/glossary/service-mesh-101/\n[3]: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/\n[4]: https://github.com/servicemeshinterface/smi-spec/blob/main/apis/traffic-split/v1alpha4/traffic-split.md#workflow\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frussellluo%2Fcaddy-mesh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frussellluo%2Fcaddy-mesh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frussellluo%2Fcaddy-mesh/lists"}