Compare commits
350 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7f997c092 | ||
|
|
6f6af25467 | ||
|
|
a0f1638f6c | ||
|
|
fc13276f0e | ||
|
|
8a0b92db19 | ||
|
|
2f0d34adb2 | ||
|
|
617f416291 | ||
|
|
7a438ad323 | ||
|
|
5776f0b64b | ||
|
|
96d190a789 | ||
|
|
d2038699c0 | ||
|
|
cb3b5cba90 | ||
|
|
8c881ab758 | ||
|
|
caefaf73aa | ||
|
|
e8d7001f5e | ||
|
|
ae0f20a445 | ||
|
|
4ddc12185f | ||
|
|
e81627a96d | ||
|
|
47be2a25f2 | ||
|
|
6832a4ffde | ||
|
|
bd58a47862 | ||
|
|
613fb92a25 | ||
|
|
250d9f2836 | ||
|
|
0cab25e44c | ||
|
|
cbf6b462e4 | ||
|
|
8695660c58 | ||
|
|
1216990f52 | ||
|
|
204228bc8f | ||
|
|
ebc26e9ea0 | ||
|
|
3c03119d2d | ||
|
|
644049092f | ||
|
|
578f447728 | ||
|
|
3bf926e419 | ||
|
|
48ee4f8bd2 | ||
|
|
b4964a0535 | ||
|
|
47ff00e9b9 | ||
|
|
6ca99a5ddb | ||
|
|
30b5054692 | ||
|
|
edf7b90c11 | ||
|
|
7f0f97d14d | ||
|
|
b03b75cd7e | ||
|
|
f0d2e60a9a | ||
|
|
328f1d9ea2 | ||
|
|
a14013f393 | ||
|
|
aef1d7904d | ||
|
|
dc478188c1 | ||
|
|
9fa6e775c0 | ||
|
|
584350623b | ||
|
|
919959b32c | ||
|
|
ec54eedf93 | ||
|
|
f311797215 | ||
|
|
059b5d0f89 | ||
|
|
7542640494 | ||
|
|
52493f181a | ||
|
|
5d95143536 | ||
|
|
a2c5861ca5 | ||
|
|
fcc07f02b0 | ||
|
|
3f43526aac | ||
|
|
cd07da9137 | ||
|
|
30ab182b2e | ||
|
|
2ddd9587f7 | ||
|
|
50800857b6 | ||
|
|
8f50521435 | ||
|
|
45ecaa9084 | ||
|
|
9c7db58d87 | ||
|
|
6b11e9714b | ||
|
|
7f5a9ed34a | ||
|
|
bc9a231d26 | ||
|
|
0bb3815f73 | ||
|
|
944cc8ef62 | ||
|
|
e97334d7c1 | ||
|
|
2dacf08c30 | ||
|
|
6f6590774e | ||
|
|
fe5bb3fd26 | ||
|
|
c638edd346 | ||
|
|
c02477a245 | ||
|
|
da6da9c839 | ||
|
|
d83293776d | ||
|
|
d5994ac127 | ||
|
|
36584826bb | ||
|
|
7a6fccb70d | ||
|
|
ca1971c085 | ||
|
|
97eaecec48 | ||
|
|
01d47808a7 | ||
|
|
7d2f3dea7a | ||
|
|
bce1d02b3b | ||
|
|
9a993b131d | ||
|
|
636a1d7576 | ||
|
|
fb621ec465 | ||
|
|
00e993c686 | ||
|
|
374a55d8f5 | ||
|
|
1e88e2fa72 | ||
|
|
a2326198f6 | ||
|
|
a0031d626a | ||
|
|
a2b58d59ab | ||
|
|
e8b17406b7 | ||
|
|
5245045d84 | ||
|
|
b57d39369b | ||
|
|
db72fe3d97 | ||
|
|
3a2f688c56 | ||
|
|
13a2a5073f | ||
|
|
418853fd0c | ||
|
|
cfb68a6e56 | ||
|
|
88b13274d7 | ||
|
|
056ba675a7 | ||
|
|
873b74561c | ||
|
|
8b42ce374d | ||
|
|
4871003ff1 | ||
|
|
b4e7ad5575 | ||
|
|
1a246060e2 | ||
|
|
6a3d74c645 | ||
|
|
2073bd2027 | ||
|
|
c63554c534 | ||
|
|
be8ed8a696 | ||
|
|
98530d9968 | ||
|
|
38adc513a6 | ||
|
|
eb12e3bde1 | ||
|
|
8b2839d36e | ||
|
|
f0fa2aa6bb | ||
|
|
33528b073f | ||
|
|
cf8783ea37 | ||
|
|
00355635f8 | ||
|
|
aa485f4bf1 | ||
|
|
273b05fb24 | ||
|
|
e470474d6f | ||
|
|
ddfd2fe2ec | ||
|
|
7533d0ae99 | ||
|
|
04ec7f0388 | ||
|
|
419000cc13 | ||
|
|
0dc8edb437 | ||
|
|
0759b6531b | ||
|
|
d8f984de7d | ||
|
|
82e490a875 | ||
|
|
c6dffd9d3e | ||
|
|
8ee3d5835a | ||
|
|
1209d7e42b | ||
|
|
cdc05ba506 | ||
|
|
a6fae0195f | ||
|
|
11375b6890 | ||
|
|
3811470ebf | ||
|
|
e2b08eb4dc | ||
|
|
38d3ca1022 | ||
|
|
df459c5fe6 | ||
|
|
d1d9c0e2a9 | ||
|
|
c1b1d7d448 | ||
|
|
e6b5ee2042 | ||
|
|
0170fc6166 | ||
|
|
4cc2ada2a2 | ||
|
|
a5d3e4f6a6 | ||
|
|
7c92b33886 | ||
|
|
0f0b9414ae | ||
|
|
6fbb67ee8c | ||
|
|
6634f1a9ae | ||
|
|
8da8138f77 | ||
|
|
588f4c477b | ||
|
|
fda1775d3a | ||
|
|
fc71d53c71 | ||
|
|
ab2a320659 | ||
|
|
7f50f81ac7 | ||
|
|
c36a13ccff | ||
|
|
47de726345 | ||
|
|
7a4fdbddc0 | ||
|
|
0dc6f33550 | ||
|
|
b2436eb0df | ||
|
|
cc673159d7 | ||
|
|
17c310d66d | ||
|
|
e7357c4e07 | ||
|
|
c44de2d7c3 | ||
|
|
d82b2c219a | ||
|
|
35c8957a55 | ||
|
|
8555f8250a | ||
|
|
8137a25b13 | ||
|
|
2db5573c0e | ||
|
|
1e382203b8 | ||
|
|
873903a4cb | ||
|
|
e5b8afc085 | ||
|
|
ded658fed9 | ||
|
|
88d8858900 | ||
|
|
737c185aa6 | ||
|
|
0006a68740 | ||
|
|
4db91f7062 | ||
|
|
b8c23967b7 | ||
|
|
2019d048a4 | ||
|
|
fe0a4eb20c | ||
|
|
a35b0e8639 | ||
|
|
4c0843f92a | ||
|
|
867c1af897 | ||
|
|
100308289f | ||
|
|
3d4739760d | ||
|
|
9f321dd685 | ||
|
|
ba6078f235 | ||
|
|
cd2f1a24bd | ||
|
|
b87a81b798 | ||
|
|
0f9dd61786 | ||
|
|
4869a9f3ae | ||
|
|
cd6f36302d | ||
|
|
e5fdc7a57d | ||
|
|
834a601311 | ||
|
|
a2784c533e | ||
|
|
8e3ee3439c | ||
|
|
f9d40cfe1b | ||
|
|
b26b49fac2 | ||
|
|
f68d647fd0 | ||
|
|
deb3fb01a2 | ||
|
|
3accd23a19 | ||
|
|
6a66113560 | ||
|
|
6a7f7415fa | ||
|
|
4654f2cba9 | ||
|
|
17557dc206 | ||
|
|
39a3898234 | ||
|
|
9372cf9f18 | ||
|
|
41e427d645 | ||
|
|
84ff6f7e89 | ||
|
|
a286625ad9 | ||
|
|
d7999e6627 | ||
|
|
41481c1ca8 | ||
|
|
e926486b0f | ||
|
|
3ad55c9750 | ||
|
|
06c4151ec4 | ||
|
|
51605d9e04 | ||
|
|
438b558809 | ||
|
|
293c44b2a5 | ||
|
|
55de241f48 | ||
|
|
fda1d32dec | ||
|
|
b8d5295690 | ||
|
|
fdc8dd8795 | ||
|
|
99b3775926 | ||
|
|
f0f44c9d35 | ||
|
|
d7b878f980 | ||
|
|
d8c8b90a95 | ||
|
|
8be3d82ae9 | ||
|
|
fd778be943 | ||
|
|
51936bdc89 | ||
|
|
2935fad54d | ||
|
|
c9257bdb99 | ||
|
|
90a6ace666 | ||
|
|
5eb2b5211c | ||
|
|
2ed9ddcdf8 | ||
|
|
92f4be79ac | ||
|
|
593f450093 | ||
|
|
d20efe4509 | ||
|
|
fcac992e71 | ||
|
|
d59663810c | ||
|
|
37abdbb774 | ||
|
|
a5909682cd | ||
|
|
927b4324ae | ||
|
|
1ae72dafca | ||
|
|
392865ec59 | ||
|
|
3f1af1ec85 | ||
|
|
487432d873 | ||
|
|
a1ff44454a | ||
|
|
05b0557430 | ||
|
|
975b84a2eb | ||
|
|
3e845f1a29 | ||
|
|
49a266c207 | ||
|
|
7284e55eb0 | ||
|
|
b82fd5e5a5 | ||
|
|
4b084cf685 | ||
|
|
e6c740d917 | ||
|
|
cb93a9a158 | ||
|
|
3ea65ea1ad | ||
|
|
70d91bb399 | ||
|
|
f5fa18d7ca | ||
|
|
cb24c74769 | ||
|
|
775dc91ede | ||
|
|
ffef8ba4d9 | ||
|
|
ef2df0d7bc | ||
|
|
f0bf5219d4 | ||
|
|
c8a1165db2 | ||
|
|
e9c3518ce7 | ||
|
|
a5ea6587c0 | ||
|
|
2792835d66 | ||
|
|
16867db1b4 | ||
|
|
164bbb884d | ||
|
|
873141b9ca | ||
|
|
4a66a28c01 | ||
|
|
c886c1db62 | ||
|
|
f2d121a13b | ||
|
|
f255938780 | ||
|
|
aa17367de7 | ||
|
|
d5df6df661 | ||
|
|
ec6004963c | ||
|
|
61d272dbbc | ||
|
|
6be97b3fc7 | ||
|
|
6f95275051 | ||
|
|
49829fc80f | ||
|
|
9112c5a064 | ||
|
|
73c4833697 | ||
|
|
f3ca6266ab | ||
|
|
03acb869b7 | ||
|
|
8470d728f9 | ||
|
|
71965b199b | ||
|
|
fd47d385c2 | ||
|
|
dfdd8cffd7 | ||
|
|
138c42ec3a | ||
|
|
e53723c9c2 | ||
|
|
03be6a58ac | ||
|
|
864f362f7d | ||
|
|
bfb329b2f3 | ||
|
|
4ce65be0c6 | ||
|
|
6ab598d71b | ||
|
|
06b8ab4096 | ||
|
|
596bb6487c | ||
|
|
fa33a3e4bb | ||
|
|
abecb891dd | ||
|
|
fa14cebbf4 | ||
|
|
bde24d28b7 | ||
|
|
c0b400eb7c | ||
|
|
4772c91835 | ||
|
|
6da8d919b3 | ||
|
|
10b5504446 | ||
|
|
76b73a6319 | ||
|
|
0bebfbbb23 | ||
|
|
8cb147920b | ||
|
|
5cb343d89f | ||
|
|
67f34f1b29 | ||
|
|
349d781085 | ||
|
|
d7524414ce | ||
|
|
2e6cccaa90 | ||
|
|
565b99e210 | ||
|
|
5eb37b8f76 | ||
|
|
41cb713367 | ||
|
|
b29fe1f13b | ||
|
|
339780dcc4 | ||
|
|
56c77085bf | ||
|
|
118cac5941 | ||
|
|
7027f18394 | ||
|
|
99a85205f0 | ||
|
|
4b8d8718c2 | ||
|
|
0c4dd94e38 | ||
|
|
52cec59ca3 | ||
|
|
2c1ba42bcc | ||
|
|
6d204b52ce | ||
|
|
55c3745ef8 | ||
|
|
c876f879de | ||
|
|
f2beab1fdc | ||
|
|
85af1abb26 | ||
|
|
4f54901d08 | ||
|
|
98b10866bf | ||
|
|
ccf4dc55e9 | ||
|
|
8ce90e1814 | ||
|
|
2b6047d124 | ||
|
|
05e832ed55 | ||
|
|
45fddab9a9 | ||
|
|
34e9c0da6b | ||
|
|
9891375c20 | ||
|
|
377f145a3f | ||
|
|
6c7fff080f | ||
|
|
b1a168c5f2 | ||
|
|
d15df9ae88 |
50
.cosign/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Flagger signed releases
|
||||
|
||||
Flagger releases published to GitHub Container Registry as multi-arch container images
|
||||
are signed using [cosign](https://github.com/sigstore/cosign).
|
||||
|
||||
## Verify Flagger images
|
||||
|
||||
Install the [cosign](https://github.com/sigstore/cosign) CLI:
|
||||
|
||||
```sh
|
||||
brew install sigstore/tap/cosign
|
||||
```
|
||||
|
||||
Verify a Flagger release with cosign CLI:
|
||||
|
||||
```sh
|
||||
cosign verify -key https://raw.githubusercontent.com/fluxcd/flagger/main/cosign/cosign.pub \
|
||||
ghcr.io/fluxcd/flagger:1.13.0
|
||||
```
|
||||
|
||||
Verify Flagger images before they get pulled on your Kubernetes clusters with [Kyverno](https://github.com/kyverno/kyverno/):
|
||||
|
||||
```yaml
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: verify-flagger-image
|
||||
annotations:
|
||||
policies.kyverno.io/title: Verify Flagger Image
|
||||
policies.kyverno.io/category: Cosign
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/minversion: 1.4.2
|
||||
spec:
|
||||
validationFailureAction: enforce
|
||||
background: false
|
||||
rules:
|
||||
- name: verify-image
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- image: "ghcr.io/fluxcd/flagger:*"
|
||||
key: |-
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEST+BqQ1XZhhVYx0YWQjdUJYIG5Lt
|
||||
iz2+UxRIqmKBqNmce2T+l45qyqOs99qfD7gLNGmkVZ4vtJ9bM7FxChFczg==
|
||||
-----END PUBLIC KEY-----
|
||||
```
|
||||
11
.cosign/cosign.key
Normal file
@@ -0,0 +1,11 @@
|
||||
-----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
|
||||
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
|
||||
OCwicCI6MX0sInNhbHQiOiIvK1MwbTNrU3pGMFFXdVVYQkFoY2gvTDc3NVJBSy9O
|
||||
cnkzUC9iMkxBZGF3PSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
|
||||
Iiwibm9uY2UiOiJBNEFYL2IyU1BsMDBuY3JUNk45QkNOb0VLZTZLZEluRCJ9LCJj
|
||||
aXBoZXJ0ZXh0IjoiZ054UlJweXpraWtRMUVaRldsSnEvQXVUWTl0Vis2enBlWkIy
|
||||
dUFHREMzOVhUQlAwaWY5YStaZTE1V0NTT2FQZ01XQmtSZWhrQVVjQ3dZOGF2WTZa
|
||||
eFhZWWE3T1B4eFdidHJuSUVZM2hwZUk1M1dVQVZ6SXEzQjl0N0ZmV1JlVGsxdFlo
|
||||
b3hwQmxUSHY4U0c2azdPYk1aQnJleitzSGRWclF6YUdMdG12V1FOMTNZazRNb25i
|
||||
ZUpRSUJpUXFQTFg5NzFhSUlxU0dxYVhCanc9PSJ9
|
||||
-----END ENCRYPTED COSIGN PRIVATE KEY-----
|
||||
4
.cosign/cosign.pub
Normal file
@@ -0,0 +1,4 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEST+BqQ1XZhhVYx0YWQjdUJYIG5Lt
|
||||
iz2+UxRIqmKBqNmce2T+l45qyqOs99qfD7gLNGmkVZ4vtJ9bM7FxChFczg==
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -13,3 +13,5 @@ redirects:
|
||||
usage/skipper-progressive-delivery: tutorials/skipper-progressive-delivery.md
|
||||
usage/crossover-progressive-delivery: tutorials/crossover-progressive-delivery.md
|
||||
usage/traefik-progressive-delivery: tutorials/traefik-progressive-delivery.md
|
||||
usage/osm-progressive-delivery: tutorials/osm-progressive-delivery.md
|
||||
usage/kuma-progressive-delivery: tutorials/kuma-progressive-delivery.md
|
||||
|
||||
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve this project
|
||||
title: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Describe the bug
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
Please provide the Canary definition and Flagger logs.
|
||||
|
||||
### To Reproduce
|
||||
|
||||
<!--
|
||||
Steps to reproduce the behaviour
|
||||
-->
|
||||
|
||||
### Expected behavior
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
### Additional context
|
||||
|
||||
- Flagger version:
|
||||
- Kubernetes version:
|
||||
- Service Mesh provider:
|
||||
- Ingress provider:
|
||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
blank_issues_enabled: true
|
||||
|
||||
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: I have a suggestion (and may want to implement it 🙂)!
|
||||
title: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Describe the feature
|
||||
|
||||
What problem are you trying to solve?
|
||||
|
||||
### Proposed solution
|
||||
|
||||
What do you want to happen? Add any considered drawbacks.
|
||||
|
||||
### Any alternatives you've considered?
|
||||
|
||||
Is there another way to solve this problem that isn't as good a solution?
|
||||
5
.github/workflows/build.yaml
vendored
@@ -9,6 +9,9 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read # for actions/checkout to fetch code
|
||||
|
||||
jobs:
|
||||
container:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -25,7 +28,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.15.x
|
||||
go-version: 1.17.x
|
||||
- name: Download modules
|
||||
run: |
|
||||
go mod download
|
||||
|
||||
11
.github/workflows/e2e.yaml
vendored
@@ -9,14 +9,22 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read # for actions/checkout to fetch code
|
||||
|
||||
jobs:
|
||||
kind:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
provider:
|
||||
# service mesh
|
||||
- istio
|
||||
- linkerd
|
||||
- osm
|
||||
- kuma
|
||||
# ingress controllers
|
||||
- contour
|
||||
- nginx
|
||||
- traefik
|
||||
@@ -28,6 +36,9 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Kubernetes
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
with:
|
||||
version: "v0.11.1"
|
||||
image: kindest/node:v1.21.1@sha256:fae9a58f17f18f06aeac9772ca8b5ac680ebbed985e266f711d936e91d113bad
|
||||
- name: Build container image
|
||||
run: |
|
||||
docker build -t test/flagger:latest .
|
||||
|
||||
18
.github/workflows/helm.yaml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: helm
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write # needed to push chart
|
||||
|
||||
jobs:
|
||||
build-push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Publish Helm charts
|
||||
uses: stefanprodan/helm-gh-pages@v1.3.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
charts_url: https://flagger.app
|
||||
43
.github/workflows/push-ld.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
name: push-ld
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write # needed to write releases
|
||||
packages: write # needed for ghcr access
|
||||
|
||||
jobs:
|
||||
build-push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Prepare
|
||||
id: prep
|
||||
run: |
|
||||
VERSION=$(grep 'VERSION' cmd/loadtester/main.go | head -1 | awk '{ print $4 }' | tr -d '"')
|
||||
echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
echo ::set-output name=VERSION::${VERSION}
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
- name: Publish image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
file: ./Dockerfile.loadtester
|
||||
platforms: linux/amd64
|
||||
tags: |
|
||||
ghcr.io/fluxcd/flagger-loadtester:${{ steps.prep.outputs.VERSION }}
|
||||
- name: Check images
|
||||
run: |
|
||||
docker buildx imagetools inspect ghcr.io/fluxcd/flagger-loadtester:${{ steps.prep.outputs.VERSION }}
|
||||
61
.github/workflows/release.yml
vendored
@@ -4,34 +4,47 @@ on:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: write # needed to write releases
|
||||
id-token: write # needed for keyless signing
|
||||
packages: write # needed for ghcr access
|
||||
|
||||
env:
|
||||
IMAGE: "ghcr.io/fluxcd/${{ github.event.repository.name }}"
|
||||
|
||||
jobs:
|
||||
build-push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: sigstore/cosign-installer@main
|
||||
- name: Prepare
|
||||
id: prep
|
||||
run: |
|
||||
VERSION=$(grep 'VERSION' pkg/version/version.go | awk '{ print $4 }' | tr -d '"')
|
||||
CHANGELOG="https://github.com/fluxcd/flagger/blob/main/CHANGELOG.md#$(echo $VERSION | tr -d '.')"
|
||||
echo "[CHANGELOG](${CHANGELOG})" > notes.md
|
||||
echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
echo ::set-output name=VERSION::${VERSION}
|
||||
echo ::set-output name=CHANGELOG::${CHANGELOG}
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
buildkitd-flags: "--debug"
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
- name: Generate image meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: |
|
||||
${{ env.IMAGE }}
|
||||
tags: |
|
||||
type=raw,value=${{ steps.prep.outputs.VERSION }}
|
||||
- name: Publish image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
@@ -42,33 +55,31 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
build-args: |
|
||||
REVISON=${{ github.sha }}
|
||||
tags: |
|
||||
ghcr.io/fluxcd/flagger:${{ steps.prep.outputs.VERSION }}
|
||||
labels: |
|
||||
org.opencontainers.image.title=${{ github.event.repository.name }}
|
||||
org.opencontainers.image.description=${{ github.event.repository.description }}
|
||||
org.opencontainers.image.url=${{ github.event.repository.html_url }}
|
||||
org.opencontainers.image.source=${{ github.event.repository.html_url }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.version=${{ steps.prep.outputs.VERSION }}
|
||||
org.opencontainers.image.created=${{ steps.prep.outputs.BUILD_DATE }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
- name: Sign image
|
||||
run: |
|
||||
echo -n "${{secrets.COSIGN_PASSWORD}}" | \
|
||||
cosign sign -key ./.cosign/cosign.key -a git_sha=$GITHUB_SHA \
|
||||
${{ env.IMAGE }}:${{ steps.prep.outputs.VERSION }}
|
||||
- name: Check images
|
||||
run: |
|
||||
docker buildx imagetools inspect ghcr.io/fluxcd/flagger:${{ steps.prep.outputs.VERSION }}
|
||||
docker buildx imagetools inspect ${{ env.IMAGE }}:${{ steps.prep.outputs.VERSION }}
|
||||
- name: Verifiy image signature
|
||||
run: |
|
||||
cosign verify -key ./.cosign/cosign.pub \
|
||||
${{ env.IMAGE }}:${{ steps.prep.outputs.VERSION }}
|
||||
- name: Publish Helm charts
|
||||
uses: stefanprodan/helm-gh-pages@v1.3.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
charts_url: https://flagger.app
|
||||
linting: off
|
||||
- name: Create release
|
||||
uses: actions/create-release@latest
|
||||
- uses: anchore/sbom-action/download-syft@v0
|
||||
- name: Create release and SBOM
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
with:
|
||||
version: latest
|
||||
args: release --release-notes=notes.md --rm-dist --skip-validate
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: |
|
||||
[CHANGELOG](${{ steps.prep.outputs.CHANGELOG }})
|
||||
|
||||
41
.github/workflows/scan.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '18 10 * * 3'
|
||||
|
||||
permissions:
|
||||
contents: read # for actions/checkout to fetch code
|
||||
security-events: write # for codeQL to write security events
|
||||
|
||||
jobs:
|
||||
fossa:
|
||||
name: FOSSA
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run FOSSA scan and upload build data
|
||||
uses: fossa-contrib/fossa-action@v1
|
||||
with:
|
||||
# FOSSA Push-Only API Token
|
||||
fossa-api-key: 5ee8bf422db1471e0bcf2bcb289185de
|
||||
github-token: ${{ github.token }}
|
||||
|
||||
codeql:
|
||||
name: CodeQL
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: go
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -1,14 +1,17 @@
|
||||
project_name: flagger
|
||||
|
||||
builds:
|
||||
- main: ./cmd/flagger
|
||||
binary: flagger
|
||||
ldflags: -s -w -X github.com/fluxcd/flagger/pkg/version.REVISION={{.Commit}}
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
archives:
|
||||
- name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
files:
|
||||
- none*
|
||||
- skip: true
|
||||
|
||||
release:
|
||||
prerelease: auto
|
||||
|
||||
source:
|
||||
enabled: true
|
||||
name_template: "{{ .ProjectName }}_{{ .Version }}_source_code"
|
||||
|
||||
sboms:
|
||||
- id: source
|
||||
artifacts: source
|
||||
documents:
|
||||
- "{{ .ProjectName }}_{{ .Version }}_sbom.spdx.json"
|
||||
|
||||
401
CHANGELOG.md
@@ -2,6 +2,407 @@
|
||||
|
||||
All notable changes to this project are documented in this file.
|
||||
|
||||
## 1.17.0
|
||||
|
||||
**Release date:** 2022-01-11
|
||||
|
||||
This release comes with support for [Kuma Service Mesh](https://kuma.io/).
|
||||
For more details see the [Kuma Progressive Delivery tutorial](https://docs.flagger.app/tutorials/kuma-progressive-delivery).
|
||||
|
||||
To differentiate alerts based on the cluster name, you can configure Flagger with the `-cluster-name=my-cluster`
|
||||
command flag, or with Helm `--set clusterName=my-cluster`.
|
||||
|
||||
#### Features
|
||||
|
||||
- Add kuma support for progressive traffic shifting canaries
|
||||
[#1085](https://github.com/fluxcd/flagger/pull/1085)
|
||||
[#1093](https://github.com/fluxcd/flagger/pull/1093)
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Publish a Software Bill of Materials (SBOM)
|
||||
[#1094](https://github.com/fluxcd/flagger/pull/1094)
|
||||
- Add cluster name to flagger cmd args for altering
|
||||
[#1041](https://github.com/fluxcd/flagger/pull/1041)
|
||||
|
||||
## 1.16.1
|
||||
|
||||
**Release date:** 2021-12-17
|
||||
|
||||
This release contains updates to Kubernetes packages (1.23.0), Alpine (3.15)
|
||||
and load tester components.
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Release loadtester v0.21.0
|
||||
[#1083](https://github.com/fluxcd/flagger/pull/1083)
|
||||
- Add loadtester image pull secrets to Helm chart
|
||||
[#1076](https://github.com/fluxcd/flagger/pull/1076)
|
||||
- Update libraries included in the load tester to newer versions
|
||||
[#1063](https://github.com/fluxcd/flagger/pull/1063)
|
||||
[#1080](https://github.com/fluxcd/flagger/pull/1080)
|
||||
- Update Kubernetes packages to v1.23.0
|
||||
[#1078](https://github.com/fluxcd/flagger/pull/1078)
|
||||
- Update Alpine to 3.15
|
||||
[#1081](https://github.com/fluxcd/flagger/pull/1081)
|
||||
- Update Go to v1.17
|
||||
[#1077](https://github.com/fluxcd/flagger/pull/1077)
|
||||
|
||||
## 1.16.0
|
||||
|
||||
**Release date:** 2021-11-22
|
||||
|
||||
This release comes with a new API field called `primaryReadyThreshold`
|
||||
that allows setting the percentage of pods that need to be available
|
||||
to consider the primary deployment as ready.
|
||||
|
||||
#### Features
|
||||
|
||||
- Allow configuring threshold for primary
|
||||
[#1048](https://github.com/fluxcd/flagger/pull/1048)
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Append to list of ownerReferences for primary configmaps and secrets
|
||||
[#1052](https://github.com/fluxcd/flagger/pull/1052)
|
||||
- Prevent Flux from overriding Flagger managed objects
|
||||
[#1049](https://github.com/fluxcd/flagger/pull/1049)
|
||||
- Add warning in docs about ExternalDNS + Istio configuration
|
||||
[#1044](https://github.com/fluxcd/flagger/pull/1044)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Mark `CanaryMetric.Threshold` as omitempty
|
||||
[#1047](https://github.com/fluxcd/flagger/pull/1047)
|
||||
- Replace `ioutil` in testing of gchat
|
||||
[#1045](https://github.com/fluxcd/flagger/pull/1045)
|
||||
|
||||
## 1.15.0
|
||||
|
||||
**Release date:** 2021-10-28
|
||||
|
||||
This release comes with support for NGINX ingress canary metrics.
|
||||
The nginx-ingress minimum supported version is now v1.0.2.
|
||||
|
||||
Starting with version, Flagger will use the `spec.service.apex.annotations`
|
||||
to annotate the generated apex VirtualService, TrafficSplit or HTTPProxy.
|
||||
|
||||
#### Features
|
||||
|
||||
- Use nginx controller canary metrics
|
||||
[#1023](https://github.com/fluxcd/flagger/pull/1023)
|
||||
- Add metadata annotations to generated apex objects
|
||||
[#1034](https://github.com/fluxcd/flagger/pull/1034)
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Update load tester binaries (CVEs fix)
|
||||
[#1038](https://github.com/fluxcd/flagger/pull/1038)
|
||||
- Add podLabels to load tester Helm chart
|
||||
[#1036](https://github.com/fluxcd/flagger/pull/1036)
|
||||
|
||||
## 1.14.0
|
||||
|
||||
**Release date:** 2021-09-20
|
||||
|
||||
This release comes with support for extending the canary analysis with
|
||||
Dynatrace, InfluxDB and Google Cloud Monitoring (Stackdriver) metrics.
|
||||
|
||||
#### Features
|
||||
|
||||
- Add Stackdriver metric provider
|
||||
[#991](https://github.com/fluxcd/flagger/pull/991)
|
||||
- Add Influxdb metric provider
|
||||
[#1012](https://github.com/fluxcd/flagger/pull/1012)
|
||||
- Add Dynatrace metric provider
|
||||
[#1013](https://github.com/fluxcd/flagger/pull/1013)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Fix inline promql query
|
||||
[#1015](https://github.com/fluxcd/flagger/pull/1015)
|
||||
- Fix Istio load balancer settings mapping
|
||||
[#1016](https://github.com/fluxcd/flagger/pull/1016)
|
||||
|
||||
## 1.13.0
|
||||
|
||||
**Release date:** 2021-08-25
|
||||
|
||||
This release comes with support for [Open Service Mesh](https://openservicemesh.io).
|
||||
For more details see the [OSM Progressive Delivery tutorial](https://docs.flagger.app/tutorials/osm-progressive-delivery).
|
||||
|
||||
Starting with this version, Flagger container images are signed with
|
||||
[sigstore/cosign](https://github.com/sigstore/cosign), for more details see the
|
||||
[Flagger cosign docs](https://github.com/fluxcd/flagger/blob/main/.cosign/README.md).
|
||||
|
||||
#### Features
|
||||
|
||||
- Support OSM progressive traffic shifting in Flagger
|
||||
[#955](https://github.com/fluxcd/flagger/pull/955)
|
||||
[#977](https://github.com/fluxcd/flagger/pull/977)
|
||||
- Add support for Google Chat alerts
|
||||
[#953](https://github.com/fluxcd/flagger/pull/953)
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Sign Flagger container images with cosign
|
||||
[#983](https://github.com/fluxcd/flagger/pull/983)
|
||||
- Update Gloo APIs and e2e tests to Gloo v1.8.9
|
||||
[#982](https://github.com/fluxcd/flagger/pull/982)
|
||||
- Update e2e tests to Istio v1.11, Contour v1.18, Linkerd v2.10.2 and NGINX v0.49.0
|
||||
[#979](https://github.com/fluxcd/flagger/pull/979)
|
||||
- Update e2e tests to Traefik to 2.4.9
|
||||
[#960](https://github.com/fluxcd/flagger/pull/960)
|
||||
- Add support for volumes/volumeMounts in loadtester Helm chart
|
||||
[#975](https://github.com/fluxcd/flagger/pull/975)
|
||||
- Add extra podLabels options to Flagger Helm Chart
|
||||
[#966](https://github.com/fluxcd/flagger/pull/966)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Fix for the http client proxy overriding the default client
|
||||
[#943](https://github.com/fluxcd/flagger/pull/943)
|
||||
- Drop deprecated io/ioutil
|
||||
[#964](https://github.com/fluxcd/flagger/pull/964)
|
||||
- Remove problematic nulls from Grafana dashboard
|
||||
[#952](https://github.com/fluxcd/flagger/pull/952)
|
||||
|
||||
## 1.12.1
|
||||
|
||||
**Release date:** 2021-06-17
|
||||
|
||||
This release comes with a fix to Flagger when used with Flux v2.
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Update Go to v1.16 and Kubernetes packages to v1.21.1
|
||||
[#940](https://github.com/fluxcd/flagger/pull/940)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Remove the GitOps Toolkit metadata from generated objects
|
||||
[#939](https://github.com/fluxcd/flagger/pull/939)
|
||||
|
||||
## 1.12.0
|
||||
|
||||
**Release date:** 2021-06-16
|
||||
|
||||
This release comes with support for disabling the SSL certificate verification
|
||||
for the Prometheus and Graphite metric providers.
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Add `insecureSkipVerify` option for Prometheus and Graphite
|
||||
[#935](https://github.com/fluxcd/flagger/pull/935)
|
||||
- Copy labels from Gloo upstreams
|
||||
[#932](https://github.com/fluxcd/flagger/pull/932)
|
||||
- Improve language and correct typos in FAQs docs
|
||||
[#925](https://github.com/fluxcd/flagger/pull/925)
|
||||
- Remove Flux GC markers from generated objects
|
||||
[#936](https://github.com/fluxcd/flagger/pull/936)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Require SMI TrafficSplit Service and Weight
|
||||
[#878](https://github.com/fluxcd/flagger/pull/878)
|
||||
|
||||
## 1.11.0
|
||||
|
||||
**Release date:** 2021-06-01
|
||||
|
||||
**Breaking change:** the minimum supported version of Kubernetes is v1.19.0.
|
||||
|
||||
This release comes with support for Kubernetes Ingress `networking.k8s.io/v1`.
|
||||
The Ingress from `networking.k8s.io/v1beta1` is no longer supported,
|
||||
affected integrations: **NGINX** and **Skipper** ingress controllers.
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Upgrade Ingress to networking.k8s.io/v1
|
||||
[#917](https://github.com/fluxcd/flagger/pull/917)
|
||||
- Update Kubernetes manifests to rbac.authorization.k8s.io/v1
|
||||
[#920](https://github.com/fluxcd/flagger/pull/920)
|
||||
|
||||
## 1.10.0
|
||||
|
||||
**Release date:** 2021-05-28
|
||||
|
||||
This release comes with support for [Graphite](https://docs.flagger.app/usage/metrics#graphite) metric templates.
|
||||
|
||||
#### Features
|
||||
|
||||
- Add Graphite metrics provider
|
||||
[#915](https://github.com/fluxcd/flagger/pull/915)
|
||||
|
||||
#### Improvements
|
||||
|
||||
- ConfigTracker: Scan envFrom in init-containers
|
||||
[#914](https://github.com/fluxcd/flagger/pull/914)
|
||||
- e2e: Update Istio to v1.10 and Contour to v1.15
|
||||
[#914](https://github.com/fluxcd/flagger/pull/914)
|
||||
|
||||
## 1.9.0
|
||||
|
||||
**Release date:** 2021-05-14
|
||||
|
||||
This release comes with improvements to the [Gloo Edge](https://docs.flagger.app/tutorials/gloo-progressive-delivery) integration.
|
||||
|
||||
Starting with this version, Flagger no longer requires Gloo discovery to be enabled.
|
||||
Flagger generated the Gloo upstream objects on its own and optionally it can use an
|
||||
existing upstream (specified with `.spec.upstreamRef`) as a template.
|
||||
|
||||
#### Features
|
||||
|
||||
- Gloo: Create gloo upstreams from non-discovered services
|
||||
[#894](https://github.com/fluxcd/flagger/pull/894)
|
||||
- Gloo Upstream Ref for Upstream Config
|
||||
[#908](https://github.com/fluxcd/flagger/pull/908)
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Adjusted Nginx ingress canary headers on init and promotion
|
||||
[#907](https://github.com/fluxcd/flagger/pull/907)
|
||||
|
||||
## 1.8.0
|
||||
|
||||
**Release date:** 2021-04-29
|
||||
|
||||
This release comes with support for the SMI `v1alpha2` and `v1alpha3` TrafficSplit APIs.
|
||||
|
||||
For SMI compatible service mesh solutions like Open Service Mesh, Consul Connect or Nginx Service Mesh,
|
||||
[Prometheus MetricTemplates](https://docs.flagger.app/usage/metrics#prometheus) can be used to implement
|
||||
the request success rate and request duration checks.
|
||||
|
||||
The desired SMI version can be set in the Canary object:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: my-canary
|
||||
spec:
|
||||
provider: "smi:v1alpha3" # or "smi:v1alpha2"
|
||||
```
|
||||
|
||||
#### Features
|
||||
|
||||
- Implement SMI v1alpha2 and v1alpha3 routers
|
||||
[#896](https://github.com/fluxcd/flagger/pull/896)
|
||||
[#879](https://github.com/fluxcd/flagger/pull/879)
|
||||
- Add alerting HTTP/S proxy option
|
||||
[#872](https://github.com/fluxcd/flagger/pull/872)
|
||||
- Add option to mute alerts generated from webhooks
|
||||
[#887](https://github.com/fluxcd/flagger/pull/887)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Scale up canary on confirm rollout
|
||||
[#878](https://github.com/fluxcd/flagger/pull/878)
|
||||
|
||||
## 1.7.0
|
||||
|
||||
**Release date:** 2021-03-23
|
||||
|
||||
This release comes with support for manually approving
|
||||
the traffic weight increase.
|
||||
|
||||
#### Features
|
||||
|
||||
- Add webhook for manually approving traffic weight increase
|
||||
[#849](https://github.com/fluxcd/flagger/pull/849)
|
||||
- Add WaitingPromotion phase to canary status
|
||||
[#859](https://github.com/fluxcd/flagger/pull/859)
|
||||
|
||||
#### Improvements
|
||||
|
||||
- linkerd: update prometheus URL based on the latest 2.10 changes
|
||||
[#845](https://github.com/fluxcd/flagger/pull/845)
|
||||
- docs: update resources to disable mTLS in Istio
|
||||
[#843](https://github.com/fluxcd/flagger/pull/843)
|
||||
- docs: updating slack alerting docs to point to legacy slack webhooks
|
||||
[#833](https://github.com/fluxcd/flagger/pull/833)
|
||||
- chart: Add pull secret for Prometheus deployment
|
||||
[#842](https://github.com/fluxcd/flagger/pull/842)
|
||||
- Update Kubernetes packages to v1.20.4
|
||||
[#857](https://github.com/fluxcd/flagger/pull/857)
|
||||
|
||||
## 1.6.4
|
||||
|
||||
**Release date:** 2021-02-26
|
||||
|
||||
This release comes with a bug fix to the AppMesh integration
|
||||
when using multiple backends.
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Consolidate logos and add project name logos
|
||||
[#829](https://github.com/fluxcd/flagger/pull/829)
|
||||
- chart: add env option to loadtester
|
||||
[#821](https://github.com/fluxcd/flagger/pull/821)
|
||||
- chart: Added PodDisruptionBudget for the loadtester
|
||||
[#819](https://github.com/fluxcd/flagger/pull/819)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Fix AWS AppMesh issue when providing multiple backends
|
||||
[#831](https://github.com/fluxcd/flagger/pull/831)
|
||||
|
||||
## 1.6.3
|
||||
|
||||
**Release date:** 2021-02-15
|
||||
|
||||
This release comes with support for Kubernetes pod topology spread constraints.
|
||||
|
||||
Flagger has a new [logo](https://github.com/fluxcd/flagger/pull/812),
|
||||
many thanks to [Bianca](https://github.com/bia) for designed it.
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Rewrite the primary Pod Topology Spread Constraints based on label selector
|
||||
[#806](https://github.com/fluxcd/flagger/pull/806)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Suffix only the podAntiAffinity values that match the deployment name
|
||||
[#805](https://github.com/fluxcd/flagger/pull/805)
|
||||
- Check if mandatory secrets/configmaps exist
|
||||
[#799](https://github.com/fluxcd/flagger/pull/799)
|
||||
|
||||
## 1.6.2
|
||||
|
||||
**Release date:** 2021-01-28
|
||||
|
||||
This release comes with support for Kubernetes anti-affinity rules.
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Support for adding `-primary` suffix to Anti-Affinity values
|
||||
[#788](https://github.com/fluxcd/flagger/pull/788)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Add missing alerts section to Canary CRD schema
|
||||
[#794](https://github.com/fluxcd/flagger/pull/794)
|
||||
|
||||
## 1.6.1
|
||||
|
||||
**Release date:** 2021-01-19
|
||||
|
||||
This release extends the support for Istio's `HTTPMatchRequest` and
|
||||
comes with a regression bug fix to secrets and configmaps tracking.
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Update HTTPMatchRequest to match Istio's definitions
|
||||
[#777](https://github.com/fluxcd/flagger/pull/777)
|
||||
- e2e: Update Istio to v1.8.2 and Contour to v1.11.0
|
||||
[#778](https://github.com/fluxcd/flagger/pull/778)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Add missing TrackedConfig field to Canary status CRD
|
||||
[#781](https://github.com/fluxcd/flagger/pull/781)
|
||||
|
||||
## 1.6.0
|
||||
|
||||
**Release date:** 2021-01-05
|
||||
|
||||
@@ -29,7 +29,7 @@ you can sign your commit automatically with `git commit -s`.
|
||||
|
||||
The project uses Slack: To join the conversation, simply join the
|
||||
[CNCF](https://slack.cncf.io/) Slack workspace and use the
|
||||
[#flux](https://cloud-native.slack.com/messages/flux/) channel.
|
||||
[#flagger](https://cloud-native.slack.com/messages/flagger/) channel.
|
||||
|
||||
The developers use a mailing list to discuss development as well.
|
||||
Simply subscribe to [flux-dev on cncf.io](https://lists.cncf.io/g/cncf-flux-dev)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.15-alpine as builder
|
||||
FROM golang:1.17-alpine as builder
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
ARG REVISON
|
||||
@@ -21,7 +21,7 @@ RUN CGO_ENABLED=0 go build \
|
||||
-ldflags "-s -w -X github.com/fluxcd/flagger/pkg/version.REVISION=${REVISON}" \
|
||||
-a -o flagger ./cmd/flagger
|
||||
|
||||
FROM alpine:3.12
|
||||
FROM alpine:3.15
|
||||
|
||||
RUN apk --no-cache add ca-certificates
|
||||
|
||||
|
||||
@@ -1,40 +1,57 @@
|
||||
FROM alpine:3.11 as build
|
||||
FROM alpine:3.15.0 as build
|
||||
|
||||
RUN apk --no-cache add alpine-sdk perl curl
|
||||
|
||||
RUN curl -sSLo hey "https://storage.googleapis.com/hey-release/hey_linux_amd64" && \
|
||||
RUN curl -sSLo hey "https://hey-release.s3.us-east-2.amazonaws.com/hey_linux_amd64" && \
|
||||
chmod +x hey && mv hey /usr/local/bin/hey
|
||||
|
||||
RUN HELM2_VERSION=2.16.8 && \
|
||||
RUN HELM2_VERSION=2.17.0 && \
|
||||
curl -sSL "https://get.helm.sh/helm-v${HELM2_VERSION}-linux-amd64.tar.gz" | tar xvz && \
|
||||
chmod +x linux-amd64/helm && mv linux-amd64/helm /usr/local/bin/helm && \
|
||||
chmod +x linux-amd64/tiller && mv linux-amd64/tiller /usr/local/bin/tiller
|
||||
|
||||
RUN HELM3_VERSION=3.2.3 && \
|
||||
RUN HELM3_VERSION=3.7.2 && \
|
||||
curl -sSL "https://get.helm.sh/helm-v${HELM3_VERSION}-linux-amd64.tar.gz" | tar xvz && \
|
||||
chmod +x linux-amd64/helm && mv linux-amd64/helm /usr/local/bin/helmv3
|
||||
|
||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.3.1 && \
|
||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.4.6 && \
|
||||
wget -qO /usr/local/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||
chmod +x /usr/local/bin/grpc_health_probe
|
||||
|
||||
RUN GHZ_VERSION=0.39.0 && \
|
||||
curl -sSL "https://github.com/bojand/ghz/releases/download/v${GHZ_VERSION}/ghz_${GHZ_VERSION}_Linux_x86_64.tar.gz" | tar xz -C /tmp && \
|
||||
RUN GHZ_VERSION=0.105.0 && \
|
||||
curl -sSL "https://github.com/bojand/ghz/releases/download/v${GHZ_VERSION}/ghz-linux-x86_64.tar.gz" | tar xz -C /tmp && \
|
||||
mv /tmp/ghz /usr/local/bin && chmod +x /usr/local/bin/ghz
|
||||
|
||||
RUN HELM_TILLER_VERSION=0.9.3 && \
|
||||
curl -sSL "https://github.com/rimusz/helm-tiller/archive/v${HELM_TILLER_VERSION}.tar.gz" | tar xz -C /tmp && \
|
||||
mv /tmp/helm-tiller-${HELM_TILLER_VERSION} /tmp/helm-tiller
|
||||
|
||||
RUN WRK_VERSION=4.0.2 && \
|
||||
cd /tmp && git clone -b ${WRK_VERSION} https://github.com/wg/wrk
|
||||
RUN cd /tmp/wrk && make
|
||||
FROM golang:1.17-alpine as go
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
ARG REVISON
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
# copy modules manifests
|
||||
COPY go.mod go.mod
|
||||
COPY go.sum go.sum
|
||||
|
||||
# cache modules
|
||||
RUN go mod download
|
||||
|
||||
# copy source code
|
||||
COPY cmd/ cmd/
|
||||
COPY pkg/ pkg/
|
||||
|
||||
# build
|
||||
RUN CGO_ENABLED=0 go build -o loadtester ./cmd/loadtester/*
|
||||
|
||||
FROM bash:5.0
|
||||
|
||||
RUN addgroup -S app && \
|
||||
adduser -S -g app app && \
|
||||
apk --no-cache add ca-certificates curl jq libgcc
|
||||
apk --no-cache add ca-certificates curl jq libgcc wrk
|
||||
|
||||
WORKDIR /home/app
|
||||
|
||||
@@ -42,7 +59,6 @@ COPY --from=bats/bats:v1.1.0 /opt/bats/ /opt/bats/
|
||||
RUN ln -s /opt/bats/bin/bats /usr/local/bin/
|
||||
|
||||
COPY --from=build /usr/local/bin/hey /usr/local/bin/
|
||||
COPY --from=build /tmp/wrk/wrk /usr/local/bin/
|
||||
COPY --from=build /usr/local/bin/helm /usr/local/bin/
|
||||
COPY --from=build /usr/local/bin/tiller /usr/local/bin/
|
||||
COPY --from=build /usr/local/bin/ghz /usr/local/bin/
|
||||
@@ -52,8 +68,6 @@ COPY --from=build /tmp/helm-tiller /tmp/helm-tiller
|
||||
|
||||
ADD https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/health/v1/health.proto /tmp/ghz/health.proto
|
||||
|
||||
COPY ./bin/loadtester .
|
||||
|
||||
RUN chown -R app:app ./
|
||||
RUN chown -R app:app /tmp/ghz
|
||||
|
||||
@@ -64,6 +78,8 @@ RUN hey -n 1 -c 1 https://flagger.app > /dev/null && echo $? | grep 0
|
||||
RUN wrk -d 1s -c 1 -t 1 https://flagger.app > /dev/null && echo $? | grep 0
|
||||
|
||||
# install Helm v2 plugins
|
||||
RUN helm init --client-only && helm plugin install /tmp/helm-tiller
|
||||
RUN helm init --stable-repo-url=https://charts.helm.sh/stable --client-only && helm plugin install /tmp/helm-tiller
|
||||
|
||||
COPY --from=go --chown=app:app /workspace/loadtester .
|
||||
|
||||
ENTRYPOINT ["./loadtester"]
|
||||
|
||||
10
MAINTAINERS
@@ -1,6 +1,8 @@
|
||||
The maintainers are generally available in Slack at
|
||||
https://weave-community.slack.com/messages/flagger/ (obtain an invitation
|
||||
at https://slack.weave.works/).
|
||||
https://cloud-native.slack.com/messages/flagger/ (obtain an invitation
|
||||
at https://slack.cncf.io/).
|
||||
|
||||
Stefan Prodan, Weaveworks <stefan@weave.works> (Slack: @stefan Twitter: @stefanprodan)
|
||||
Takeshi Yoneda, DMM.com <cz.rk.t0415y.g@gmail.com> (Slack: @mathetake Twitter: @mathetake)
|
||||
In alphabetical order:
|
||||
|
||||
Stefan Prodan, Weaveworks <stefan@weave.works> (github: @stefanprodan, slack: stefanprodan)
|
||||
Takeshi Yoneda, Tetrate <takeshi@tetrate.io> (github: @mathetake, slack: mathetake)
|
||||
|
||||
14
Makefile
@@ -6,6 +6,7 @@ build:
|
||||
CGO_ENABLED=0 go build -a -o ./bin/flagger ./cmd/flagger
|
||||
|
||||
fmt:
|
||||
go mod tidy
|
||||
gofmt -l -s -w ./
|
||||
goimports -l -w ./
|
||||
|
||||
@@ -29,12 +30,12 @@ crd:
|
||||
version-set:
|
||||
@next="$(TAG)" && \
|
||||
current="$(VERSION)" && \
|
||||
sed -i '' "s/$$current/$$next/g" pkg/version/version.go && \
|
||||
sed -i '' "s/flagger:$$current/flagger:$$next/g" artifacts/flagger/deployment.yaml && \
|
||||
sed -i '' "s/tag: $$current/tag: $$next/g" charts/flagger/values.yaml && \
|
||||
sed -i '' "s/appVersion: $$current/appVersion: $$next/g" charts/flagger/Chart.yaml && \
|
||||
sed -i '' "s/version: $$current/version: $$next/g" charts/flagger/Chart.yaml && \
|
||||
sed -i '' "s/newTag: $$current/newTag: $$next/g" kustomize/base/flagger/kustomization.yaml && \
|
||||
sed -i "s/$$current/$$next/g" pkg/version/version.go && \
|
||||
sed -i "s/flagger:$$current/flagger:$$next/g" artifacts/flagger/deployment.yaml && \
|
||||
sed -i "s/tag: $$current/tag: $$next/g" charts/flagger/values.yaml && \
|
||||
sed -i "s/appVersion: $$current/appVersion: $$next/g" charts/flagger/Chart.yaml && \
|
||||
sed -i "s/version: $$current/version: $$next/g" charts/flagger/Chart.yaml && \
|
||||
sed -i "s/newTag: $$current/newTag: $$next/g" kustomize/base/flagger/kustomization.yaml && \
|
||||
echo "Version $$next set in code, deployment, chart and kustomize"
|
||||
|
||||
release:
|
||||
@@ -42,7 +43,6 @@ release:
|
||||
git push origin "v$(VERSION)"
|
||||
|
||||
loadtester-build:
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o ./bin/loadtester ./cmd/loadtester/*
|
||||
docker build -t ghcr.io/fluxcd/flagger-loadtester:$(LT_VERSION) . -f Dockerfile.loadtester
|
||||
|
||||
loadtester-push:
|
||||
|
||||
87
README.md
@@ -1,5 +1,6 @@
|
||||
# flagger
|
||||
# flagger
|
||||
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4783)
|
||||
[](https://github.com/fluxcd/flagger/actions)
|
||||
[](https://goreportcard.com/report/github.com/fluxcd/flagger)
|
||||
[](https://github.com/fluxcd/flagger/blob/main/LICENSE)
|
||||
@@ -9,12 +10,16 @@ Flagger is a progressive delivery tool that automates the release process for ap
|
||||
It reduces the risk of introducing a new software version in production
|
||||
by gradually shifting traffic to the new version while measuring metrics and running conformance tests.
|
||||
|
||||

|
||||

|
||||
|
||||
Flagger implements several deployment strategies (Canary releases, A/B testing, Blue/Green mirroring)
|
||||
using a service mesh (App Mesh, Istio, Linkerd) or an ingress controller (Contour, Gloo, NGINX, Skipper, Traefik) for traffic routing.
|
||||
For release analysis, Flagger can query Prometheus, Datadog or CloudWatch
|
||||
and for alerting it uses Slack, MS Teams, Discord and Rocket.
|
||||
using a service mesh (App Mesh, Istio, Linkerd, Open Service Mesh, Kuma)
|
||||
or an ingress controller (Contour, Gloo, NGINX, Skipper, Traefik) for traffic routing.
|
||||
For release analysis, Flagger can query Prometheus, Datadog, New Relic, CloudWatch, Dynatrace,
|
||||
InfluxDB and Stackdriver and for alerting it uses Slack, MS Teams, Discord, Rocket and Google Chat.
|
||||
|
||||
Flagger is a [Cloud Native Computing Foundation](https://cncf.io/) project
|
||||
and part of [Flux](https://fluxcd.io) family of GitOps tools.
|
||||
|
||||
### Documentation
|
||||
|
||||
@@ -33,6 +38,8 @@ Flagger documentation can be found at [docs.flagger.app](https://docs.flagger.ap
|
||||
* [App Mesh](https://docs.flagger.app/tutorials/appmesh-progressive-delivery)
|
||||
* [Istio](https://docs.flagger.app/tutorials/istio-progressive-delivery)
|
||||
* [Linkerd](https://docs.flagger.app/tutorials/linkerd-progressive-delivery)
|
||||
* [Open Service Mesh (OSM)](https://docs.flagger.app/tutorials/osm-progressive-delivery)
|
||||
* [Kuma Service Mesh](https://docs.flagger.app/tutorials/kuma-progressive-delivery)
|
||||
* [Contour](https://docs.flagger.app/tutorials/contour-progressive-delivery)
|
||||
* [Gloo](https://docs.flagger.app/tutorials/gloo-progressive-delivery)
|
||||
* [NGINX Ingress](https://docs.flagger.app/tutorials/nginx-progressive-delivery)
|
||||
@@ -42,17 +49,9 @@ Flagger documentation can be found at [docs.flagger.app](https://docs.flagger.ap
|
||||
|
||||
### Who is using Flagger
|
||||
|
||||
List of organizations using Flagger:
|
||||
**Our list of production users has moved to <https://fluxcd.io/adopters/#flagger>**.
|
||||
|
||||
* [Chick-fil-A](https://www.chick-fil-a.com)
|
||||
* [Capra Consulting](https://www.capraconsulting.no)
|
||||
* [DMM.com](https://dmm-corp.com)
|
||||
* [MediaMarktSaturn](https://www.mediamarktsaturn.com)
|
||||
* [Weaveworks](https://weave.works)
|
||||
* [Jumia Group](https://group.jumia.com)
|
||||
* [eLife](https://elifesciences.org/)
|
||||
|
||||
If you are using Flagger, please submit a PR to add your organization to the list!
|
||||
If you are using Flagger, please [submit a PR to add your organization](https://github.com/fluxcd/website/tree/main/adopters#readme) to the list!
|
||||
|
||||
### Canary CRD
|
||||
|
||||
@@ -73,7 +72,8 @@ metadata:
|
||||
namespace: test
|
||||
spec:
|
||||
# service mesh provider (optional)
|
||||
# can be: kubernetes, istio, linkerd, appmesh, nginx, skipper, contour, gloo, supergloo, traefik
|
||||
# can be: kubernetes, istio, linkerd, appmesh, nginx, skipper, contour, gloo, supergloo, traefik, osm
|
||||
# for SMI TrafficSplit can be: smi:v1alpha1, smi:v1alpha2, smi:v1alpha3
|
||||
provider: istio
|
||||
# deployment reference
|
||||
targetRef:
|
||||
@@ -184,30 +184,34 @@ For more details on how the canary analysis and promotion works please [read the
|
||||
|
||||
**Service Mesh**
|
||||
|
||||
| Feature | App Mesh | Istio | Linkerd | Kubernetes CNI |
|
||||
| ------------------------------------------ | ------------------ | ------------------ | ------------------ | ----------------- |
|
||||
| Canary deployments (weighted traffic) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
||||
| A/B testing (headers and cookies routing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Blue/Green deployments (traffic switch) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Blue/Green deployments (traffic mirroring) | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Webhooks (acceptance/load testing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Manual gating (approve/pause/resume) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request success rate check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
||||
| Request duration check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
||||
| Custom metric checks | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Feature | App Mesh | Istio | Linkerd | Kuma | OSM | SMI | Kubernetes CNI |
|
||||
|--------------------------------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|
|
||||
| Canary deployments (weighted traffic) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: |
|
||||
| A/B testing (headers and cookies routing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Blue/Green deployments (traffic switch) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Blue/Green deployments (traffic mirroring) | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Webhooks (acceptance/load testing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Manual gating (approve/pause/resume) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request success rate check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Request duration check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Custom metric checks | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
|
||||
For other SMI compatible service mesh solutions like Consul Connect or Nginx Service Mesh,
|
||||
[Prometheus MetricTemplates](https://docs.flagger.app/usage/metrics#prometheus) can be used to implement
|
||||
the request success rate and request duration checks.
|
||||
|
||||
**Ingress**
|
||||
|
||||
| Feature | Contour | Gloo | NGINX | Skipper | Traefik |
|
||||
| ------------------------------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ |
|
||||
| Canary deployments (weighted traffic) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| A/B testing (headers and cookies routing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Blue/Green deployments (traffic switch) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Webhooks (acceptance/load testing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Manual gating (approve/pause/resume) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request success rate check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request duration check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Custom metric checks | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Feature | Contour | Gloo | NGINX | Skipper | Traefik |
|
||||
|-------------------------------------------|--------------------|--------------------|--------------------|--------------------|--------------------|
|
||||
| Canary deployments (weighted traffic) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| A/B testing (headers and cookies routing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: |
|
||||
| Blue/Green deployments (traffic switch) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Webhooks (acceptance/load testing) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Manual gating (approve/pause/resume) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request success rate check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Request duration check (L7 metric) | :heavy_check_mark: | :heavy_check_mark: | :heavy_minus_sign: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Custom metric checks | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
|
||||
### Roadmap
|
||||
|
||||
@@ -221,7 +225,6 @@ For more details on how the canary analysis and promotion works please [read the
|
||||
#### Integrations
|
||||
|
||||
* Add support for Kubernetes [Ingress v2](https://github.com/kubernetes-sigs/service-apis)
|
||||
* Add support for SMI compatible service mesh solutions like Open Service Mesh and Consul Connect
|
||||
* Add support for ingress controllers like HAProxy and ALB
|
||||
* Add support for metrics providers like InfluxDB, Stackdriver, SignalFX
|
||||
|
||||
@@ -243,10 +246,10 @@ When submitting bug reports please include as much details as possible:
|
||||
If you have any questions about Flagger and progressive delivery:
|
||||
|
||||
* Read the Flagger [docs](https://docs.flagger.app).
|
||||
* Invite yourself to the [Weave community slack](https://slack.weave.works/)
|
||||
and join the [#flagger](https://weave-community.slack.com/messages/flagger/) channel.
|
||||
* Join the [Weave User Group](https://www.meetup.com/pro/Weave/) and get invited to online talks,
|
||||
hands-on training and meetups in your area.
|
||||
* Invite yourself to the [CNCF community slack](https://slack.cncf.io/)
|
||||
and join the [#flagger](https://cloud-native.slack.com/messages/flagger/) channel.
|
||||
* Check out the **[Flux events calendar](https://fluxcd.io/#calendar)**, both with upcoming talks, events and meetings you can attend.
|
||||
* Or view the **[Flux resources section](https://fluxcd.io/resources)** with past events videos you can watch.
|
||||
* File an [issue](https://github.com/fluxcd/flagger/issues/new).
|
||||
|
||||
Your feedback is always welcome!
|
||||
|
||||
50
artifacts/examples/kuma-canary.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
annotations:
|
||||
kuma.io/mesh: default
|
||||
spec:
|
||||
targetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
progressDeadlineSeconds: 60
|
||||
service:
|
||||
port: 9898
|
||||
targetPort: 9898
|
||||
apex:
|
||||
annotations:
|
||||
9898.service.kuma.io/protocol: "http"
|
||||
canary:
|
||||
annotations:
|
||||
9898.service.kuma.io/protocol: "http"
|
||||
primary:
|
||||
annotations:
|
||||
9898.service.kuma.io/protocol: "http"
|
||||
analysis:
|
||||
interval: 15s
|
||||
threshold: 15
|
||||
maxWeight: 50
|
||||
stepWeight: 10
|
||||
metrics:
|
||||
- name: request-success-rate
|
||||
threshold: 99
|
||||
interval: 1m
|
||||
- name: request-duration
|
||||
threshold: 500
|
||||
interval: 30s
|
||||
webhooks:
|
||||
- name: acceptance-test
|
||||
type: pre-rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
timeout: 30s
|
||||
metadata:
|
||||
type: bash
|
||||
cmd: "curl -sd 'test' http://podinfo-canary.test:9898/token | grep token"
|
||||
- name: load-test
|
||||
type: rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
metadata:
|
||||
cmd: "hey -z 2m -q 10 -c 2 http://podinfo-canary.test:9898/"
|
||||
42
artifacts/examples/osm-canary-steps.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
spec:
|
||||
provider: osm
|
||||
targetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
progressDeadlineSeconds: 600
|
||||
service:
|
||||
port: 9898
|
||||
targetPort: 9898
|
||||
analysis:
|
||||
interval: 15s
|
||||
threshold: 10
|
||||
stepWeights: [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]
|
||||
metrics:
|
||||
- name: request-success-rate
|
||||
thresholdRange:
|
||||
min: 99
|
||||
interval: 1m
|
||||
- name: request-duration
|
||||
thresholdRange:
|
||||
max: 500
|
||||
interval: 30s
|
||||
webhooks:
|
||||
- name: acceptance-test
|
||||
type: pre-rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
timeout: 15s
|
||||
metadata:
|
||||
type: bash
|
||||
cmd: "curl -sd 'test' http://podinfo-canary.test:9898/token | grep token"
|
||||
- name: load-test
|
||||
type: rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
timeout: 5s
|
||||
metadata:
|
||||
cmd: "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/"
|
||||
43
artifacts/examples/osm-canary.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
spec:
|
||||
provider: osm
|
||||
targetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
progressDeadlineSeconds: 600
|
||||
service:
|
||||
port: 9898
|
||||
targetPort: 9898
|
||||
analysis:
|
||||
interval: 15s
|
||||
threshold: 10
|
||||
maxWeight: 50
|
||||
stepWeight: 5
|
||||
metrics:
|
||||
- name: request-success-rate
|
||||
thresholdRange:
|
||||
min: 99
|
||||
interval: 1m
|
||||
- name: request-duration
|
||||
thresholdRange:
|
||||
max: 500
|
||||
interval: 30s
|
||||
webhooks:
|
||||
- name: acceptance-test
|
||||
type: pre-rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
timeout: 15s
|
||||
metadata:
|
||||
type: bash
|
||||
cmd: "curl -sd 'test' http://podinfo-canary.test:9898/token | grep token"
|
||||
- name: load-test
|
||||
type: rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
timeout: 5s
|
||||
metadata:
|
||||
cmd: "hey -z 1m -q 10 -c 2 http://podinfo-canary.test:9898/"
|
||||
@@ -6,7 +6,7 @@ metadata:
|
||||
labels:
|
||||
app: flagger
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: flagger
|
||||
@@ -192,7 +192,7 @@ rules:
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: flagger
|
||||
|
||||
@@ -129,6 +129,21 @@ spec:
|
||||
- Ingress
|
||||
name:
|
||||
type: string
|
||||
upstreamRef:
|
||||
description: Gloo Upstream selector
|
||||
type: object
|
||||
required: [ "apiVersion", "kind", "name" ]
|
||||
properties:
|
||||
apiVersion:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
enum:
|
||||
- Upstream
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
service:
|
||||
description: Kubernetes Service spec
|
||||
type: object
|
||||
@@ -172,15 +187,23 @@ spec:
|
||||
description: URI match conditions
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
uri:
|
||||
type: object
|
||||
authority:
|
||||
oneOf:
|
||||
- required: ["exact"]
|
||||
- required: ["prefix"]
|
||||
- required: ["suffix"]
|
||||
- required: ["regex"]
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
@@ -188,12 +211,223 @@ spec:
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
suffix:
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
gateways:
|
||||
description:
|
||||
Names of gateways where the rule should be
|
||||
applied.
|
||||
items:
|
||||
format: string
|
||||
type: string
|
||||
type: array
|
||||
headers:
|
||||
additionalProperties:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
ignoreUriCase:
|
||||
description:
|
||||
Flag to specify whether the URI matching should
|
||||
be case-insensitive.
|
||||
type: boolean
|
||||
method:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
description: The name assigned to a match.
|
||||
format: string
|
||||
type: string
|
||||
port:
|
||||
description:
|
||||
Specifies the ports on the host that is being
|
||||
addressed.
|
||||
type: integer
|
||||
queryParams:
|
||||
additionalProperties:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
description: Query parameters for matching.
|
||||
type: object
|
||||
scheme:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
sourceLabels:
|
||||
additionalProperties:
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
sourceNamespace:
|
||||
description:
|
||||
Source namespace constraining the applicability
|
||||
of a rule to workloads in that namespace.
|
||||
format: string
|
||||
type: string
|
||||
uri:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
withoutHeaders:
|
||||
additionalProperties:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
description:
|
||||
withoutHeader has the same syntax with the
|
||||
header, but has opposite meaning.
|
||||
type: object
|
||||
type: object
|
||||
retries:
|
||||
description: Retry policy for HTTP requests
|
||||
type: object
|
||||
@@ -592,6 +826,9 @@ spec:
|
||||
mirrorWeight:
|
||||
description: Weight of traffic to be mirrored
|
||||
type: number
|
||||
primaryReadyThreshold:
|
||||
description: Percentage of pods that need to be available to consider primary as ready
|
||||
type: number
|
||||
match:
|
||||
description: A/B testing match conditions
|
||||
type: array
|
||||
@@ -668,6 +905,37 @@ spec:
|
||||
namespace:
|
||||
description: Namespace of this metric template
|
||||
type: string
|
||||
alerts:
|
||||
description: Alert list for this canary analysis
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- providerRef
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
description: Name of the this alert
|
||||
type: string
|
||||
severity:
|
||||
description: Severity level can be info, warn, error (default info)
|
||||
type: string
|
||||
enum:
|
||||
- ""
|
||||
- info
|
||||
- warn
|
||||
- error
|
||||
providerRef:
|
||||
description: Alert provider reference
|
||||
type: object
|
||||
required: ["name"]
|
||||
properties:
|
||||
name:
|
||||
description: Name of the alert provider
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace of the alert provider
|
||||
type: string
|
||||
webhooks:
|
||||
description: Webhook list for this canary
|
||||
type: array
|
||||
@@ -690,6 +958,10 @@ spec:
|
||||
- post-rollout
|
||||
- event
|
||||
- rollback
|
||||
- confirm-traffic-increase
|
||||
muteAlert:
|
||||
description: Mute all alerts for the webhook
|
||||
type: boolean
|
||||
url:
|
||||
description: URL address of this webhook
|
||||
type: string
|
||||
@@ -716,12 +988,18 @@ spec:
|
||||
- Initialized
|
||||
- Waiting
|
||||
- Progressing
|
||||
- WaitingPromotion
|
||||
- Promoting
|
||||
- Finalising
|
||||
- Succeeded
|
||||
- Failed
|
||||
- Terminating
|
||||
- Terminated
|
||||
trackedConfigs:
|
||||
description: TrackedConfig of this canary
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
canaryWeight:
|
||||
description: Traffic weight routed to canary
|
||||
type: number
|
||||
@@ -829,8 +1107,11 @@ spec:
|
||||
- prometheus
|
||||
- influxdb
|
||||
- datadog
|
||||
- stackdriver
|
||||
- cloudwatch
|
||||
- newrelic
|
||||
- graphite
|
||||
- dynatrace
|
||||
address:
|
||||
description: API address of this provider
|
||||
type: string
|
||||
@@ -846,6 +1127,9 @@ spec:
|
||||
region:
|
||||
description: Region of the provider
|
||||
type: string
|
||||
insecureSkipVerify:
|
||||
description: Disable SSL certificate validation for the provider address
|
||||
type: boolean
|
||||
query:
|
||||
description: Query of this metric template
|
||||
type: string
|
||||
@@ -912,9 +1196,19 @@ spec:
|
||||
- msteams
|
||||
- discord
|
||||
- rocket
|
||||
- gchat
|
||||
channel:
|
||||
description: Alert channel for this provider
|
||||
type: string
|
||||
username:
|
||||
description: Bot username for this provider
|
||||
type: string
|
||||
address:
|
||||
description: Hook URL address of this provider
|
||||
type: string
|
||||
proxy:
|
||||
description: Http/s proxy of this provider
|
||||
type: string
|
||||
secretRef:
|
||||
description: Kubernetes secret reference containing the provider address
|
||||
type: object
|
||||
|
||||
@@ -22,7 +22,7 @@ spec:
|
||||
serviceAccountName: flagger
|
||||
containers:
|
||||
- name: flagger
|
||||
image: ghcr.io/fluxcd/flagger:1.6.0
|
||||
image: ghcr.io/fluxcd/flagger:1.17.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
apiVersion: v1
|
||||
name: flagger
|
||||
version: 1.6.0
|
||||
appVersion: 1.6.0
|
||||
version: 1.17.0
|
||||
appVersion: 1.17.0
|
||||
kubeVersion: ">=1.16.0-0"
|
||||
engine: gotpl
|
||||
description: Flagger is a progressive delivery operator for Kubernetes
|
||||
home: https://flagger.app
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flagger/main/docs/logo/weaveworks.png
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flagger/main/docs/logo/flagger-icon.png
|
||||
sources:
|
||||
- https://github.com/fluxcd/flagger
|
||||
maintainers:
|
||||
@@ -21,5 +21,8 @@ keywords:
|
||||
- gloo
|
||||
- contour
|
||||
- nginx
|
||||
- traefik
|
||||
- osm
|
||||
- smi
|
||||
- gitops
|
||||
- canary
|
||||
|
||||
@@ -7,10 +7,13 @@ Flagger can run automated application analysis, testing, promotion and rollback
|
||||
* A/B Testing (HTTP headers and cookies traffic routing)
|
||||
* Blue/Green (traffic switching and mirroring)
|
||||
|
||||
Flagger works with service mesh solutions (Istio, Linkerd, AWS App Mesh) and with Kubernetes ingress controllers
|
||||
Flagger works with service mesh solutions (Istio, Linkerd, AWS App Mesh, Open Service Mesh) and with Kubernetes ingress controllers
|
||||
(NGINX, Skipper, Gloo, Contour, Traefik).
|
||||
Flagger can be configured to send alerts to various chat platforms such as Slack, Microsoft Teams, Discord and Rocket.
|
||||
|
||||
Flagger is a [Cloud Native Computing Foundation](https://cncf.io/) project
|
||||
and part of [Flux](https://fluxcd.io) family of GitOps tools.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* Kubernetes >= 1.16
|
||||
@@ -38,13 +41,13 @@ $ helm upgrade -i flagger flagger/flagger \
|
||||
--set metricsServer=http://prometheus:9090
|
||||
```
|
||||
|
||||
To install Flagger for **Linkerd**:
|
||||
To install Flagger for **Linkerd** (requires Linkerd Viz extension):
|
||||
|
||||
```console
|
||||
$ helm upgrade -i flagger flagger/flagger \
|
||||
--namespace=linkerd \
|
||||
--set meshProvider=linkerd \
|
||||
--set metricsServer=http://linkerd-prometheus:9090
|
||||
--set metricsServer=http://prometheus.linkerd-viz:9090
|
||||
```
|
||||
|
||||
To install Flagger for **AWS App Mesh**:
|
||||
@@ -56,6 +59,25 @@ $ helm upgrade -i flagger flagger/flagger \
|
||||
--set metricsServer=http://appmesh-prometheus:9090
|
||||
```
|
||||
|
||||
|
||||
To install Flagger for **Open Service Mesh** (requires OSM to have been installed with Prometheus):
|
||||
|
||||
```console
|
||||
$ helm upgrade -i flagger flagger/flagger \
|
||||
--namespace=osm-system \
|
||||
--set meshProvider=osm \
|
||||
--set metricsServer=http://osm-prometheus.osm-system.svc:7070
|
||||
```
|
||||
|
||||
To install Flagger for **Kuma Service Mesh** (requires Kuma to have been installed with Prometheus):
|
||||
|
||||
```console
|
||||
$ helm upgrade -i flagger flagger/flagger \
|
||||
--namespace=kuma-system \
|
||||
--set meshProvider=kuma \
|
||||
--set metricsServer=http://prometheus-server.kuma-metrics:80
|
||||
```
|
||||
|
||||
To install Flagger and Prometheus for **NGINX** Ingress (requires controller metrics enabled):
|
||||
|
||||
```console
|
||||
@@ -65,7 +87,7 @@ $ helm upgrade -i flagger flagger/flagger \
|
||||
--set prometheus.install=true
|
||||
```
|
||||
|
||||
To install Flagger and Prometheus for **Gloo** (requires Gloo discovery enabled):
|
||||
To install Flagger and Prometheus for **Gloo** (no longer requires Gloo discovery):
|
||||
|
||||
```console
|
||||
$ helm upgrade -i flagger flagger/flagger \
|
||||
@@ -109,51 +131,54 @@ The command removes all the Kubernetes components associated with the chart and
|
||||
|
||||
The following tables lists the configurable parameters of the Flagger chart and their default values.
|
||||
|
||||
Parameter | Description | Default
|
||||
--- | --- | ---
|
||||
`image.repository` | Image repository | `ghcr.io/fluxcd/flagger`
|
||||
`image.tag` | Image tag | `<VERSION>`
|
||||
`image.pullPolicy` | Image pull policy | `IfNotPresent`
|
||||
`logLevel` | Log level | `info`
|
||||
`metricsServer` | Prometheus URL, used when `prometheus.install` is `false` | `http://prometheus.istio-system:9090`
|
||||
`prometheus.install` | If `true`, installs Prometheus configured to scrape all pods in the custer | `false`
|
||||
`prometheus.retention` | Prometheus data retention | `2h`
|
||||
`selectorLabels` | List of labels that Flagger uses to create pod selectors | `app,name,app.kubernetes.io/name`
|
||||
`configTracking.enabled` | If `true`, flagger will track changes in Secrets and ConfigMaps referenced in the target deployment | `true`
|
||||
`eventWebhook` | If set, Flagger will publish events to the given webhook | None
|
||||
`slack.url` | Slack incoming webhook | None
|
||||
`slack.channel` | Slack channel | None
|
||||
`slack.user` | Slack username | `flagger`
|
||||
`msteams.url` | Microsoft Teams incoming webhook | None
|
||||
`podMonitor.enabled` | If `true`, create a PodMonitor for [monitoring the metrics](https://docs.flagger.app/usage/monitoring#metrics) | `false`
|
||||
`podMonitor.namespace` | Namespace where the PodMonitor is created | the same namespace
|
||||
`podMonitor.interval` | Interval at which metrics should be scraped | `15s`
|
||||
`podMonitor.podMonitor` | Additional labels to add to the PodMonitor | `{}`
|
||||
`leaderElection.enabled` | If `true`, Flagger will run in HA mode | `false`
|
||||
`leaderElection.replicaCount` | Number of replicas | `1`
|
||||
`serviceAccount.create` | If `true`, Flagger will create service account | `true`
|
||||
`serviceAccount.name` | The name of the service account to create or use. If not set and `serviceAccount.create` is `true`, a name is generated using the Flagger fullname | `""`
|
||||
`serviceAccount.annotations` | Annotations for service account | `{}`
|
||||
`ingressAnnotationsPrefix` | Annotations prefix for ingresses | `custom.ingress.kubernetes.io`
|
||||
`includeLabelPrefix` | List of prefixes of labels that are copied when creating primary deployments or daemonsets. Use * to include all | `""`
|
||||
`rbac.create` | If `true`, create and use RBAC resources | `true`
|
||||
`rbac.pspEnabled` | If `true`, create and use a restricted pod security policy | `false`
|
||||
`crd.create` | If `true`, create Flagger's CRDs (should be enabled for Helm v2 only) | `false`
|
||||
`resources.requests/cpu` | Pod CPU request | `10m`
|
||||
`resources.requests/memory` | Pod memory request | `32Mi`
|
||||
`resources.limits/cpu` | Pod CPU limit | `1000m`
|
||||
`resources.limits/memory` | Pod memory limit | `512Mi`
|
||||
`affinity` | Node/pod affinities | None
|
||||
`nodeSelector` | Node labels for pod assignment | `{}`
|
||||
`threadiness` | Number of controller workers | `2`
|
||||
`tolerations` | List of node taints to tolerate | `[]`
|
||||
`istio.kubeconfig.secretName` | The name of the Kubernetes secret containing the Istio shared control plane kubeconfig | None
|
||||
`istio.kubeconfig.key` | The name of Kubernetes secret data key that contains the Istio control plane kubeconfig | `kubeconfig`
|
||||
`ingressAnnotationsPrefix` | Annotations prefix for NGINX ingresses | None
|
||||
`ingressClass` | Ingress class used for annotating HTTPProxy objects, e.g. `contour` | None
|
||||
`podPriorityClassName` | PriorityClass name for pod priority configuration | ""
|
||||
`podDisruptionBudget.enabled` | A PodDisruptionBudget will be created if `true` | `false`
|
||||
`podDisruptionBudget.minAvailable` | The minimal number of available replicas that will be set in the PodDisruptionBudget | `1`
|
||||
| Parameter | Description | Default |
|
||||
|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------|
|
||||
| `image.repository` | Image repository | `ghcr.io/fluxcd/flagger` |
|
||||
| `image.tag` | Image tag | `<VERSION>` |
|
||||
| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
|
||||
| `logLevel` | Log level | `info` |
|
||||
| `metricsServer` | Prometheus URL, used when `prometheus.install` is `false` | `http://prometheus.istio-system:9090` |
|
||||
| `prometheus.install` | If `true`, installs Prometheus configured to scrape all pods in the custer | `false` |
|
||||
| `prometheus.retention` | Prometheus data retention | `2h` |
|
||||
| `selectorLabels` | List of labels that Flagger uses to create pod selectors | `app,name,app.kubernetes.io/name` |
|
||||
| `configTracking.enabled` | If `true`, flagger will track changes in Secrets and ConfigMaps referenced in the target deployment | `true` |
|
||||
| `eventWebhook` | If set, Flagger will publish events to the given webhook | None |
|
||||
| `slack.url` | Slack incoming webhook | None |
|
||||
| `slack.proxyUrl` | Slack proxy url | None |
|
||||
| `slack.channel` | Slack channel | None |
|
||||
| `slack.user` | Slack username | `flagger` |
|
||||
| `msteams.url` | Microsoft Teams incoming webhook | None |
|
||||
| `msteams.proxyUrl` | Microsoft Teams proxy url | None |
|
||||
| `clusterName` | When specified, Flagger will add the cluster name to alerts | `""` |
|
||||
| `podMonitor.enabled` | If `true`, create a PodMonitor for [monitoring the metrics](https://docs.flagger.app/usage/monitoring#metrics) | `false` |
|
||||
| `podMonitor.namespace` | Namespace where the PodMonitor is created | the same namespace |
|
||||
| `podMonitor.interval` | Interval at which metrics should be scraped | `15s` |
|
||||
| `podMonitor.podMonitor` | Additional labels to add to the PodMonitor | `{}` |
|
||||
| `leaderElection.enabled` | If `true`, Flagger will run in HA mode | `false` |
|
||||
| `leaderElection.replicaCount` | Number of replicas | `1` |
|
||||
| `serviceAccount.create` | If `true`, Flagger will create service account | `true` |
|
||||
| `serviceAccount.name` | The name of the service account to create or use. If not set and `serviceAccount.create` is `true`, a name is generated using the Flagger fullname | `""` |
|
||||
| `serviceAccount.annotations` | Annotations for service account | `{}` |
|
||||
| `ingressAnnotationsPrefix` | Annotations prefix for ingresses | `custom.ingress.kubernetes.io` |
|
||||
| `includeLabelPrefix` | List of prefixes of labels that are copied when creating primary deployments or daemonsets. Use * to include all | `""` |
|
||||
| `rbac.create` | If `true`, create and use RBAC resources | `true` |
|
||||
| `rbac.pspEnabled` | If `true`, create and use a restricted pod security policy | `false` |
|
||||
| `crd.create` | If `true`, create Flagger's CRDs (should be enabled for Helm v2 only) | `false` |
|
||||
| `resources.requests/cpu` | Pod CPU request | `10m` |
|
||||
| `resources.requests/memory` | Pod memory request | `32Mi` |
|
||||
| `resources.limits/cpu` | Pod CPU limit | `1000m` |
|
||||
| `resources.limits/memory` | Pod memory limit | `512Mi` |
|
||||
| `affinity` | Node/pod affinities | None |
|
||||
| `nodeSelector` | Node labels for pod assignment | `{}` |
|
||||
| `threadiness` | Number of controller workers | `2` |
|
||||
| `tolerations` | List of node taints to tolerate | `[]` |
|
||||
| `istio.kubeconfig.secretName` | The name of the Kubernetes secret containing the Istio shared control plane kubeconfig | None |
|
||||
| `istio.kubeconfig.key` | The name of Kubernetes secret data key that contains the Istio control plane kubeconfig | `kubeconfig` |
|
||||
| `ingressAnnotationsPrefix` | Annotations prefix for NGINX ingresses | None |
|
||||
| `ingressClass` | Ingress class used for annotating HTTPProxy objects, e.g. `contour` | None |
|
||||
| `podPriorityClassName` | PriorityClass name for pod priority configuration | "" |
|
||||
| `podDisruptionBudget.enabled` | A PodDisruptionBudget will be created if `true` | `false` |
|
||||
| `podDisruptionBudget.minAvailable` | The minimal number of available replicas that will be set in the PodDisruptionBudget | `1` |
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm upgrade`. For example,
|
||||
|
||||
|
||||
@@ -129,6 +129,21 @@ spec:
|
||||
- Ingress
|
||||
name:
|
||||
type: string
|
||||
upstreamRef:
|
||||
description: Gloo Upstream selector
|
||||
type: object
|
||||
required: [ "apiVersion", "kind", "name" ]
|
||||
properties:
|
||||
apiVersion:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
enum:
|
||||
- Upstream
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
service:
|
||||
description: Kubernetes Service spec
|
||||
type: object
|
||||
@@ -172,15 +187,23 @@ spec:
|
||||
description: URI match conditions
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
uri:
|
||||
type: object
|
||||
authority:
|
||||
oneOf:
|
||||
- required: ["exact"]
|
||||
- required: ["prefix"]
|
||||
- required: ["suffix"]
|
||||
- required: ["regex"]
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
@@ -188,12 +211,223 @@ spec:
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
suffix:
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
gateways:
|
||||
description:
|
||||
Names of gateways where the rule should be
|
||||
applied.
|
||||
items:
|
||||
format: string
|
||||
type: string
|
||||
type: array
|
||||
headers:
|
||||
additionalProperties:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
ignoreUriCase:
|
||||
description:
|
||||
Flag to specify whether the URI matching should
|
||||
be case-insensitive.
|
||||
type: boolean
|
||||
method:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
description: The name assigned to a match.
|
||||
format: string
|
||||
type: string
|
||||
port:
|
||||
description:
|
||||
Specifies the ports on the host that is being
|
||||
addressed.
|
||||
type: integer
|
||||
queryParams:
|
||||
additionalProperties:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
description: Query parameters for matching.
|
||||
type: object
|
||||
scheme:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
sourceLabels:
|
||||
additionalProperties:
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
sourceNamespace:
|
||||
description:
|
||||
Source namespace constraining the applicability
|
||||
of a rule to workloads in that namespace.
|
||||
format: string
|
||||
type: string
|
||||
uri:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
withoutHeaders:
|
||||
additionalProperties:
|
||||
oneOf:
|
||||
- not:
|
||||
anyOf:
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
- required:
|
||||
- exact
|
||||
- required:
|
||||
- prefix
|
||||
- required:
|
||||
- regex
|
||||
properties:
|
||||
exact:
|
||||
format: string
|
||||
type: string
|
||||
prefix:
|
||||
format: string
|
||||
type: string
|
||||
regex:
|
||||
description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax).
|
||||
format: string
|
||||
type: string
|
||||
type: object
|
||||
description:
|
||||
withoutHeader has the same syntax with the
|
||||
header, but has opposite meaning.
|
||||
type: object
|
||||
type: object
|
||||
retries:
|
||||
description: Retry policy for HTTP requests
|
||||
type: object
|
||||
@@ -592,6 +826,9 @@ spec:
|
||||
mirrorWeight:
|
||||
description: Weight of traffic to be mirrored
|
||||
type: number
|
||||
primaryReadyThreshold:
|
||||
description: Percentage of pods that need to be available to consider primary as ready
|
||||
type: number
|
||||
match:
|
||||
description: A/B testing match conditions
|
||||
type: array
|
||||
@@ -668,6 +905,37 @@ spec:
|
||||
namespace:
|
||||
description: Namespace of this metric template
|
||||
type: string
|
||||
alerts:
|
||||
description: Alert list for this canary analysis
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- providerRef
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
description: Name of the this alert
|
||||
type: string
|
||||
severity:
|
||||
description: Severity level can be info, warn, error (default info)
|
||||
type: string
|
||||
enum:
|
||||
- ""
|
||||
- info
|
||||
- warn
|
||||
- error
|
||||
providerRef:
|
||||
description: Alert provider reference
|
||||
type: object
|
||||
required: ["name"]
|
||||
properties:
|
||||
name:
|
||||
description: Name of the alert provider
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace of the alert provider
|
||||
type: string
|
||||
webhooks:
|
||||
description: Webhook list for this canary
|
||||
type: array
|
||||
@@ -690,6 +958,10 @@ spec:
|
||||
- post-rollout
|
||||
- event
|
||||
- rollback
|
||||
- confirm-traffic-increase
|
||||
muteAlert:
|
||||
description: Mute all alerts for the webhook
|
||||
type: boolean
|
||||
url:
|
||||
description: URL address of this webhook
|
||||
type: string
|
||||
@@ -716,12 +988,18 @@ spec:
|
||||
- Initialized
|
||||
- Waiting
|
||||
- Progressing
|
||||
- WaitingPromotion
|
||||
- Promoting
|
||||
- Finalising
|
||||
- Succeeded
|
||||
- Failed
|
||||
- Terminating
|
||||
- Terminated
|
||||
trackedConfigs:
|
||||
description: TrackedConfig of this canary
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
canaryWeight:
|
||||
description: Traffic weight routed to canary
|
||||
type: number
|
||||
@@ -829,8 +1107,11 @@ spec:
|
||||
- prometheus
|
||||
- influxdb
|
||||
- datadog
|
||||
- stackdriver
|
||||
- cloudwatch
|
||||
- newrelic
|
||||
- graphite
|
||||
- dynatrace
|
||||
address:
|
||||
description: API address of this provider
|
||||
type: string
|
||||
@@ -846,6 +1127,9 @@ spec:
|
||||
region:
|
||||
description: Region of the provider
|
||||
type: string
|
||||
insecureSkipVerify:
|
||||
description: Disable SSL certificate validation for the provider address
|
||||
type: boolean
|
||||
query:
|
||||
description: Query of this metric template
|
||||
type: string
|
||||
@@ -912,9 +1196,19 @@ spec:
|
||||
- msteams
|
||||
- discord
|
||||
- rocket
|
||||
- gchat
|
||||
channel:
|
||||
description: Alert channel for this provider
|
||||
type: string
|
||||
username:
|
||||
description: Bot username for this provider
|
||||
type: string
|
||||
address:
|
||||
description: Hook URL address of this provider
|
||||
type: string
|
||||
proxy:
|
||||
description: Http/s proxy of this provider
|
||||
type: string
|
||||
secretRef:
|
||||
description: Kubernetes secret reference containing the provider address
|
||||
type: object
|
||||
|
||||
@@ -22,6 +22,11 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ template "flagger.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- if .Values.podLabels }}
|
||||
{{- range $key, $value := .Values.podLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{- if .Values.podAnnotations }}
|
||||
{{ toYaml .Values.podAnnotations | indent 8 }}
|
||||
@@ -90,6 +95,9 @@ spec:
|
||||
{{- if .Values.slack.url }}
|
||||
- -slack-url={{ .Values.slack.url }}
|
||||
{{- end }}
|
||||
{{- if .Values.slack.proxyUrl }}
|
||||
- -slack-proxy-url={{ .Values.slack.proxyUrl }}
|
||||
{{- end }}
|
||||
{{- if .Values.slack.user }}
|
||||
- -slack-user={{ .Values.slack.user }}
|
||||
{{- end }}
|
||||
@@ -99,6 +107,9 @@ spec:
|
||||
{{- if .Values.msteams.url }}
|
||||
- -msteams-url={{ .Values.msteams.url }}
|
||||
{{- end }}
|
||||
{{- if .Values.msteams.proxyUrl }}
|
||||
- -msteams-proxy-url={{ .Values.msteams.proxyUrl }}
|
||||
{{- end }}
|
||||
{{- if .Values.leaderElection.enabled }}
|
||||
- -enable-leader-election=true
|
||||
- -leader-election-namespace={{ .Release.Namespace }}
|
||||
@@ -127,6 +138,9 @@ spec:
|
||||
{{- if .Values.threadiness }}
|
||||
- -threadiness={{ .Values.threadiness }}
|
||||
{{- end }}
|
||||
{{- if .Values.clusterName }}
|
||||
- -cluster-name={{ .Values.clusterName }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{{- if .Values.prometheus.install }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ template "flagger.fullname" . }}-prometheus
|
||||
@@ -24,7 +24,7 @@ rules:
|
||||
- nonResourceURLs: ["/metrics"]
|
||||
verbs: ["get"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ template "flagger.fullname" . }}-prometheus
|
||||
@@ -255,7 +255,14 @@ spec:
|
||||
mountPath: /etc/prometheus
|
||||
- name: data-volume
|
||||
mountPath: /prometheus/data
|
||||
|
||||
{{- if .Values.prometheus.securityContext.enabled }}
|
||||
securityContext:
|
||||
{{ toYaml .Values.prometheus.securityContext.context | indent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.prometheus.pullSecret }}
|
||||
imagePullSecrets:
|
||||
- name: {{ .Values.prometheus.pullSecret }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{{- if .Values.rbac.create }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ template "flagger.fullname" . }}
|
||||
@@ -195,12 +195,25 @@ rules:
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- kuma.io
|
||||
resources:
|
||||
- trafficroutes
|
||||
- trafficroutes/finalizers
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- nonResourceURLs:
|
||||
- /version
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ template "flagger.fullname" . }}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
image:
|
||||
repository: ghcr.io/fluxcd/flagger
|
||||
tag: 1.6.0
|
||||
tag: 1.17.0
|
||||
pullPolicy: IfNotPresent
|
||||
pullSecret:
|
||||
|
||||
@@ -19,7 +19,7 @@ podPriorityClassName: ""
|
||||
|
||||
metricsServer: "http://prometheus:9090"
|
||||
|
||||
# accepted values are kubernetes, istio, linkerd, appmesh, contour, nginx, gloo, skipper, traefik
|
||||
# accepted values are kubernetes, istio, linkerd, appmesh, contour, nginx, gloo, skipper, traefik, osm
|
||||
meshProvider: ""
|
||||
|
||||
# single namespace restriction
|
||||
@@ -50,11 +50,15 @@ securityContext:
|
||||
# when specified, flagger will publish events to the provided webhook
|
||||
eventWebhook: ""
|
||||
|
||||
# when specified, flagger will add the cluster name to alerts
|
||||
clusterName: ""
|
||||
|
||||
slack:
|
||||
user: flagger
|
||||
channel:
|
||||
# incoming webhook https://api.slack.com/incoming-webhooks
|
||||
url:
|
||||
proxy:
|
||||
|
||||
msteams:
|
||||
# MS Teams incoming webhook URL
|
||||
@@ -72,11 +76,21 @@ podMonitor:
|
||||
# secretKeyRef:
|
||||
# name: slack
|
||||
# key: url
|
||||
#- name: SLACK_PROXY_URL
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
# name: slack
|
||||
# key: proxy-url
|
||||
#- name: MSTEAMS_URL
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
# name: msteams
|
||||
# key: url
|
||||
#- name: MSTEAMS_PROXY_URL
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
# name: msteams
|
||||
# key: proxy-url
|
||||
#- name: EVENT_WEBHOOK_URL
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
@@ -124,8 +138,15 @@ tolerations: []
|
||||
prometheus:
|
||||
# to be used with ingress controllers
|
||||
install: false
|
||||
image: docker.io/prom/prometheus:v2.23.0
|
||||
image: docker.io/prom/prometheus:v2.32.1
|
||||
pullSecret:
|
||||
retention: 2h
|
||||
# when enabled, it will add a security context for the prometheus pod
|
||||
securityContext:
|
||||
enabled: false
|
||||
context:
|
||||
readOnlyRootFilesystem: true
|
||||
runAsUser: 10001
|
||||
|
||||
kubeconfigQPS: ""
|
||||
kubeconfigBurst: ""
|
||||
@@ -142,3 +163,5 @@ istio:
|
||||
podDisruptionBudget:
|
||||
enabled: false
|
||||
minAvailable: 1
|
||||
|
||||
podLabels: {}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
apiVersion: v1
|
||||
name: grafana
|
||||
version: 1.5.0
|
||||
version: 1.6.0
|
||||
appVersion: 7.2.0
|
||||
description: Grafana dashboards for monitoring Flagger canary deployments
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flagger/main/docs/logo/weaveworks.png
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flagger/main/docs/logo/flagger-icon.png
|
||||
home: https://flagger.app
|
||||
sources:
|
||||
- https://github.com/fluxcd/flagger
|
||||
|
||||
@@ -1146,7 +1146,6 @@
|
||||
"list": [
|
||||
{
|
||||
"allValue": null,
|
||||
"current": null,
|
||||
"datasource": "prometheus",
|
||||
"definition": "query_result(sum(envoy_cluster_upstream_rq) by (kubernetes_namespace))",
|
||||
"hide": 0,
|
||||
@@ -1168,7 +1167,6 @@
|
||||
},
|
||||
{
|
||||
"allValue": null,
|
||||
"current": null,
|
||||
"datasource": "prometheus",
|
||||
"definition": "query_result(sum(envoy_cluster_upstream_rq{kubernetes_namespace=\"$namespace\",app=~\".*-primary\"}) by (app))",
|
||||
"hide": 0,
|
||||
@@ -1190,7 +1188,6 @@
|
||||
},
|
||||
{
|
||||
"allValue": null,
|
||||
"current": null,
|
||||
"datasource": "prometheus",
|
||||
"definition": "query_result(sum(envoy_cluster_upstream_rq{kubernetes_namespace=\"$namespace\",app!~\".*-primary\"}) by (app))",
|
||||
"hide": 0,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
apiVersion: v1
|
||||
name: loadtester
|
||||
version: 0.18.0
|
||||
appVersion: 0.18.0
|
||||
version: 0.21.0
|
||||
appVersion: 0.21.0
|
||||
kubeVersion: ">=1.11.0-0"
|
||||
engine: gotpl
|
||||
description: Flagger's load testing services based on rakyll/hey and bojand/ghz that generates traffic during canary analysis when configured as a webhook.
|
||||
home: https://docs.flagger.app
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flagger/main/docs/logo/weaveworks.png
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flagger/main/docs/logo/flagger-icon.png
|
||||
sources:
|
||||
- https://github.com/fluxcd/flagger
|
||||
maintainers:
|
||||
@@ -19,5 +19,7 @@ keywords:
|
||||
- appmesh
|
||||
- linkerd
|
||||
- gloo
|
||||
- osm
|
||||
- smi
|
||||
- gitops
|
||||
- load testing
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Flagger load testing service
|
||||
|
||||
[Flagger's](https://github.com/fluxcd/flagger) load testing service is based on
|
||||
[rakyll/hey](https://github.com/rakyll/hey) and
|
||||
[Flagger's](https://github.com/fluxcd/flagger) load testing service is based on
|
||||
[rakyll/hey](https://github.com/rakyll/hey) and
|
||||
[bojand/ghz](https://github.com/bojand/ghz).
|
||||
It can be used to generate HTTP and gRPC traffic during canary analysis when configured as a webhook.
|
||||
|
||||
@@ -26,7 +26,7 @@ helm upgrade -i flagger-loadtester flagger/loadtester
|
||||
The command deploys loadtester on the Kubernetes cluster in the default namespace.
|
||||
|
||||
> **Tip**: Note that the namespace where you deploy the load tester should
|
||||
> have the Istio, App Mesh or Linkerd sidecar injection enabled
|
||||
> have the Istio, App Mesh, Linkerd or Open Service Mesh sidecar injection enabled
|
||||
|
||||
The [configuration](#configuration) section lists the parameters that can be configured during installation.
|
||||
|
||||
@@ -50,7 +50,7 @@ Parameter | Description | Default
|
||||
`image.pullPolicy` | Image pull policy | `IfNotPresent`
|
||||
`image.tag` | Image tag | `<VERSION>`
|
||||
`replicaCount` | Desired number of pods | `1`
|
||||
`serviceAccountName` | Kubernetes service account name | `none`
|
||||
`serviceAccountName` | Kubernetes service account name | `none`
|
||||
`resources.requests.cpu` | CPU requests | `10m`
|
||||
`resources.requests.memory` | Memory requests | `64Mi`
|
||||
`tolerations` | List of node taints to tolerate | `[]`
|
||||
@@ -70,6 +70,8 @@ Parameter | Description | Default
|
||||
`podPriorityClassName` | PriorityClass name for pod priority configuration | ""
|
||||
`securityContext.enabled` | Add securityContext to container | ""
|
||||
`securityContext.context` | securityContext to add | ""
|
||||
`podDisruptionBudget.enabled` | A PodDisruptionBudget will be created if `true` | `false`
|
||||
`podDisruptionBudget.minAvailable` | The minimal number of available replicas that will be set in the PodDisruptionBudget | `1`
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm upgrade`. For example,
|
||||
|
||||
@@ -87,5 +89,3 @@ helm install flagger/loadtester --name flagger-loadtester -f values.yaml
|
||||
```
|
||||
|
||||
> **Tip**: You can use the default [values.yaml](values.yaml)
|
||||
|
||||
|
||||
|
||||
@@ -16,8 +16,13 @@ spec:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ include "loadtester.name" . }}
|
||||
app.kubernetes.io/name: {{ include "loadtester.name" . }}
|
||||
{{- range $key, $value := .Values.podLabels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
appmesh.k8s.aws/ports: "444"
|
||||
openservicemesh.io/inbound-port-exclusion-list: "80, 8080"
|
||||
{{- if .Values.podAnnotations }}
|
||||
{{ toYaml .Values.podAnnotations | indent 8 }}
|
||||
{{- end }}
|
||||
@@ -29,7 +34,7 @@ spec:
|
||||
{{- end }}
|
||||
{{- if .Values.podPriorityClassName }}
|
||||
priorityClassName: {{ .Values.podPriorityClassName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
{{- if .Values.securityContext.enabled }}
|
||||
@@ -66,8 +71,24 @@ spec:
|
||||
- --spider
|
||||
- http://localhost:8080/healthz
|
||||
timeoutSeconds: 5
|
||||
{{- if .Values.env }}
|
||||
env:
|
||||
{{- toYaml .Values.env | nindent 12 }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
{{- with .Values.volumeMounts }}
|
||||
volumeMounts:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.image.pullSecret }}
|
||||
imagePullSecrets:
|
||||
- name: {{ .Values.image.pullSecret }}
|
||||
{{- end }}
|
||||
{{ with .Values.volumes }}
|
||||
volumes:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
|
||||
11
charts/loadtester/templates/pdb.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
{{- if .Values.podDisruptionBudget.enabled }}
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: {{ include "loadtester.fullname" . }}
|
||||
spec:
|
||||
minAvailable: {{ .Values.podDisruptionBudget.minAvailable }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ include "loadtester.name" . }}
|
||||
{{- end }}
|
||||
@@ -2,14 +2,17 @@ replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: ghcr.io/fluxcd/flagger-loadtester
|
||||
tag: 0.18.0
|
||||
tag: 0.21.0
|
||||
pullPolicy: IfNotPresent
|
||||
pullSecret:
|
||||
|
||||
podLabels: {}
|
||||
|
||||
podAnnotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "8080"
|
||||
|
||||
podPriorityClassName: ""
|
||||
podPriorityClassName: ""
|
||||
|
||||
logLevel: info
|
||||
cmd:
|
||||
@@ -18,6 +21,8 @@ cmd:
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
env: []
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
@@ -27,6 +32,9 @@ resources:
|
||||
cpu: 10m
|
||||
memory: 64Mi
|
||||
|
||||
volumes: []
|
||||
volumeMounts: []
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
@@ -62,15 +70,15 @@ appmesh:
|
||||
- podinfo
|
||||
- podinfo-canary
|
||||
|
||||
#Istio virtual service and gatway settings. TLS secrets should be in namespace before enbaled it. ( secret format loadtester.fullname )
|
||||
#Istio virtual service and gatway settings. TLS secrets should be in namespace before enbaled it. ( secret format loadtester.fullname )
|
||||
istio:
|
||||
enabled: false
|
||||
host: flagger-loadtester.flagger
|
||||
gateway:
|
||||
enabled: false
|
||||
enabled: false
|
||||
tls:
|
||||
enabled: false
|
||||
httpsRedirect: false
|
||||
httpsRedirect: false
|
||||
|
||||
# when enabled, it will add a security context for the loadtester pod
|
||||
securityContext:
|
||||
@@ -79,3 +87,7 @@ securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
runAsUser: 100
|
||||
runAsGroup: 101
|
||||
|
||||
podDisruptionBudget:
|
||||
enabled: false
|
||||
minAvailable: 1
|
||||
|
||||
@@ -5,7 +5,7 @@ name: podinfo
|
||||
engine: gotpl
|
||||
description: Flagger canary deployment demo application
|
||||
home: https://docs.flagger.app
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flagger/main/docs/logo/weaveworks.png
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flagger/main/docs/logo/flagger-icon.png
|
||||
sources:
|
||||
- https://github.com/stefanprodan/podinfo
|
||||
maintainers:
|
||||
|
||||
@@ -12,6 +12,7 @@ metadata:
|
||||
sidecar.istio.io/inject: "false"
|
||||
linkerd.io/inject: disabled
|
||||
appmesh.k8s.aws/sidecarInjectorWebhook: disabled
|
||||
openservicemesh.io/sidecar-injection: disabled
|
||||
spec:
|
||||
containers:
|
||||
- name: tools
|
||||
|
||||
@@ -63,8 +63,10 @@ var (
|
||||
logLevel string
|
||||
port string
|
||||
msteamsURL string
|
||||
msteamsProxyURL string
|
||||
includeLabelPrefix string
|
||||
slackURL string
|
||||
slackProxyURL string
|
||||
slackUser string
|
||||
slackChannel string
|
||||
eventWebhook string
|
||||
@@ -81,6 +83,7 @@ var (
|
||||
enableConfigTracking bool
|
||||
ver bool
|
||||
kubeconfigServiceMesh string
|
||||
clusterName string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -93,16 +96,18 @@ func init() {
|
||||
flag.StringVar(&logLevel, "log-level", "debug", "Log level can be: debug, info, warning, error.")
|
||||
flag.StringVar(&port, "port", "8080", "Port to listen on.")
|
||||
flag.StringVar(&slackURL, "slack-url", "", "Slack hook URL.")
|
||||
flag.StringVar(&slackProxyURL, "slack-proxy-url", "", "Slack proxy URL.")
|
||||
flag.StringVar(&slackUser, "slack-user", "flagger", "Slack user name.")
|
||||
flag.StringVar(&slackChannel, "slack-channel", "", "Slack channel.")
|
||||
flag.StringVar(&eventWebhook, "event-webhook", "", "Webhook for publishing flagger events")
|
||||
flag.StringVar(&msteamsURL, "msteams-url", "", "MS Teams incoming webhook URL.")
|
||||
flag.StringVar(&msteamsProxyURL, "msteams-proxy-url", "", "MS Teams proxy URL.")
|
||||
flag.StringVar(&includeLabelPrefix, "include-label-prefix", "", "List of prefixes of labels that are copied when creating primary deployments or daemonsets. Use * to include all.")
|
||||
flag.IntVar(&threadiness, "threadiness", 2, "Worker concurrency.")
|
||||
flag.BoolVar(&zapReplaceGlobals, "zap-replace-globals", false, "Whether to change the logging level of the global zap logger.")
|
||||
flag.StringVar(&zapEncoding, "zap-encoding", "json", "Zap logger encoding.")
|
||||
flag.StringVar(&namespace, "namespace", "", "Namespace that flagger would watch canary object.")
|
||||
flag.StringVar(&meshProvider, "mesh-provider", "istio", "Service mesh provider, can be istio, linkerd, appmesh, contour, gloo, nginx, skipper or traefik.")
|
||||
flag.StringVar(&meshProvider, "mesh-provider", "istio", "Service mesh provider, can be istio, linkerd, appmesh, contour, gloo, nginx, skipper, traefik, osm or kuma.")
|
||||
flag.StringVar(&selectorLabels, "selector-labels", "app,name,app.kubernetes.io/name", "List of pod labels that Flagger uses to create pod selectors.")
|
||||
flag.StringVar(&ingressAnnotationsPrefix, "ingress-annotations-prefix", "nginx.ingress.kubernetes.io", "Annotations prefix for NGINX ingresses.")
|
||||
flag.StringVar(&ingressClass, "ingress-class", "", "Ingress class used for annotating HTTPProxy objects.")
|
||||
@@ -111,6 +116,7 @@ func init() {
|
||||
flag.BoolVar(&enableConfigTracking, "enable-config-tracking", true, "Enable secrets and configmaps tracking.")
|
||||
flag.BoolVar(&ver, "version", false, "Print version")
|
||||
flag.StringVar(&kubeconfigServiceMesh, "kubeconfig-service-mesh", "", "Path to a kubeconfig for the service mesh control plane cluster.")
|
||||
flag.StringVar(&clusterName, "cluster-name", "", "Cluster name to be included in alert msgs.")
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -234,6 +240,7 @@ func main() {
|
||||
meshProvider,
|
||||
version.VERSION,
|
||||
fromEnv("EVENT_WEBHOOK_URL", eventWebhook),
|
||||
clusterName,
|
||||
)
|
||||
|
||||
// leader election context
|
||||
@@ -349,11 +356,13 @@ func startLeaderElection(ctx context.Context, run func(), ns string, kubeClient
|
||||
func initNotifier(logger *zap.SugaredLogger) (client notifier.Interface) {
|
||||
provider := "slack"
|
||||
notifierURL := fromEnv("SLACK_URL", slackURL)
|
||||
notifierProxyURL := fromEnv("SLACK_PROXY_URL", slackProxyURL)
|
||||
if msteamsURL != "" || os.Getenv("MSTEAMS_URL") != "" {
|
||||
provider = "msteams"
|
||||
notifierURL = fromEnv("MSTEAMS_URL", msteamsURL)
|
||||
notifierProxyURL = fromEnv("MSTEAMS_PROXY_URL", msteamsProxyURL)
|
||||
}
|
||||
notifierFactory := notifier.NewFactory(notifierURL, slackUser, slackChannel)
|
||||
notifierFactory := notifier.NewFactory(notifierURL, notifierProxyURL, slackUser, slackChannel)
|
||||
|
||||
var err error
|
||||
client, err = notifierFactory.Notifier(provider)
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var VERSION = "0.18.0"
|
||||
var VERSION = "0.21.0"
|
||||
var (
|
||||
logLevel string
|
||||
port string
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
BIN
docs/diagrams/flagger-kuma-canary.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 39 KiB |
BIN
docs/diagrams/flagger-osm-traffic-split.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 45 KiB |
BIN
docs/diagrams/flagger-traefik-overview.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
@@ -4,39 +4,40 @@ description: Flagger is a progressive delivery Kubernetes operator
|
||||
|
||||
# Introduction
|
||||
|
||||
[Flagger](https://github.com/fluxcd/flagger) is a **Kubernetes** operator
|
||||
that automates the promotion of canary deployments using
|
||||
**Istio**, **Linkerd**, **App Mesh**, **NGINX**, **Skipper**, **Contour**, **Gloo** or **Traefik**
|
||||
routing for traffic shifting and **Prometheus** metrics for canary analysis.
|
||||
The canary analysis can be extended with webhooks for running
|
||||
system integration/acceptance tests, load tests, or any other custom validation.
|
||||
[Flagger](https://github.com/fluxcd/flagger) is a progressive delivery tool that automates the release
|
||||
process for applications running on Kubernetes. It reduces the risk of introducing a new software
|
||||
version in production by gradually shifting traffic to the new version while measuring metrics
|
||||
and running conformance tests.
|
||||
|
||||
Flagger implements a control loop that gradually shifts traffic to the canary
|
||||
while measuring key performance indicators like HTTP requests success rate,
|
||||
requests average duration and pods health.
|
||||
Based on analysis of the **KPIs** a canary is promoted or aborted,
|
||||
and the analysis result is published to **Slack** or **MS Teams**.
|
||||
Flagger implements several deployment strategies (Canary releases, A/B testing, Blue/Green mirroring)
|
||||
using a service mesh (App Mesh, Istio, Linkerd, Open Service Mesh)
|
||||
or an ingress controller (Contour, Gloo, NGINX, Skipper, Traefik) for traffic routing.
|
||||
For release analysis, Flagger can query Prometheus, Datadog, New Relic, CloudWatch or Graphite
|
||||
and for alerting it uses Slack, MS Teams, Discord and Rocket.
|
||||
|
||||

|
||||

|
||||
|
||||
Flagger can be configured with Kubernetes custom resources and is compatible with any CI/CD solutions made for Kubernetes.
|
||||
Since Flagger is declarative and reacts to Kubernetes events,
|
||||
it can be used in **GitOps** pipelines together with Flux CD or JenkinsX.
|
||||
Flagger can be configured with Kubernetes custom resources and is compatible with
|
||||
any CI/CD solutions made for Kubernetes. Since Flagger is declarative and reacts to Kubernetes events,
|
||||
it can be used in **GitOps** pipelines together with tools like Flux, JenkinsX, Carvel, Argo, etc.
|
||||
|
||||
Flagger is a [Cloud Native Computing Foundation](https://cncf.io/) project.
|
||||
Flagger is a [Cloud Native Computing Foundation](https://cncf.io/) project
|
||||
and part of [Flux](https://fluxcd.io) family of GitOps tools.
|
||||
|
||||
## Getting started
|
||||
|
||||
To get started with Flagger, chose one of the supported routing providers and
|
||||
To get started with Flagger, choose one of the supported routing providers and
|
||||
[install](install/flagger-install-on-kubernetes.md) Flagger with Helm or Kustomize.
|
||||
|
||||
After install Flagger, you can follow one of these tutorials to get started:
|
||||
After installing Flagger, you can follow one of these tutorials to get started:
|
||||
|
||||
**Service mesh tutorials**
|
||||
|
||||
* [Istio](tutorials/istio-progressive-delivery.md)
|
||||
* [Linkerd](tutorials/linkerd-progressive-delivery.md)
|
||||
* [AWS App Mesh](tutorials/appmesh-progressive-delivery.md)
|
||||
* [Open Service Mesh](tutorials/osm-progressive-delivery.md)
|
||||
* [Kuma](tutorials/kuma-progressive-delivery.md)
|
||||
|
||||
**Ingress controller tutorials**
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* [Flagger Install on Kubernetes](install/flagger-install-on-kubernetes.md)
|
||||
* [Flagger Install on GKE Istio](install/flagger-install-on-google-cloud.md)
|
||||
* [Flagger Install on EKS App Mesh](install/flagger-install-on-eks-appmesh.md)
|
||||
* [Flagger Install on Alibaba ServiceMesh](install/flagger-install-on-alibaba-servicemesh.md)
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -29,10 +30,11 @@
|
||||
* [NGINX Canary Deployments](tutorials/nginx-progressive-delivery.md)
|
||||
* [Skipper Canary Deployments](tutorials/skipper-progressive-delivery.md)
|
||||
* [Traefik Canary Deployments](tutorials/traefik-progressive-delivery.md)
|
||||
* [Open Service Mesh Deployments](tutorials/osm-progressive-delivery.md)
|
||||
* [Kuma Canary Deployments](tutorials/kuma-progressive-delivery.md)
|
||||
* [Blue/Green Deployments](tutorials/kubernetes-blue-green.md)
|
||||
* [Canary analysis with Prometheus Operator](tutorials/prometheus-operator.md)
|
||||
* [Zero downtime deployments](tutorials/zero-downtime-deployments.md)
|
||||
* [Rollout Weights](tutorials/rollout-weights.md)
|
||||
|
||||
## Dev
|
||||
|
||||
|
||||
@@ -8,17 +8,17 @@ Flagger is written in Go and uses Go modules for dependency management.
|
||||
|
||||
On your dev machine install the following tools:
|
||||
|
||||
* go >= 1.14
|
||||
* git >= 2.20
|
||||
* bash >= 5.0
|
||||
* make >= 3.81
|
||||
* kubectl >= 1.16
|
||||
* kustomize >= 3.5
|
||||
* helm >= 3.0
|
||||
* docker >= 19.03
|
||||
* go >= 1.17
|
||||
* git >;= 2.20
|
||||
* bash >= 5.0
|
||||
* make >= 3.81
|
||||
* kubectl >= 1.22
|
||||
* kustomize >= 4.4
|
||||
* helm >= 3.0
|
||||
* docker >= 19.03
|
||||
|
||||
You'll also need a Kubernetes cluster for testing Flagger.
|
||||
You can use Minikube, Kind, Docker desktop or any remote cluster (AKS/EKS/GKE/etc) Kubernetes version 1.16 or newer.
|
||||
You can use Minikube, Kind, Docker desktop or any remote cluster (AKS/EKS/GKE/etc) Kubernetes version 1.22 or newer.
|
||||
|
||||
To start contributing to Flagger, fork the [repository](https://github.com/fluxcd/flagger) on GitHub.
|
||||
|
||||
@@ -100,6 +100,8 @@ make codegen
|
||||
Run code formatters:
|
||||
|
||||
```bash
|
||||
go install golang.org/x/tools/cmd/goimports@latest
|
||||
|
||||
make fmt
|
||||
```
|
||||
|
||||
@@ -200,7 +202,7 @@ Run the Istio e2e tests:
|
||||
./test/istio/run.sh
|
||||
```
|
||||
|
||||
For each service mesh and ingress controller there is a dedicated e2e test suite,
|
||||
chose one that matches your changes from this [list](https://github.com/fluxcd/flagger/tree/main/test).
|
||||
For each service mesh and ingress controller, there is a dedicated e2e test suite,
|
||||
choose one that matches your changes from this [list](https://github.com/fluxcd/flagger/tree/main/test).
|
||||
|
||||
When you open a pull request on Flagger repo, the unit and integration tests will be run in CI.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Deployment Strategies
|
||||
|
||||
**Which deployment strategies are supported by Flagger?**
|
||||
#### Which deployment strategies are supported by Flagger?
|
||||
|
||||
Flagger implements the following deployment strategies:
|
||||
|
||||
@@ -11,25 +11,25 @@ Flagger implements the following deployment strategies:
|
||||
* [Blue/Green](usage/deployment-strategies.md#bluegreen-deployments)
|
||||
* [Blue/Green Mirroring](usage/deployment-strategies.md#bluegreen-with-traffic-mirroring)
|
||||
|
||||
**When should I use A/B testing instead of progressive traffic shifting?**
|
||||
#### When should I use A/B testing instead of progressive traffic shifting?
|
||||
|
||||
For frontend applications that require session affinity you should use HTTP headers or
|
||||
cookies match conditions to ensure a set of users will stay on the same version for
|
||||
For frontend applications that require session affinity, you should use HTTP headers or
|
||||
cookie match conditions to ensure a set of users will stay on the same version for
|
||||
the whole duration of the canary analysis.
|
||||
|
||||
**Can I use Flagger to manage applications that live outside of a service mesh?**
|
||||
#### Can I use Flagger to manage applications that live outside of a service mesh?
|
||||
|
||||
For applications that are not deployed on a service mesh,
|
||||
Flagger can orchestrate Blue/Green style deployments with Kubernetes L4 networking.
|
||||
|
||||
**When can I use traffic mirroring?**
|
||||
#### When can I use traffic mirroring?
|
||||
|
||||
Traffic mirroring can be used for Blue/Green deployment strategy or a pre-stage in a Canary release.
|
||||
Traffic mirroring will copy each incoming request, sending one request to the primary and one to the canary service.
|
||||
Mirroring should be used for requests that are **idempotent**
|
||||
or capable of being processed twice (once by the primary and once by the canary).
|
||||
|
||||
**How to retry a failed release?**
|
||||
#### How to retry a failed release?
|
||||
|
||||
A canary analysis is triggered by changes in any of the following objects:
|
||||
|
||||
@@ -49,11 +49,17 @@ spec:
|
||||
timestamp: "2020-03-10T14:24:48+0000"
|
||||
```
|
||||
|
||||
#### Why is there a window of downtime during the canary initializing process when analysis is disabled?
|
||||
|
||||
A window of downtime is the intended behavior when the analysis is disabled. This allows instant rollback and also mimics the way
|
||||
a Kubernetes deployment initialization works. To avoid this, enable the analysis (`skipAnalysis: true`), wait for the initialization
|
||||
to finish, and disable it afterward (`skipAnalysis: false`).
|
||||
|
||||
## Kubernetes services
|
||||
|
||||
**How is an application exposed inside the cluster?**
|
||||
#### How is an application exposed inside the cluster?
|
||||
|
||||
Assuming the app name is podinfo you can define a canary like:
|
||||
Assuming the app name is `podinfo`, you can define a canary like:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
@@ -79,19 +85,19 @@ spec:
|
||||
|
||||
If the `service.name` is not specified, then `targetRef.name` is used for
|
||||
the apex domain and canary/primary services name prefix.
|
||||
You should treat the service name as an immutable field, changing it could result in routing conflicts.
|
||||
You should treat the service name as an immutable field; changing its could result in routing conflicts.
|
||||
|
||||
Based on the canary spec service, Flagger generates the following Kubernetes ClusterIP service:
|
||||
|
||||
* `<service.name>.<namespace>.svc.cluster.local`
|
||||
* `<service.name>.<namespace>.svc.cluster.local`
|
||||
|
||||
selector `app=<name>-primary`
|
||||
|
||||
* `<service.name>-primary.<namespace>.svc.cluster.local`
|
||||
* `<service.name>-primary.<namespace>.svc.cluster.local`
|
||||
|
||||
selector `app=<name>-primary`
|
||||
|
||||
* `<service.name>-canary.<namespace>.svc.cluster.local`
|
||||
* `<service.name>-canary.<namespace>.svc.cluster.local`
|
||||
|
||||
selector `app=<name>`
|
||||
|
||||
@@ -147,7 +153,7 @@ and can be used for conformance testing or load testing.
|
||||
|
||||
## Multiple ports
|
||||
|
||||
**My application listens on multiple ports, how can I expose them inside the cluster?**
|
||||
#### My application listens on multiple ports. How can I expose them inside the cluster?
|
||||
|
||||
If port discovery is enabled, Flagger scans the deployment spec and extracts the containers ports excluding
|
||||
the port specified in the canary service and Envoy sidecar ports.
|
||||
@@ -195,7 +201,7 @@ Both port `8080` and `9090` will be added to the ClusterIP services.
|
||||
|
||||
## Label selectors
|
||||
|
||||
**What labels selectors are supported by Flagger?**
|
||||
#### What labels selectors are supported by Flagger?
|
||||
|
||||
The target deployment must have a single label selector in the format `app: <DEPLOYMENT-NAME>`:
|
||||
|
||||
@@ -214,14 +220,93 @@ spec:
|
||||
app: podinfo
|
||||
```
|
||||
|
||||
Besides `app` Flagger supports `name` and `app.kubernetes.io/name` selectors.
|
||||
If you use a different convention you can specify your label with the `-selector-labels` flag.
|
||||
Besides `app`, Flagger supports `name` and `app.kubernetes.io/name` selectors.
|
||||
If you use a different convention, you can specify your label with the `-selector-labels` flag.
|
||||
For example:
|
||||
|
||||
**Is pod affinity and anti affinity supported?**
|
||||
```
|
||||
flagger \
|
||||
-selector-labels=service,name,app.kubernetes.io/name \
|
||||
...
|
||||
```
|
||||
|
||||
For pod affinity to work you need to use a different label than the `app`, `name` or `app.kubernetes.io/name`.
|
||||
#### Is pod affinity and anti affinity supported?
|
||||
|
||||
Anti affinity example:
|
||||
Flagger will rewrite the first value in each match expression,
|
||||
defined in the target deployment's pod anti-affinity and topology spread constraints,
|
||||
satisfying the following two requirements when creating, or updating, the primary deployment:
|
||||
|
||||
* The key in the match expression must be one of the labels specified by the parameter selector-labels.
|
||||
The default labels are `app`,`name`,`app.kubernetes.io/name`.
|
||||
* The value must match the name of the target deployment.
|
||||
|
||||
The rewrite done by Flagger in these cases is to suffix the value with `-primary`.
|
||||
This rewrite can be used to spread the pods created by the canary
|
||||
and primary deployments across different availability zones.
|
||||
|
||||
Example target deployment:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: podinfo
|
||||
spec:
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- podinfo
|
||||
topologyKey: topology.kubernetes.io/zone
|
||||
```
|
||||
|
||||
Example of generated primary deployment:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: podinfo-primary
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo-primary
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: podinfo-primary
|
||||
spec:
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- podinfo-primary
|
||||
topologyKey: topology.kubernetes.io/zone
|
||||
```
|
||||
|
||||
It is also possible to use a different label than the `app`, `name` or `app.kubernetes.io/name`.
|
||||
|
||||
Anti affinity example(using a different label):
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
@@ -247,16 +332,16 @@ spec:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
affinity: podinfo
|
||||
topologyKey: kubernetes.io/hostname
|
||||
topologyKey: topology.kubernetes.io/zone
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
**How does Flagger measure the request success rate and duration?**
|
||||
#### How does Flagger measure the request success rate and duration?
|
||||
|
||||
Flagger measures the request success rate and duration using Prometheus queries.
|
||||
By default, Flagger measures the request success rate and duration using Prometheus queries.
|
||||
|
||||
**HTTP requests success rate percentage**
|
||||
#### HTTP requests success rate percentage
|
||||
|
||||
Spec:
|
||||
|
||||
@@ -283,8 +368,8 @@ sum(
|
||||
response_code!~"5.*"
|
||||
}[$interval]
|
||||
)
|
||||
)
|
||||
/
|
||||
)
|
||||
/
|
||||
sum(
|
||||
rate(
|
||||
istio_requests_total{
|
||||
@@ -307,8 +392,8 @@ sum(
|
||||
envoy_response_code!~"5.*"
|
||||
}[$interval]
|
||||
)
|
||||
)
|
||||
/
|
||||
)
|
||||
/
|
||||
sum(
|
||||
rate(
|
||||
envoy_cluster_upstream_rq{
|
||||
@@ -340,7 +425,7 @@ sum(
|
||||
)
|
||||
```
|
||||
|
||||
**HTTP requests milliseconds duration P99**
|
||||
#### HTTP requests milliseconds duration P99
|
||||
|
||||
Spec:
|
||||
|
||||
@@ -358,10 +443,10 @@ Spec:
|
||||
Istio query:
|
||||
|
||||
```javascript
|
||||
histogram_quantile(0.99,
|
||||
histogram_quantile(0.99,
|
||||
sum(
|
||||
irate(
|
||||
istio_request_duration_seconds_bucket{
|
||||
istio_request_duration_milliseconds_bucket{
|
||||
reporter="destination",
|
||||
destination_workload=~"$workload",
|
||||
destination_workload_namespace=~"$namespace"
|
||||
@@ -374,7 +459,7 @@ histogram_quantile(0.99,
|
||||
Envoy query (App Mesh, Contour and Gloo):
|
||||
|
||||
```javascript
|
||||
histogram_quantile(0.99,
|
||||
histogram_quantile(0.99,
|
||||
sum(
|
||||
irate(
|
||||
envoy_cluster_upstream_rq_time_bucket{
|
||||
@@ -388,14 +473,14 @@ histogram_quantile(0.99,
|
||||
|
||||
> **Note** that the metric interval should be lower or equal to the control loop interval.
|
||||
|
||||
**Can I use custom metrics?**
|
||||
#### Can I use custom metrics?
|
||||
|
||||
The analysis can be extended with metrics provided by Prometheus, Datadog and AWS CloudWatch.
|
||||
For more details on how custom metrics can be used please read the [metrics docs](usage/metrics.md).
|
||||
The analysis can be extended with metrics provided by Prometheus, Datadog, AWS CloudWatch, New Relic and Graphite.
|
||||
For more details on how custom metrics can be used, please read the [metrics docs](usage/metrics.md).
|
||||
|
||||
## Istio routing
|
||||
|
||||
**How does Flagger interact with Istio?**
|
||||
#### How does Flagger interact with Istio?
|
||||
|
||||
Flagger creates an Istio Virtual Service and Destination Rules based on the Canary service spec.
|
||||
The service configuration lets you expose an app inside or outside the mesh. You can also define traffic policies,
|
||||
@@ -634,7 +719,7 @@ spec:
|
||||
weight: 0
|
||||
```
|
||||
|
||||
Therefore, The following virtual service forward the traffic to `/podinfo` by the above delegate VirtualService.
|
||||
Therefore, the following virtual service forwards the traffic to `/podinfo` by the above delegate VirtualService.
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
@@ -660,17 +745,17 @@ spec:
|
||||
namespace: test
|
||||
```
|
||||
|
||||
Note that pilot env `PILOT_ENABLE_VIRTUAL_SERVICE_DELEGATE` must also be set.
|
||||
Note that pilot env `PILOT_ENABLE_VIRTUAL_SERVICE_DELEGATE` must also be set.
|
||||
For the use of Istio Delegation, you can refer to the documentation of
|
||||
[Virtual Service](https://istio.io/latest/docs/reference/config/networking/virtual-service/#Delegate)
|
||||
and [pilot environment variables](https://istio.io/latest/docs/reference/commands/pilot-discovery/#envvars).
|
||||
|
||||
## Istio Ingress Gateway
|
||||
|
||||
**How can I expose multiple canaries on the same external domain?**
|
||||
#### How can I expose multiple canaries on the same external domain?
|
||||
|
||||
Assuming you have two apps, one that servers the main website and one that serves the REST API.
|
||||
For each app you can define a canary object as:
|
||||
Assuming you have two apps -- one that serves the main website and one that serves its REST API --
|
||||
you can define a canary object for each app as:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
@@ -714,11 +799,11 @@ Istio Pilot will
|
||||
[merge](https://istio.io/help/ops/traffic-management/deploy-guidelines/#multiple-virtual-services-and-destination-rules-for-the-same-host)
|
||||
the two services and the website rule will be moved to the end of the list in the merged configuration.
|
||||
|
||||
Note that host merging only works if the canaries are bounded to a ingress gateway other than the `mesh` gateway.
|
||||
Note that host merging only works if the canaries are bounded to an ingress gateway other than the `mesh` gateway.
|
||||
|
||||
## Istio Mutual TLS
|
||||
|
||||
**How can I enable mTLS for a canary?**
|
||||
#### How can I enable mTLS for a canary?
|
||||
|
||||
When deploying Istio with global mTLS enabled, you have to set the TLS mode to `ISTIO_MUTUAL`:
|
||||
|
||||
@@ -732,7 +817,7 @@ spec:
|
||||
mode: ISTIO_MUTUAL
|
||||
```
|
||||
|
||||
If you run Istio in permissive mode you can disable TLS:
|
||||
If you run Istio in permissive mode, you can disable TLS:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
@@ -744,13 +829,13 @@ spec:
|
||||
mode: DISABLE
|
||||
```
|
||||
|
||||
**If Flagger is outside of the mesh, how can it start the load test?**
|
||||
#### If Flagger is outside of the mesh, how can it start the load test?
|
||||
|
||||
In order for Flagger to be able to call the load tester service from outside the mesh,
|
||||
you need to disable mTLS on port 80:
|
||||
you need to disable mTLS:
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: flagger-loadtester
|
||||
@@ -761,14 +846,54 @@ spec:
|
||||
tls:
|
||||
mode: DISABLE
|
||||
---
|
||||
apiVersion: authentication.istio.io/v1alpha1
|
||||
kind: Policy
|
||||
apiVersion: security.istio.io/v1beta1
|
||||
kind: PeerAuthentication
|
||||
metadata:
|
||||
name: flagger-loadtester
|
||||
namespace: test
|
||||
spec:
|
||||
targets:
|
||||
- name: flagger-loadtester
|
||||
ports:
|
||||
- number: 80
|
||||
selector:
|
||||
matchLabels:
|
||||
app: flagger-loadtester
|
||||
mtls:
|
||||
mode: DISABLE
|
||||
```
|
||||
|
||||
## ExternalDNS
|
||||
|
||||
### Can I use annotations?
|
||||
|
||||
Flagger propagates annotations (and labels) to all the generated apex,
|
||||
primary and canary objects. This allows using external-dns annotations.
|
||||
|
||||
You can configure Flagger to set annotations with:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
service:
|
||||
apex:
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: "mydomain.com"
|
||||
primary:
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: "primary.mydomain.com"
|
||||
canary:
|
||||
annotations:
|
||||
external-dns.alpha.kubernetes.io/hostname: "canary.mydomain.com"
|
||||
```
|
||||
|
||||
### Multiple sources and Istio
|
||||
|
||||
**/!\\** The apex annotations are added to both the generated Kubernetes Services and the generated Istio
|
||||
VirtualServices objects. If you have configured external-dns to use both sources,
|
||||
this will create conflicts!
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
containers:
|
||||
args:
|
||||
- --source=service # choose only one
|
||||
- --source=istio-virtualservice # of these two
|
||||
```
|
||||
|
||||
[Checkout ExeternalDNS documentation](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/istio.md)
|
||||
|
||||
136
docs/gitbook/install/flagger-install-on-alibaba-servicemesh.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# Flagger Install on Alibaba ServiceMesh
|
||||
|
||||
This guide walks you through setting up Flagger on Alibaba ServiceMesh.
|
||||
|
||||
## Prerequisites
|
||||
- Created an ACK([Alibabacloud Container Service for Kubernetes](https://cs.console.aliyun.com)) cluster instance.
|
||||
- Created an ASM([Alibaba ServiceMesh](https://servicemesh.console.aliyun.com)) instance, and added ACK cluster.
|
||||
|
||||
### Variables declaration
|
||||
- `$ACK_CONFIG`: the kubeconfig file path of ACK, which be treated as`$HOME/.kube/config` in the rest of guide.
|
||||
- `$MESH_CONFIG`: the kubeconfig file path of ASM.
|
||||
- `$ISTIO_RELEASE`: see https://github.com/istio/istio/releases
|
||||
- `$FLAGGER_SRC`: see https://github.com/fluxcd/flagger
|
||||
|
||||
## Install Prometheus
|
||||
Install Prometheus:
|
||||
|
||||
```bash
|
||||
kubectl apply -f $ISTIO_RELEASE/samples/addons/prometheus.yaml
|
||||
```
|
||||
|
||||
it' same with the below cmd:
|
||||
|
||||
```bash
|
||||
kubectl --kubeconfig "$ACK_CONFIG" apply -f $ISTIO_RELEASE/samples/addons/prometheus.yaml
|
||||
```
|
||||
|
||||
Append the below configs to `scrape_configs` in prometheus configmap, to support telemetry:
|
||||
```yaml
|
||||
scrape_configs:
|
||||
# Mixer scrapping. Defaults to Prometheus and mixer on same namespace.
|
||||
- job_name: 'istio-mesh'
|
||||
kubernetes_sd_configs:
|
||||
- role: endpoints
|
||||
namespaces:
|
||||
names:
|
||||
- istio-system
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
|
||||
action: keep
|
||||
regex: istio-telemetry;prometheus
|
||||
# Scrape config for envoy stats
|
||||
- job_name: 'envoy-stats'
|
||||
metrics_path: /stats/prometheus
|
||||
kubernetes_sd_configs:
|
||||
- role: pod
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_pod_container_port_name]
|
||||
action: keep
|
||||
regex: '.*-envoy-prom'
|
||||
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
|
||||
action: replace
|
||||
regex: ([^:]+)(?::\d+)?;(\d+)
|
||||
replacement: $1:15090
|
||||
target_label: __address__
|
||||
- action: labeldrop
|
||||
regex: __meta_kubernetes_pod_label_(.+)
|
||||
- source_labels: [__meta_kubernetes_namespace]
|
||||
action: replace
|
||||
target_label: namespace
|
||||
- source_labels: [__meta_kubernetes_pod_name]
|
||||
action: replace
|
||||
target_label: pod_name
|
||||
- job_name: 'istio-policy'
|
||||
kubernetes_sd_configs:
|
||||
- role: endpoints
|
||||
namespaces:
|
||||
names:
|
||||
- istio-system
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
|
||||
action: keep
|
||||
regex: istio-policy;http-policy-monitoring
|
||||
- job_name: 'istio-telemetry'
|
||||
kubernetes_sd_configs:
|
||||
- role: endpoints
|
||||
namespaces:
|
||||
names:
|
||||
- istio-system
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
|
||||
action: keep
|
||||
regex: istio-telemetry;http-monitoring
|
||||
- job_name: 'pilot'
|
||||
kubernetes_sd_configs:
|
||||
- role: endpoints
|
||||
namespaces:
|
||||
names:
|
||||
- istio-system
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
|
||||
action: keep
|
||||
regex: istiod;http-monitoring
|
||||
- source_labels: [__meta_kubernetes_service_label_app]
|
||||
target_label: app
|
||||
- job_name: 'sidecar-injector'
|
||||
kubernetes_sd_configs:
|
||||
- role: endpoints
|
||||
namespaces:
|
||||
names:
|
||||
- istio-system
|
||||
relabel_configs:
|
||||
- source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
|
||||
action: keep
|
||||
regex: istio-sidecar-injector;http-monitoring
|
||||
```
|
||||
|
||||
## Install Flagger
|
||||
|
||||
Add Flagger Helm repository:
|
||||
|
||||
```bash
|
||||
helm repo add flagger https://flagger.app
|
||||
helm repo update
|
||||
```
|
||||
|
||||
Install Flagger's Canary CRD:
|
||||
|
||||
```yaml
|
||||
kubectl apply -f $FLAGGER_SRC/artifacts/flagger/crd.yaml
|
||||
```
|
||||
|
||||
Deploy Flagger for Alibaba ServiceMesh:
|
||||
|
||||
```bash
|
||||
cp $MESH_CONFIG kubeconfig
|
||||
kubectl -n istio-system create secret generic istio-kubeconfig --from-file kubeconfig
|
||||
kubectl -n istio-system label secret istio-kubeconfig istio/multiCluster=true
|
||||
helm upgrade -i flagger flagger/flagger \
|
||||
--namespace=istio-system \
|
||||
--set crd.create=false \
|
||||
--set meshProvider=istio \
|
||||
--set metricsServer=http://prometheus:9090 \
|
||||
--set istio.kubeconfig.secretName=istio-kubeconfig \
|
||||
--set istio.kubeconfig.key=kubeconfig
|
||||
```
|
||||
@@ -71,6 +71,16 @@ helm upgrade -i flagger flagger/flagger \
|
||||
--set metricsServer=http://appmesh-prometheus:9090
|
||||
```
|
||||
|
||||
Deploy Flagger for **Open Service Mesh (OSM)** (requires OSM to have been installed with Prometheus):
|
||||
|
||||
```console
|
||||
$ helm upgrade -i flagger flagger/flagger \
|
||||
--namespace=osm-system \
|
||||
--set crd.create=false \
|
||||
--set meshProvider=osm \
|
||||
--set metricsServer=http://osm-prometheus.osm-system.svc:7070
|
||||
```
|
||||
|
||||
You can install Flagger in any namespace as long as it can talk to the Prometheus service on port 9090.
|
||||
|
||||
For ingress controllers, the install instructions are:
|
||||
@@ -173,6 +183,14 @@ kustomize build https://github.com/fluxcd/flagger/kustomize/linkerd?ref=main | k
|
||||
|
||||
This deploys Flagger in the `linkerd` namespace and sets the metrics server URL to Linkerd's Prometheus instance.
|
||||
|
||||
Install Flagger for Open Service Mesh:
|
||||
|
||||
```bash
|
||||
kustomize build https://github.com/fluxcd/flagger/kustomize/osm?ref=main | kubectl apply -f -
|
||||
```
|
||||
|
||||
This deploys Flagger in the `osm-system` namespace and sets the metrics server URL to OSM's Prometheus instance.
|
||||
|
||||
If you want to install a specific Flagger release, add the version number to the URL:
|
||||
|
||||
```bash
|
||||
@@ -202,7 +220,7 @@ metadata:
|
||||
name: app
|
||||
namespace: test
|
||||
spec:
|
||||
# can be: kubernetes, istio, linkerd, appmesh, nginx, skipper, gloo, traefik
|
||||
# can be: kubernetes, istio, linkerd, appmesh, nginx, skipper, gloo, traefik, osm
|
||||
# use the kubernetes provider for Blue/Green style deployments
|
||||
provider: nginx
|
||||
```
|
||||
|
||||
@@ -337,7 +337,7 @@ A canary deployment can fail due to any of the following reasons:
|
||||
|
||||
* the container image can't be downloaded
|
||||
* the deployment replica set is stuck for more then ten minutes \(eg. due to a container crash loop\)
|
||||
* the webooks \(acceptance tests, helm tests, load tests, etc\) are returning a non 2xx response
|
||||
* the webhooks \(acceptance tests, helm tests, load tests, etc\) are returning a non 2xx response
|
||||
* the HTTP success rate \(non 5xx responses\) metric drops under the threshold
|
||||
* the HTTP average duration metric goes over the threshold
|
||||
* the Istio telemetry service is unable to collect traffic metrics
|
||||
|
||||
@@ -10,8 +10,8 @@ and Flagger to automate canary releases and A/B testing.
|
||||
Flagger requires a Kubernetes cluster **v1.16** or newer and Gloo Edge ingress **1.6.0** or newer.
|
||||
|
||||
This guide was written for Flagger version **1.6.0** or higher. Prior versions of Flagger
|
||||
used Gloo upstream groups to handle canaries, but newer versions of Flagger use Gloo
|
||||
route tables to handle canaries as well as A/B testing.
|
||||
used Gloo `UpstreamGroup`s to handle canaries, but newer versions of Flagger use Gloo
|
||||
`RouteTable`s to handle canaries as well as A/B testing.
|
||||
|
||||
Install Gloo with Helm v3:
|
||||
|
||||
@@ -36,7 +36,7 @@ helm upgrade -i flagger flagger/flagger \
|
||||
## Bootstrap
|
||||
|
||||
Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler (HPA),
|
||||
then creates a series of objects (Kubernetes deployments, ClusterIP services and Gloo route tables groups).
|
||||
then creates a series of objects (Kubernetes deployments, ClusterIP services, Gloo route tables and upstreams).
|
||||
These objects expose the application outside the cluster and drive the canary analysis and promotion.
|
||||
|
||||
Create a test namespace:
|
||||
@@ -94,6 +94,14 @@ metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
spec:
|
||||
# upstreamRef (optional)
|
||||
# defines an upstream to copy the spec from when flagger generates new upstreams.
|
||||
# necessary to copy over TLS config, circuit breakers, etc. (anything nonstandard)
|
||||
# upstreamRef:
|
||||
# apiVersion: gloo.solo.io/v1
|
||||
# kind: Upstream
|
||||
# name: podinfo-upstream
|
||||
# namespace: gloo-system
|
||||
provider: gloo
|
||||
# deployment reference
|
||||
targetRef:
|
||||
@@ -152,6 +160,8 @@ spec:
|
||||
cmd: "hey -z 2m -q 5 -c 2 -host app.example.com http://gateway-proxy.gloo-system"
|
||||
```
|
||||
|
||||
*Note: when using upstreamRef the following fields are copied over from the original upstream: `Labels, SslConfig, CircuitBreakers, ConnectionConfig, UseHttp2, InitialStreamWindowSize`*
|
||||
|
||||
Save the above resource as podinfo-canary.yaml and then apply it:
|
||||
|
||||
```bash
|
||||
@@ -174,6 +184,8 @@ service/podinfo
|
||||
service/podinfo-canary
|
||||
service/podinfo-primary
|
||||
routetables.gateway.solo.io/podinfo
|
||||
upstreams.gloo.solo.io/test-podinfo-canaryupstream-9898
|
||||
upstreams.gloo.solo.io/test-podinfo-primaryupstream-9898
|
||||
```
|
||||
|
||||
When the bootstrap finishes Flagger will set the canary status to initialized:
|
||||
|
||||
252
docs/gitbook/tutorials/kuma-progressive-delivery.md
Normal file
@@ -0,0 +1,252 @@
|
||||
# Kuma Canary Deployments
|
||||
|
||||
This guide shows you how to use Kuma and Flagger to automate canary deployments.
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
|
||||
Flagger requires a Kubernetes cluster **v1.16** or newer and Kuma **1.3** or newer.
|
||||
|
||||
Install Kuma and Prometheus (part of Kuma Metrics):
|
||||
|
||||
```bash
|
||||
kumactl install control-plane | kubectl apply -f -
|
||||
kumactl install metrics | kubectl apply -f -
|
||||
```
|
||||
|
||||
Install Flagger in the `kuma-system` namespace:
|
||||
|
||||
```bash
|
||||
kubectl apply -k github.com/fluxcd/flagger//kustomize/kuma
|
||||
```
|
||||
|
||||
## Bootstrap
|
||||
|
||||
Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler (HPA),
|
||||
then creates a series of objects (Kubernetes deployments, ClusterIP services and Kuma `TrafficRoute`).
|
||||
These objects expose the application inside the mesh and drive the canary analysis and promotion.
|
||||
|
||||
Create a test namespace and enable Kuma sidecar injection:
|
||||
|
||||
```bash
|
||||
kubectl create ns test
|
||||
kubectl annotate namespace test kuma.io/sidecar-injection=enabled
|
||||
```
|
||||
|
||||
Install the load testing service to generate traffic during the canary analysis:
|
||||
|
||||
```bash
|
||||
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/tester?ref=main
|
||||
```
|
||||
|
||||
Create a deployment and a horizontal pod autoscaler:
|
||||
|
||||
```bash
|
||||
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main
|
||||
```
|
||||
|
||||
Create a canary custom resource for the `podinfo` deployment:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
annotations:
|
||||
kuma.io/mesh: default
|
||||
spec:
|
||||
targetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
progressDeadlineSeconds: 60
|
||||
service:
|
||||
port: 9898
|
||||
targetPort: 9898
|
||||
apex:
|
||||
annotations:
|
||||
9898.service.kuma.io/protocol: "http"
|
||||
canary:
|
||||
annotations:
|
||||
9898.service.kuma.io/protocol: "http"
|
||||
primary:
|
||||
annotations:
|
||||
9898.service.kuma.io/protocol: "http"
|
||||
analysis:
|
||||
# schedule interval (default 60s)
|
||||
interval: 30s
|
||||
# max number of failed metric checks before rollback
|
||||
threshold: 5
|
||||
# max traffic percentage routed to canary
|
||||
# percentage (0-100)
|
||||
maxWeight: 50
|
||||
# canary increment step
|
||||
# percentage (0-100)
|
||||
stepWeight: 5
|
||||
metrics:
|
||||
- name: request-success-rate
|
||||
threshold: 99
|
||||
interval: 1m
|
||||
- name: request-duration
|
||||
threshold: 500
|
||||
interval: 30s
|
||||
webhooks:
|
||||
- name: acceptance-test
|
||||
type: pre-rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
timeout: 30s
|
||||
metadata:
|
||||
type: bash
|
||||
cmd: "curl -sd 'test' http://podinfo-canary.test:9898/token | grep token"
|
||||
- name: load-test
|
||||
type: rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
metadata:
|
||||
cmd: "hey -z 2m -q 10 -c 2 http://podinfo-canary.test:9898/"
|
||||
```
|
||||
|
||||
Save the above resource as `podinfo-canary.yaml` and then apply it:
|
||||
|
||||
```bash
|
||||
kubectl apply -f ./podinfo-canary.yaml
|
||||
```
|
||||
|
||||
When the canary analysis starts, Flagger will call the pre-rollout webhooks before routing traffic to the canary. The canary analysis will run for five minutes while validating the HTTP metrics and rollout hooks every half a minute.
|
||||
|
||||
After a couple of seconds Flagger will create the canary objects:
|
||||
|
||||
```bash
|
||||
# applied
|
||||
deployment.apps/podinfo
|
||||
horizontalpodautoscaler.autoscaling/podinfo
|
||||
ingresses.extensions/podinfo
|
||||
canary.flagger.app/podinfo
|
||||
|
||||
# generated
|
||||
deployment.apps/podinfo-primary
|
||||
horizontalpodautoscaler.autoscaling/podinfo-primary
|
||||
service/podinfo
|
||||
service/podinfo-canary
|
||||
service/podinfo-primary
|
||||
trafficroutes.kuma.io/podinfo
|
||||
```
|
||||
|
||||
After the boostrap, the podinfo deployment will be scaled to zero and the traffic to `podinfo.test` will be routed to the primary pods. During the canary analysis, the `podinfo-canary.test` address can be used to target directly the canary pods.
|
||||
|
||||
## Automated canary promotion
|
||||
|
||||
Flagger implements a control loop that gradually shifts traffic to the canary while measuring key performance indicators like HTTP requests success rate, requests average duration and pod health. Based on analysis of the KPIs a canary is promoted or aborted, and the analysis result is published to Slack.
|
||||
|
||||

|
||||
|
||||
Trigger a canary deployment by updating the container image:
|
||||
|
||||
```bash
|
||||
kubectl -n test set image deployment/podinfo \
|
||||
podinfod=stefanprodan/podinfo:3.1.1
|
||||
```
|
||||
|
||||
Flagger detects that the deployment revision changed and starts a new rollout:
|
||||
|
||||
```text
|
||||
kubectl -n test describe canary/podinfo
|
||||
|
||||
Status:
|
||||
Canary Weight: 0
|
||||
Failed Checks: 0
|
||||
Phase: Succeeded
|
||||
Events:
|
||||
New revision detected! Scaling up podinfo.test
|
||||
Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available
|
||||
Pre-rollout check acceptance-test passed
|
||||
Advance podinfo.test canary weight 5
|
||||
Advance podinfo.test canary weight 10
|
||||
Advance podinfo.test canary weight 15
|
||||
Advance podinfo.test canary weight 20
|
||||
Advance podinfo.test canary weight 25
|
||||
Waiting for podinfo.test rollout to finish: 1 of 2 updated replicas are available
|
||||
Advance podinfo.test canary weight 30
|
||||
Advance podinfo.test canary weight 35
|
||||
Advance podinfo.test canary weight 40
|
||||
Advance podinfo.test canary weight 45
|
||||
Advance podinfo.test canary weight 50
|
||||
Copying podinfo.test template spec to podinfo-primary.test
|
||||
Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available
|
||||
Promotion completed! Scaling down podinfo.test
|
||||
```
|
||||
|
||||
**Note** that if you apply new changes to the deployment during the canary analysis, Flagger will restart the analysis.
|
||||
|
||||
A canary deployment is triggered by changes in any of the following objects:
|
||||
|
||||
* Deployment PodSpec \(container image, command, ports, env, resources, etc\)
|
||||
* ConfigMaps mounted as volumes or mapped to environment variables
|
||||
* Secrets mounted as volumes or mapped to environment variables
|
||||
|
||||
You can monitor all canaries with:
|
||||
|
||||
```bash
|
||||
watch kubectl get canaries --all-namespaces
|
||||
|
||||
NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME
|
||||
test podinfo Progressing 15 2019-06-30T14:05:07Z
|
||||
prod frontend Succeeded 0 2019-06-30T16:15:07Z
|
||||
prod backend Failed 0 2019-06-30T17:05:07Z
|
||||
```
|
||||
|
||||
## Automated rollback
|
||||
|
||||
During the canary analysis you can generate HTTP 500 errors and high latency to test if Flagger pauses and rolls back the faulted version.
|
||||
|
||||
Trigger another canary deployment:
|
||||
|
||||
```bash
|
||||
kubectl -n test set image deployment/podinfo \
|
||||
podinfod=stefanprodan/podinfo:3.1.2
|
||||
```
|
||||
|
||||
Exec into the load tester pod with:
|
||||
|
||||
```bash
|
||||
kubectl -n test exec -it flagger-loadtester-xx-xx sh
|
||||
```
|
||||
|
||||
Generate HTTP 500 errors:
|
||||
|
||||
```bash
|
||||
watch -n 1 curl http://podinfo-canary.test:9898/status/500
|
||||
```
|
||||
|
||||
Generate latency:
|
||||
|
||||
```bash
|
||||
watch -n 1 curl http://podinfo-canary.test:9898/delay/1
|
||||
```
|
||||
|
||||
When the number of failed checks reaches the canary analysis threshold, the traffic is routed back to the primary, the canary is scaled to zero and the rollout is marked as failed.
|
||||
|
||||
```text
|
||||
kubectl -n test describe canary/podinfo
|
||||
|
||||
Status:
|
||||
Canary Weight: 0
|
||||
Failed Checks: 10
|
||||
Phase: Failed
|
||||
Events:
|
||||
Starting canary analysis for podinfo.test
|
||||
Pre-rollout check acceptance-test passed
|
||||
Advance podinfo.test canary weight 5
|
||||
Advance podinfo.test canary weight 10
|
||||
Advance podinfo.test canary weight 15
|
||||
Halt podinfo.test advancement success rate 69.17% < 99%
|
||||
Halt podinfo.test advancement success rate 61.39% < 99%
|
||||
Halt podinfo.test advancement success rate 55.06% < 99%
|
||||
Halt podinfo.test advancement request duration 1.20s > 0.5s
|
||||
Halt podinfo.test advancement request duration 1.45s > 0.5s
|
||||
Rolling back podinfo.test failed checks threshold reached 5
|
||||
Canary failed! Scaling down podinfo.test
|
||||
```
|
||||
|
||||
The above procedures can be extended with [custom metrics](../usage/metrics.md) checks, [webhooks](../usage/webhooks.md), [manual promotion](../usage/webhooks.md#manual-gating) approval and [Slack or MS Teams](../usage/alerting.md) notifications.
|
||||
@@ -6,7 +6,14 @@ This guide shows you how to use Linkerd and Flagger to automate canary deploymen
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Flagger requires a Kubernetes cluster **v1.16** or newer and Linkerd **2.4** or newer.
|
||||
Flagger requires a Kubernetes cluster **v1.16** or newer and Linkerd **2.10** or newer.
|
||||
|
||||
Install Linkerd the Promethues (part of Linkerd Viz):
|
||||
|
||||
```bash
|
||||
linkerd install | kubectl apply -f -
|
||||
linkerd viz install | kubectl apply -f -
|
||||
```
|
||||
|
||||
Install Flagger in the linkerd namespace:
|
||||
|
||||
@@ -14,11 +21,11 @@ Install Flagger in the linkerd namespace:
|
||||
kubectl apply -k github.com/fluxcd/flagger//kustomize/linkerd
|
||||
```
|
||||
|
||||
Note that you'll need kubectl 1.14 or newer to run the above command.
|
||||
|
||||
## Bootstrap
|
||||
|
||||
Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler \(HPA\), then creates a series of objects \(Kubernetes deployments, ClusterIP services and SMI traffic split\). These objects expose the application inside the mesh and drive the canary analysis and promotion.
|
||||
Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler (HPA),
|
||||
then creates a series of objects (Kubernetes deployments, ClusterIP services and SMI traffic split).
|
||||
These objects expose the application inside the mesh and drive the canary analysis and promotion.
|
||||
|
||||
Create a test namespace and enable Linkerd proxy injection:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This guide shows you how to use the NGINX ingress controller and Flagger to auto
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Flagger requires a Kubernetes cluster **v1.16** or newer and NGINX ingress **v0.41** or newer.
|
||||
Flagger requires a Kubernetes cluster **v1.19** or newer and NGINX ingress **v1.0.2** or newer.
|
||||
|
||||
Install the NGINX ingress controller with Helm v3:
|
||||
|
||||
@@ -59,7 +59,7 @@ helm upgrade -i flagger-loadtester flagger/loadtester \
|
||||
Create an ingress definition (replace `app.example.com` with your own domain):
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: podinfo
|
||||
@@ -70,12 +70,16 @@ metadata:
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
spec:
|
||||
rules:
|
||||
- host: app.example.com
|
||||
- host: "app.example.com"
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: podinfo
|
||||
servicePort: 80
|
||||
- pathType: Prefix
|
||||
path: "/"
|
||||
backend:
|
||||
service:
|
||||
name: podinfo
|
||||
port:
|
||||
number: 80
|
||||
```
|
||||
|
||||
Save the above resource as podinfo-ingress.yaml and then apply it:
|
||||
@@ -101,7 +105,7 @@ spec:
|
||||
name: podinfo
|
||||
# ingress reference
|
||||
ingressRef:
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
name: podinfo
|
||||
# HPA reference (optional)
|
||||
|
||||
363
docs/gitbook/tutorials/osm-progressive-delivery.md
Normal file
@@ -0,0 +1,363 @@
|
||||
# Open Service Mesh Canary Deployments
|
||||
|
||||
This guide shows you how to use Open Service Mesh (OSM) and Flagger to automate canary deployments.
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
|
||||
Flagger requires a Kubernetes cluster **v1.16** or newer and Open Service Mesh **0.9.1** or newer.
|
||||
|
||||
OSM must have permissive traffic policy enabled and have an instance of Prometheus for metrics.
|
||||
|
||||
- If the OSM CLI is being used for installation, install OSM using the following command:
|
||||
```bash
|
||||
osm install \
|
||||
--set=OpenServiceMesh.deployPrometheus=true \
|
||||
--set=OpenServiceMesh.enablePermissiveTrafficPolicy=true
|
||||
```
|
||||
- If a managed instance of OSM is being used:
|
||||
- [Bring your own instance](docs.openservicemesh.io/docs/guides/observability/metrics/#byo-prometheus) of Prometheus,
|
||||
setting the namespace to match the managed OSM controller namespace
|
||||
- Enable permissive traffic policy after installation by updating the OSM MeshConfig resource:
|
||||
```bash
|
||||
# Replace <osm-namespace> with OSM controller's namespace
|
||||
kubectl patch meshconfig osm-mesh-config -n <osm-namespace> -p '{"spec":{"traffic":{"enablePermissiveTrafficPolicyMode":true}}}' --type=merge
|
||||
```
|
||||
|
||||
To install Flagger in the default `osm-system` namespace, use:
|
||||
```bash
|
||||
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/osm?ref=main
|
||||
```
|
||||
|
||||
Alternatively, if a non-default namespace or managed instance of OSM is in use, install Flagger with Helm, replacing the <osm-namespace>
|
||||
values as appropriate. If a custom instance of Prometheus is being used, replace `osm-prometheus` with the relevant Prometheus service name.
|
||||
```bash
|
||||
helm upgrade -i flagger flagger/flagger \
|
||||
--namespace=<osm-namespace> \
|
||||
--set meshProvider=osm \
|
||||
--set metricsServer=http://osm-prometheus.<osm-namespace>.svc:7070
|
||||
```
|
||||
|
||||
## Bootstrap
|
||||
|
||||
Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler (HPA),
|
||||
then creates a series of objects (Kubernetes deployments, ClusterIP services and SMI traffic split).
|
||||
These objects expose the application inside the mesh and drive the canary analysis and promotion.
|
||||
|
||||
Create a `test` namespace and enable OSM namespace monitoring and metrics scraping for the namespace.
|
||||
|
||||
```bash
|
||||
kubectl create namespace test
|
||||
osm namespace add test
|
||||
osm metrics enable --namespace test
|
||||
```
|
||||
|
||||
Create a `podinfo` deployment and a horizontal pod autoscaler:
|
||||
|
||||
```bash
|
||||
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main
|
||||
```
|
||||
|
||||
Install the load testing service to generate traffic during the canary analysis:
|
||||
|
||||
```bash
|
||||
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/tester?ref=main
|
||||
```
|
||||
|
||||
Create a canary custom resource for the `podinfo` deployment.
|
||||
The following `podinfo` canary custom resource instructs Flagger to:
|
||||
1. monitor any changes to the `podinfo` deployment created earlier,
|
||||
2. detect `podinfo` deployment revision changes, and
|
||||
3. start a Flagger canary analysis, rollout, and promotion if there were deployment revision changes.
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: Canary
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: test
|
||||
spec:
|
||||
provider: osm
|
||||
# deployment reference
|
||||
targetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
# HPA reference (optional)
|
||||
autoscalerRef:
|
||||
apiVersion: autoscaling/v2beta2
|
||||
kind: HorizontalPodAutoscaler
|
||||
name: podinfo
|
||||
# the maximum time in seconds for the canary deployment
|
||||
# to make progress before it is rolled back (default 600s)
|
||||
progressDeadlineSeconds: 60
|
||||
service:
|
||||
# ClusterIP port number
|
||||
port: 9898
|
||||
# container port number or name (optional)
|
||||
targetPort: 9898
|
||||
analysis:
|
||||
# schedule interval (default 60s)
|
||||
interval: 30s
|
||||
# max number of failed metric checks before rollback
|
||||
threshold: 5
|
||||
# max traffic percentage routed to canary
|
||||
# percentage (0-100)
|
||||
maxWeight: 50
|
||||
# canary increment step
|
||||
# percentage (0-100)
|
||||
stepWeight: 5
|
||||
# OSM Prometheus checks
|
||||
metrics:
|
||||
- name: request-success-rate
|
||||
# minimum req success rate (non 5xx responses)
|
||||
# percentage (0-100)
|
||||
thresholdRange:
|
||||
min: 99
|
||||
interval: 1m
|
||||
- name: request-duration
|
||||
# maximum req duration P99
|
||||
# milliseconds
|
||||
thresholdRange:
|
||||
max: 500
|
||||
interval: 30s
|
||||
# testing (optional)
|
||||
webhooks:
|
||||
- name: acceptance-test
|
||||
type: pre-rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
timeout: 30s
|
||||
metadata:
|
||||
type: bash
|
||||
cmd: "curl -sd 'test' http://podinfo-canary.test:9898/token | grep token"
|
||||
- name: load-test
|
||||
type: rollout
|
||||
url: http://flagger-loadtester.test/
|
||||
timeout: 5s
|
||||
metadata:
|
||||
cmd: "hey -z 2m -q 10 -c 2 http://podinfo-canary.test:9898/"
|
||||
```
|
||||
|
||||
Save the above resource as podinfo-canary.yaml and then apply it:
|
||||
|
||||
```bash
|
||||
kubectl apply -f ./podinfo-canary.yaml
|
||||
```
|
||||
|
||||
When the canary analysis starts, Flagger will call the pre-rollout webhooks before routing traffic to the canary.
|
||||
The canary analysis will run for five minutes while validating the HTTP metrics and rollout hooks every half a minute.
|
||||
|
||||
After a couple of seconds Flagger will create the canary objects.
|
||||
|
||||
```bash
|
||||
# applied
|
||||
deployment.apps/podinfo
|
||||
horizontalpodautoscaler.autoscaling/podinfo
|
||||
ingresses.extensions/podinfo
|
||||
canary.flagger.app/podinfo
|
||||
|
||||
# generated
|
||||
deployment.apps/podinfo-primary
|
||||
horizontalpodautoscaler.autoscaling/podinfo-primary
|
||||
service/podinfo
|
||||
service/podinfo-canary
|
||||
service/podinfo-primary
|
||||
trafficsplits.split.smi-spec.io/podinfo
|
||||
```
|
||||
|
||||
After the boostrap, the `podinfo` deployment will be scaled to zero and the traffic to `podinfo.test` will be routed to the primary pods.
|
||||
During the canary analysis, the `podinfo-canary.test` address can be used to target directly the canary pods.
|
||||
|
||||
## Automated Canary Promotion
|
||||
|
||||
Flagger implements a control loop that gradually shifts traffic to the canary while measuring key performance indicators like HTTP requests success rate, requests average duration and pod health.
|
||||
Based on analysis of the KPIs a canary is promoted or aborted.
|
||||
|
||||

|
||||
|
||||
Trigger a canary deployment by updating the container image:
|
||||
|
||||
```bash
|
||||
kubectl -n test set image deployment/podinfo \
|
||||
podinfod=stefanprodan/podinfo:3.1.1
|
||||
```
|
||||
|
||||
Flagger detects that the deployment revision changed and starts a new rollout.
|
||||
|
||||
|
||||
```text
|
||||
kubectl -n test describe canary/podinfo
|
||||
|
||||
Status:
|
||||
Canary Weight: 0
|
||||
Failed Checks: 0
|
||||
Phase: Succeeded
|
||||
Events:
|
||||
New revision detected! Scaling up podinfo.test
|
||||
Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available
|
||||
Pre-rollout check acceptance-test passed
|
||||
Advance podinfo.test canary weight 5
|
||||
Advance podinfo.test canary weight 10
|
||||
Advance podinfo.test canary weight 15
|
||||
Advance podinfo.test canary weight 20
|
||||
Advance podinfo.test canary weight 25
|
||||
Waiting for podinfo.test rollout to finish: 1 of 2 updated replicas are available
|
||||
Advance podinfo.test canary weight 30
|
||||
Advance podinfo.test canary weight 35
|
||||
Advance podinfo.test canary weight 40
|
||||
Advance podinfo.test canary weight 45
|
||||
Advance podinfo.test canary weight 50
|
||||
Copying podinfo.test template spec to podinfo-primary.test
|
||||
Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available
|
||||
Promotion completed! Scaling down podinfo.test
|
||||
```
|
||||
|
||||
**Note** that if you apply any new changes to the `podinfo` deployment during the canary analysis, Flagger will restart the analysis.
|
||||
|
||||
A canary deployment is triggered by changes in any of the following objects:
|
||||
|
||||
* Deployment PodSpec \(container image, command, ports, env, resources, etc\)
|
||||
* ConfigMaps mounted as volumes or mapped to environment variables
|
||||
* Secrets mounted as volumes or mapped to environment variables
|
||||
|
||||
You can monitor all canaries with:
|
||||
|
||||
```bash
|
||||
watch kubectl get canaries --all-namespaces
|
||||
|
||||
NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME
|
||||
test podinfo Progressing 15 2019-06-30T14:05:07Z
|
||||
prod frontend Succeeded 0 2019-06-30T16:15:07Z
|
||||
prod backend Failed 0 2019-06-30T17:05:07Z
|
||||
```
|
||||
|
||||
## Automated Rollback
|
||||
|
||||
During the canary analysis you can generate HTTP 500 errors and high latency to test if Flagger pauses and rolls back the faulted version.
|
||||
|
||||
Trigger another canary deployment:
|
||||
|
||||
```bash
|
||||
kubectl -n test set image deployment/podinfo \
|
||||
podinfod=stefanprodan/podinfo:3.1.2
|
||||
```
|
||||
|
||||
Exec into the load tester pod with:
|
||||
|
||||
```bash
|
||||
kubectl -n test exec -it flagger-loadtester-xx-xx sh
|
||||
```
|
||||
|
||||
Repeatedly generate HTTP 500 errors until the `kubectl describe` output below shows canary rollout failure:
|
||||
|
||||
```bash
|
||||
watch -n 0.1 curl http://podinfo-canary.test:9898/status/500
|
||||
```
|
||||
|
||||
Repeatedly generate latency until canary rollout fails:
|
||||
|
||||
```bash
|
||||
watch -n 0.1 curl http://podinfo-canary.test:9898/delay/1
|
||||
```
|
||||
|
||||
When the number of failed checks reaches the canary analysis thresholds defined in the `podinfo` canary custom resource earlier, the traffic is routed back to the primary, the canary is scaled to zero and the rollout is marked as failed.
|
||||
|
||||
```text
|
||||
kubectl -n test describe canary/podinfo
|
||||
|
||||
Status:
|
||||
Canary Weight: 0
|
||||
Failed Checks: 10
|
||||
Phase: Failed
|
||||
Events:
|
||||
Starting canary analysis for podinfo.test
|
||||
Pre-rollout check acceptance-test passed
|
||||
Advance podinfo.test canary weight 5
|
||||
Advance podinfo.test canary weight 10
|
||||
Advance podinfo.test canary weight 15
|
||||
Halt podinfo.test advancement success rate 69.17% < 99%
|
||||
Halt podinfo.test advancement success rate 61.39% < 99%
|
||||
Halt podinfo.test advancement success rate 55.06% < 99%
|
||||
Halt podinfo.test advancement request duration 1.20s > 0.5s
|
||||
Halt podinfo.test advancement request duration 1.45s > 0.5s
|
||||
Rolling back podinfo.test failed checks threshold reached 5
|
||||
Canary failed! Scaling down podinfo.test
|
||||
```
|
||||
|
||||
## Custom Metrics
|
||||
|
||||
The canary analysis can be extended with Prometheus queries.
|
||||
|
||||
Let's define a check for 404 not found errors.
|
||||
Edit the canary analysis (`podinfo-canary.yaml` file) and add the following metric.
|
||||
For more information on creating additional custom metrics using OSM metrics, please check the [metrics available in OSM](https://docs.openservicemesh.io/docs/guides/observability/metrics/#available-metrics).
|
||||
|
||||
```yaml
|
||||
analysis:
|
||||
metrics:
|
||||
- name: "404s percentage"
|
||||
threshold: 3
|
||||
query: |
|
||||
100 - (
|
||||
sum(
|
||||
rate(
|
||||
osm_request_total{
|
||||
destination_namespace="test",
|
||||
destination_kind="Deployment",
|
||||
destination_name="podinfo",
|
||||
response_code!="404"
|
||||
}[1m]
|
||||
)
|
||||
)
|
||||
/
|
||||
sum(
|
||||
rate(
|
||||
osm_request_total{
|
||||
destination_namespace="test",
|
||||
destination_kind="Deployment",
|
||||
destination_name="podinfo"
|
||||
}[1m]
|
||||
)
|
||||
) * 100
|
||||
)
|
||||
```
|
||||
|
||||
The above configuration validates the canary version by checking if the HTTP 404 req/sec percentage is below three percent of the total traffic.
|
||||
If the 404s rate reaches the 3% threshold, then the analysis is aborted and the canary is marked as failed.
|
||||
|
||||
Trigger a canary deployment by updating the container image:
|
||||
|
||||
```bash
|
||||
kubectl -n test set image deployment/podinfo \
|
||||
podinfod=stefanprodan/podinfo:3.1.3
|
||||
```
|
||||
|
||||
Exec into the load tester pod with:
|
||||
|
||||
```bash
|
||||
kubectl -n test exec -it flagger-loadtester-xx-xx sh
|
||||
```
|
||||
|
||||
Repeatedly generate 404s until canary rollout fails:
|
||||
|
||||
```bash
|
||||
watch -n 0.1 curl http://podinfo-canary.test:9898/status/404
|
||||
```
|
||||
|
||||
Watch Flagger logs to confirm successful canary rollback.
|
||||
|
||||
```text
|
||||
kubectl -n osm-system logs deployment/flagger -f | jq .msg
|
||||
|
||||
Starting canary deployment for podinfo.test
|
||||
Pre-rollout check acceptance-test passed
|
||||
Advance podinfo.test canary weight 5
|
||||
Halt podinfo.test advancement 404s percentage 6.20 > 3
|
||||
Halt podinfo.test advancement 404s percentage 6.45 > 3
|
||||
Halt podinfo.test advancement 404s percentage 7.22 > 3
|
||||
Halt podinfo.test advancement 404s percentage 6.50 > 3
|
||||
Halt podinfo.test advancement 404s percentage 6.34 > 3
|
||||
Rolling back podinfo.test failed checks threshold reached 5
|
||||
Canary failed! Scaling down podinfo.test
|
||||
```
|
||||
@@ -6,7 +6,7 @@ This guide shows you how to use the [Skipper ingress controller](https://opensou
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Flagger requires a Kubernetes cluster **v1.16** or newer and Skipper ingress **0.11.40** or newer.
|
||||
Flagger requires a Kubernetes cluster **v1.19** or newer and Skipper ingress **v0.13** or newer.
|
||||
|
||||
Install Skipper ingress-controller using [upstream definition](https://opensource.zalando.com/skipper/kubernetes/ingress-controller/#install-skipper-as-ingress-controller).
|
||||
|
||||
@@ -36,7 +36,9 @@ kustomize build https://github.com/fluxcd/flagger/kustomize/kubernetes | kubectl
|
||||
|
||||
## Bootstrap
|
||||
|
||||
Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler \(HPA\), then creates a series of objects \(Kubernetes deployments, ClusterIP services and canary ingress\). These objects expose the application outside the cluster and drive the canary analysis and promotion.
|
||||
Flagger takes a Kubernetes deployment and optionally a horizontal pod autoscaler (HPA),
|
||||
then creates a series of objects (Kubernetes deployments, ClusterIP services and canary ingress).
|
||||
These objects expose the application outside the cluster and drive the canary analysis and promotion.
|
||||
|
||||
Create a test namespace:
|
||||
|
||||
@@ -60,7 +62,7 @@ helm upgrade -i flagger-loadtester flagger/loadtester \
|
||||
Create an ingress definition \(replace `app.example.com` with your own domain\):
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: podinfo
|
||||
@@ -71,12 +73,16 @@ metadata:
|
||||
kubernetes.io/ingress.class: "skipper"
|
||||
spec:
|
||||
rules:
|
||||
- host: app.example.com
|
||||
- host: "app.example.com"
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: podinfo
|
||||
servicePort: 80
|
||||
- pathType: Prefix
|
||||
path: "/"
|
||||
backend:
|
||||
service:
|
||||
name: podinfo
|
||||
port:
|
||||
number: 80
|
||||
```
|
||||
|
||||
Save the above resource as podinfo-ingress.yaml and then apply it:
|
||||
@@ -85,7 +91,7 @@ Save the above resource as podinfo-ingress.yaml and then apply it:
|
||||
kubectl apply -f ./podinfo-ingress.yaml
|
||||
```
|
||||
|
||||
Create a canary custom resource \(replace `app.example.com` with your own domain\):
|
||||
Create a canary custom resource (replace `app.example.com` with your own domain):
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
@@ -102,7 +108,7 @@ spec:
|
||||
name: podinfo
|
||||
# ingress reference
|
||||
ingressRef:
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
name: podinfo
|
||||
# HPA reference (optional)
|
||||
@@ -190,7 +196,9 @@ ingress.networking.k8s.io/podinfo-canary
|
||||
|
||||
## Automated canary promotion
|
||||
|
||||
Flagger implements a control loop that gradually shifts traffic to the canary while measuring key performance indicators like HTTP requests success rate, requests average duration and pod health. Based on analysis of the KPIs a canary is promoted or aborted, and the analysis result is published to Slack or MS Teams.
|
||||
Flagger implements a control loop that gradually shifts traffic to the canary while measuring
|
||||
key performance indicators like HTTP requests success rate, requests average duration and pod health.
|
||||
Based on analysis of the KPIs a canary is promoted or aborted, and the analysis result is published to Slack or MS Teams.
|
||||
|
||||

|
||||
|
||||
@@ -271,7 +279,8 @@ Generate latency:
|
||||
watch -n 1 curl http://app.example.com/delay/1
|
||||
```
|
||||
|
||||
When the number of failed checks reaches the canary analysis threshold, the traffic is routed back to the primary, the canary is scaled to zero and the rollout is marked as failed.
|
||||
When the number of failed checks reaches the canary analysis threshold, the traffic is routed back to the primary,
|
||||
the canary is scaled to zero and the rollout is marked as failed.
|
||||
|
||||
```text
|
||||
kubectl -n flagger-system logs deploy/flagger -f | jq .msg
|
||||
@@ -333,7 +342,8 @@ Edit the canary analysis and add the latency check:
|
||||
interval: 1m
|
||||
```
|
||||
|
||||
The threshold is set to 500ms so if the average request duration in the last minute goes over half a second then the analysis will fail and the canary will not be promoted.
|
||||
The threshold is set to 500ms so if the average request duration in the last minute goes over half a second
|
||||
then the analysis will fail and the canary will not be promoted.
|
||||
|
||||
Trigger a canary deployment by updating the container image:
|
||||
|
||||
@@ -367,4 +377,3 @@ Canary failed! Scaling down podinfo.test
|
||||
```
|
||||
|
||||
If you have alerting configured, Flagger will send a notification with the reason why the canary failed.
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
This guide shows you how to use the [Traefik](https://doc.traefik.io/traefik/) and Flagger to automate canary deployments.
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
|
||||
Flagger requires a Kubernetes cluster **v1.16** or newer and Traefik **v2.3** or newer.
|
||||
@@ -11,9 +13,17 @@ Install Traefik with Helm v3:
|
||||
```bash
|
||||
helm repo add traefik https://helm.traefik.io/traefik
|
||||
kubectl create ns traefik
|
||||
helm upgrade -i traefik traefik/traefik \
|
||||
--namespace traefik \
|
||||
--set additionalArguments="--metrics.prometheus=true"
|
||||
|
||||
cat <<EOF | helm upgrade -i traefik traefik/traefik --namespace traefik -f -
|
||||
deployment:
|
||||
podAnnotations:
|
||||
prometheus.io/port: "9100"
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/path: "/metrics"
|
||||
metrics:
|
||||
prometheus:
|
||||
entryPoint: metrics
|
||||
EOF
|
||||
```
|
||||
|
||||
Install Flagger and the Prometheus add-on in the same namespace as Traefik:
|
||||
|
||||
@@ -5,13 +5,25 @@ You can define a global alert provider at install time or configure alerts on a
|
||||
|
||||
## Global configuration
|
||||
|
||||
Flagger can be configured to send Slack notifications:
|
||||
### Slack
|
||||
|
||||
#### Slack Configuration
|
||||
|
||||
Flagger requires a custom webhook integration from slack, instead of the new slack app system.
|
||||
|
||||
The webhook can be generated by following the [legacy slack documentation](https://api.slack.com/legacy/custom-integrations/messaging/webhooks)
|
||||
|
||||
#### Flagger configuration
|
||||
|
||||
Once the webhook has been generated. Flagger can be configured to send Slack notifications:
|
||||
|
||||
```bash
|
||||
helm upgrade -i flagger flagger/flagger \
|
||||
--set slack.url=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \
|
||||
--set slack.proxy=my-http-proxy.com \ # optional http/s proxy
|
||||
--set slack.channel=general \
|
||||
--set slack.user=flagger
|
||||
--set slack.user=flagger \
|
||||
--set clusterName=my-cluster
|
||||
```
|
||||
|
||||
Once configured with a Slack incoming **webhook**,
|
||||
@@ -25,11 +37,14 @@ or if the analysis reached the maximum number of failed checks:
|
||||
|
||||

|
||||
|
||||
### Microsoft Teams
|
||||
|
||||
Flagger can be configured to send notifications to Microsoft Teams:
|
||||
|
||||
```bash
|
||||
helm upgrade -i flagger flagger/flagger \
|
||||
--set msteams.url=https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK
|
||||
--set msteams.url=https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK \
|
||||
--set msteams.proxy-url=my-http-proxy.com # optional http/s proxy
|
||||
```
|
||||
|
||||
Similar to Slack, Flagger alerts on canary analysis events:
|
||||
@@ -59,6 +74,8 @@ spec:
|
||||
username: flagger
|
||||
# webhook address (ignored if secretRef is specified)
|
||||
address: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
|
||||
# optional http/s proxy
|
||||
proxy: http://my-http-proxy.com
|
||||
# secret containing the webhook address (optional)
|
||||
secretRef:
|
||||
name: on-call-url
|
||||
@@ -111,6 +128,9 @@ Alert fields:
|
||||
When the severity is set to `warn`, Flagger will alert when waiting on manual confirmation or if the analysis fails.
|
||||
When the severity is set to `error`, Flagger will alert only if the canary analysis fails.
|
||||
|
||||
To differentiate alerts based on the cluster name, you can configure Flagger with the `-cluster-name=my-cluster`
|
||||
command flag, or with Helm `--set clusterName=my-cluster`.
|
||||
|
||||
## Prometheus Alert Manager
|
||||
|
||||
You can use Alertmanager to trigger alerts when a canary deployment failed:
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
Flagger can run automated application analysis, promotion and rollback for the following deployment strategies:
|
||||
|
||||
* **Canary Release** \(progressive traffic shifting\)
|
||||
* Istio, Linkerd, App Mesh, NGINX, Skipper, Contour, Gloo Edge, Traefik
|
||||
* Istio, Linkerd, App Mesh, NGINX, Skipper, Contour, Gloo Edge, Traefik, Open Service Mesh, Kuma
|
||||
* **A/B Testing** \(HTTP headers and cookies traffic routing\)
|
||||
* Istio, App Mesh, NGINX, Contour, Gloo Edge
|
||||
* **Blue/Green** \(traffic switching\)
|
||||
* Kubernetes CNI, Istio, Linkerd, App Mesh, NGINX, Contour, Gloo Edge
|
||||
* Kubernetes CNI, Istio, Linkerd, App Mesh, NGINX, Contour, Gloo Edge, Open Service Mesh
|
||||
* **Blue/Green Mirroring** \(traffic shadowing\)
|
||||
* Istio
|
||||
|
||||
@@ -326,7 +326,7 @@ Blue/Green rollout steps for service mesh:
|
||||
* run conformance tests for the canary pods
|
||||
* run load tests and metric checks for the canary pods every minute
|
||||
* abort the canary release if the failure threshold is reached
|
||||
* route traffic to canary
|
||||
* route traffic to canary (This doesn't happen when using the kubernetes provider)
|
||||
* promote canary spec over primary (blue)
|
||||
* wait for primary rollout
|
||||
* route traffic to primary
|
||||
|
||||
@@ -115,6 +115,10 @@ but disabling config-tracking using the per Secret/ConfigMap annotation may fit
|
||||
The autoscaler reference is optional, when specified,
|
||||
Flagger will pause the traffic increase while the target and primary deployments are scaled up or down.
|
||||
HPA can help reduce the resource usage during the canary analysis.
|
||||
When the autoscaler reference is specified, any changes made to the autoscaler are only made active
|
||||
in the primary autoscaler when a rollout for the deployment starts and completes successfully.
|
||||
Optionally, you can create two HPAs, one for canary and one for the primary to update the HPA without
|
||||
doing a new rollout. As the canary deployment will be scaled to 0, the HPA on the canary will be inactive.
|
||||
|
||||
The progress deadline represents the maximum time in seconds for the canary deployment to
|
||||
make progress before it is rolled back, defaults to ten minutes.
|
||||
@@ -184,6 +188,10 @@ spec:
|
||||
test: "test"
|
||||
```
|
||||
|
||||
Note that the `apex` annotations are added to both the generated Kubernetes Service and the
|
||||
generated service mesh/ingress object. This allows using external-dns with Istio `VirtualServices`
|
||||
and `TraefikServices`. Beware of configuration conflicts [here](../faq.md#ExternalDNS).
|
||||
|
||||
Besides port mapping and metadata, the service specification can
|
||||
contain URI match and rewrite rules, timeout and retry polices:
|
||||
|
||||
@@ -244,7 +252,7 @@ status:
|
||||
```
|
||||
|
||||
The `Promoted` status condition can have one of the following reasons:
|
||||
Initialized, Waiting, Progressing, Promoting, Finalising, Succeeded or Failed.
|
||||
Initialized, Waiting, Progressing, WaitingPromotion, Promoting, Finalising, Succeeded or Failed.
|
||||
A failed canary will have the promoted status set to `false`,
|
||||
the reason to `failed` and the last applied spec will be different to the last promoted one.
|
||||
|
||||
@@ -331,6 +339,10 @@ Spec:
|
||||
# total number of iterations
|
||||
# used for A/B Testing and Blue/Green
|
||||
iterations:
|
||||
# threshold of primary pods that need to be available to consider it ready
|
||||
# before starting rollout. this is optional and the default is 100
|
||||
# percentage (0-100)
|
||||
primaryReadyThreshold: 100
|
||||
# canary match conditions
|
||||
# used for A/B Testing
|
||||
match:
|
||||
|
||||
@@ -46,8 +46,9 @@ metadata:
|
||||
name: my-metric
|
||||
spec:
|
||||
provider:
|
||||
type: # can be prometheus or datadog
|
||||
type: # can be prometheus, datadog, etc
|
||||
address: # API URL
|
||||
insecureSkipVerify: # if set to true, disables the TLS cert validation
|
||||
secretRef:
|
||||
name: # name of the secret containing the API credentials
|
||||
query: # metric query
|
||||
@@ -401,3 +402,210 @@ Reference the template in the canary analysis:
|
||||
max: 5
|
||||
interval: 1m
|
||||
```
|
||||
|
||||
## Graphite
|
||||
|
||||
You can create custom metric checks using the Graphite provider.
|
||||
|
||||
Graphite template example:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: MetricTemplate
|
||||
metadata:
|
||||
name: graphite-request-success-rate
|
||||
spec:
|
||||
provider:
|
||||
type: graphite
|
||||
address: http://graphite.monitoring
|
||||
query: |
|
||||
target=summarize(
|
||||
asPercent(
|
||||
sumSeries(
|
||||
stats.timers.httpServerRequests.app.{{target}}.exception.*.method.*.outcome.{CLIENT_ERROR,INFORMATIONAL,REDIRECTION,SUCCESS}.status.*.uri.*.count
|
||||
),
|
||||
sumSeries(
|
||||
stats.timers.httpServerRequests.app.{{target}}.exception.*.method.*.outcome.*.status.*.uri.*.count
|
||||
)
|
||||
),
|
||||
{{interval}},
|
||||
'avg'
|
||||
)
|
||||
```
|
||||
|
||||
Reference the template in the canary analysis:
|
||||
|
||||
```yaml
|
||||
analysis:
|
||||
metrics:
|
||||
- name: "success rate"
|
||||
templateRef:
|
||||
name: graphite-request-success-rate
|
||||
thresholdRange:
|
||||
min: 90
|
||||
interval: 1min
|
||||
```
|
||||
|
||||
## Graphite authentication
|
||||
|
||||
If your Graphite API requires basic authentication, you can create a secret in the same namespace
|
||||
as the `MetricTemplate` with the basic-auth credentials:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: graphite-basic-auth
|
||||
namespace: flagger
|
||||
data:
|
||||
username: your-user
|
||||
password: your-password
|
||||
```
|
||||
|
||||
Then, reference the secret in the `MetricTemplate`:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: MetricTemplate
|
||||
metadata:
|
||||
name: my-metric
|
||||
namespace: flagger
|
||||
spec:
|
||||
provider:
|
||||
type: graphite
|
||||
address: http://graphite.monitoring
|
||||
secretRef:
|
||||
name: graphite-basic-auth
|
||||
```
|
||||
|
||||
## Google CLoud Monitoring (Stackdriver)
|
||||
|
||||
Enable Workload Identity on your cluster, create a service account key that has read access to the
|
||||
Cloud Monitoring API and then create an IAM policy binding between the GCP service account and the Flagger
|
||||
service account on Kubernetes. You can take a look at this [guide](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
|
||||
|
||||
Annotate the flagger service account
|
||||
```shell script
|
||||
kubectl annotate serviceaccount flagger \
|
||||
--namespace <namespace> \
|
||||
iam.gke.io/gcp-service-account=<gcp-serviceaccount-name>@<project-id>.iam.gserviceaccount.com
|
||||
```
|
||||
|
||||
Alternatively, you can download the json keys and add it to your secret with the key `serviceAccountKey` (This method is not recommended).
|
||||
|
||||
Create a secret that contains your project-id (and, if workload identity is not enabled on your cluster,
|
||||
your [service account json](https://cloud.google.com/docs/authentication/production#create_service_account)).
|
||||
|
||||
```
|
||||
kubectl create secret generic gcloud-sa --from-literal=project=<project-id>
|
||||
```
|
||||
|
||||
Then reference the secret in the metric template.
|
||||
Note: The particular MQL query used here works if [Istio is installed on GKE](https://cloud.google.com/istio/docs/istio-on-gke/installing).
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: MetricTemplate
|
||||
metadata:
|
||||
name: bytes-sent
|
||||
namespace: test
|
||||
spec:
|
||||
provider:
|
||||
type: stackdriver
|
||||
secretRef:
|
||||
name: gcloud-sa
|
||||
query: |
|
||||
fetch k8s_container
|
||||
| metric 'istio.io/service/server/response_latencies'
|
||||
| filter
|
||||
(metric.destination_service_name == '{{ service }}-canary'
|
||||
&& metric.destination_service_namespace == '{{ namespace }}')
|
||||
| align delta(1m)
|
||||
| every 1m
|
||||
| group_by [],
|
||||
[value_response_latencies_percentile:
|
||||
percentile(value.response_latencies, 99)]
|
||||
```
|
||||
|
||||
The reference for the query language can be found [here](https://cloud.google.com/monitoring/mql/reference)
|
||||
|
||||
## Influxdb
|
||||
|
||||
The influxdb provider uses the [flux](https://docs.influxdata.com/influxdb/v2.0/query-data/get-started/) scripting language.
|
||||
|
||||
Create a secret that contains your authentication token that can be gotthen from the InfluxDB UI.
|
||||
|
||||
```
|
||||
kubectl create secret generic gcloud-sa --from-literal=token=<token>
|
||||
```
|
||||
|
||||
Then reference the secret in the metric template.qq
|
||||
Note: The particular MQL query used here works if [Istio is installed on GKE](https://cloud.google.com/istio/docs/istio-on-gke/installing).
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: MetricTemplate
|
||||
metadata:
|
||||
name: not-found
|
||||
namespace: test
|
||||
spec:
|
||||
provider:
|
||||
type: influxdb
|
||||
secretRef:
|
||||
name: influx-token
|
||||
query: |
|
||||
from(bucket: "default")
|
||||
|> range(start: -2h)
|
||||
|> filter(fn: (r) => r["_measurement"] == "istio_requests_total")
|
||||
|> filter(fn: (r) => r[" destination_workload_namespace"] == "{{ namespace }}")
|
||||
|> filter(fn: (r) => r["destination_workload"] == "{{ target }}")
|
||||
|> filter(fn: (r) => r["response_code"] == "500")
|
||||
|> count()
|
||||
|> yield(name: "count")
|
||||
```
|
||||
|
||||
## Dynatrace
|
||||
|
||||
You can create custom metric checks using the Dynatrace provider.
|
||||
|
||||
Create a secret with your Dynatrace token:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: dynatrace
|
||||
namespace: istio-system
|
||||
data:
|
||||
dynatrace_token: ZHQwYz...
|
||||
```
|
||||
|
||||
Dynatrace metric template example:
|
||||
|
||||
```yaml
|
||||
apiVersion: flagger.app/v1beta1
|
||||
kind: MetricTemplate
|
||||
metadata:
|
||||
name: response-time-95pct
|
||||
namespace: istio-system
|
||||
spec:
|
||||
provider:
|
||||
type: dynatrace
|
||||
address: https://xxxxxxxx.live.dynatrace.com
|
||||
secretRef:
|
||||
name: dynatrace
|
||||
query: |
|
||||
builtin:service.response.time:filter(eq(dt.entity.service,SERVICE-ABCDEFG0123456789)):percentile(95)
|
||||
```
|
||||
|
||||
Reference the template in the canary analysis:
|
||||
|
||||
```yaml
|
||||
analysis:
|
||||
metrics:
|
||||
- name: "response-time-95pct"
|
||||
templateRef:
|
||||
name: response-time-95pct
|
||||
namespace: istio-system
|
||||
thresholdRange:
|
||||
max: 1000
|
||||
interval: 1m
|
||||
```
|
||||
|
||||
@@ -16,6 +16,9 @@ There are several types of hooks:
|
||||
* **rollout** hooks are executed during the analysis on each iteration before the metric checks.
|
||||
If a rollout hook call fails the canary advancement is paused and eventfully rolled back.
|
||||
|
||||
* **confirm-traffic-increase** hooks are executed right before the weight on the canary is increased. The canary
|
||||
advancement is paused until this hook returns HTTP 200.
|
||||
|
||||
* **confirm-promotion** hooks are executed before the promotion step.
|
||||
The canary promotion is paused until the hooks return HTTP 200.
|
||||
While the promotion is paused, Flagger will continue to run the metrics checks and rollout hooks.
|
||||
@@ -51,6 +54,9 @@ Spec:
|
||||
timeout: 15s
|
||||
metadata:
|
||||
cmd: "hey -z 1m -q 5 -c 2 http://podinfo-canary.test:9898/"
|
||||
- name: "traffic increase gate"
|
||||
type: confirm-traffic-increase
|
||||
url: http://flagger-loadtester.test/gate/approve
|
||||
- name: "promotion gate"
|
||||
type: confirm-promotion
|
||||
url: http://flagger-loadtester.test/gate/approve
|
||||
@@ -66,6 +72,9 @@ Spec:
|
||||
- name: "send to Slack"
|
||||
type: event
|
||||
url: http://event-recevier.notifications/slack
|
||||
metadata:
|
||||
environment: "test"
|
||||
cluster: "flagger-test"
|
||||
```
|
||||
|
||||
> **Note** that the sum of all rollout webhooks timeouts should be lower than the analysis interval.
|
||||
@@ -244,6 +253,42 @@ to the nGrinder server and start a new performance test. the load tester will pe
|
||||
poll the nGrinder server for the status of the test,
|
||||
and prevent duplicate requests from being sent in subsequent analysis loops.
|
||||
|
||||
### K6 Load Tester
|
||||
|
||||
You can also delegate load testing to a third-party webhook. An example of this is the [`k6 webhook`](https://github.com/grafana/flagger-k6-webhook). This webhook uses [`k6`](https://k6.io/), a very featureful load tester, to run load or smoke tests on canaries. For all features available, see the source repository.
|
||||
|
||||
Here's an example integrating this webhook as a `pre-rollout` step, to load test a service before any traffic is sent to it:
|
||||
|
||||
```yaml
|
||||
webhooks:
|
||||
- name: k6-load-test
|
||||
timeout: 5m
|
||||
type: pre-rollout
|
||||
url: http://k6-loadtester.flagger/launch-test
|
||||
metadata:
|
||||
script: |
|
||||
import http from 'k6/http';
|
||||
import { sleep } from 'k6';
|
||||
export const options = {
|
||||
vus: 2,
|
||||
duration: '30s',
|
||||
thresholds: {
|
||||
http_req_duration: ['p(95)<50']
|
||||
},
|
||||
ext: {
|
||||
loadimpact: {
|
||||
name: '<cluster>/<your_service>',
|
||||
projectID: <project id>,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default function () {
|
||||
http.get('http://<your_service>-canary.<namespace>:80/');
|
||||
sleep(0.10);
|
||||
}
|
||||
```
|
||||
|
||||
## Integration Testing
|
||||
|
||||
Flagger comes with a testing service that can run Helm tests, Bats tests or Concord tests when configured as a webhook.
|
||||
@@ -344,7 +389,8 @@ the web-hook will try to call Concord before timing out (Default is 30s).
|
||||
## Manual Gating
|
||||
|
||||
For manual approval of a canary deployment you can use the `confirm-rollout` and `confirm-promotion` webhooks.
|
||||
The confirmation rollout hooks are executed before the pre-rollout hooks.
|
||||
The confirmation rollout hooks are executed before the pre-rollout hooks. For manually approving traffic weight increase,
|
||||
you can use the `confirm-traffic-increase` webhook.
|
||||
Flagger will halt the canary traffic shifting and analysis until the confirm webhook returns HTTP status 200.
|
||||
|
||||
For manual rollback of a canary deployment you can use the `rollback` webhook.
|
||||
@@ -367,6 +413,17 @@ The `/gate/halt` returns HTTP 403 thus blocking the rollout.
|
||||
If you have notifications enabled, Flagger will post a message to
|
||||
Slack or MS Teams if a canary rollout is waiting for approval.
|
||||
|
||||
The notifications can be disabled with:
|
||||
|
||||
```yaml
|
||||
analysis:
|
||||
webhooks:
|
||||
- name: "gate"
|
||||
type: confirm-rollout
|
||||
url: http://flagger-loadtester.test/gate/halt
|
||||
muteAlert: true
|
||||
```
|
||||
|
||||
Change the URL to `/gate/approve` to start the canary analysis:
|
||||
|
||||
```yaml
|
||||
|
||||
28
docs/logo/flagger-icon-black.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="64px" height="64px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>flagger-icon-black</title>
|
||||
<g id="flagger-icon-black" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M11.7870673,17.7791346 C10.7376442,17.0966346 10.7376442,15.5602885 11.7870673,14.8783654 L31.1659135,2.27951923 C31.4527085,2.09313128 31.7809164,2 32.109115,2 C32.1144833,2 32.1144833,30.6577081 32.1144833,30.6577081 C31.7844966,30.658555 31.4542722,30.565385 31.1659135,30.3779808 L11.7870673,17.7791346 Z" id="Fill-1" fill="#000000"></path>
|
||||
<path d="M1.78706731,24.2791346 C0.737644231,23.5966346 0.737644231,22.0602885 1.78706731,21.3783654 L21.1659135,8.77951923 C21.4527085,8.59313128 21.7809164,8.5 22.109147,8.5 C22.1144833,8.5 16.7504591,14.9302441 16.4621003,14.7428399 L1.78706731,24.2791346 Z" id="Fill-1-Copy" fill="#000000"></path>
|
||||
<path d="M32.1005414,32.7999243 C32.4314477,32.7984255 32.7627112,32.8915919 33.051875,33.0795192 L52.4312981,45.6783654 C53.4807212,46.3602885 53.4807212,47.8966346 52.4312981,48.5791346 L33.051875,61.1779808 C32.7723427,61.3596486 32.4534685,61.452763 32.1336066,61.4575 C32.1336066,61.4575 32.1005414,32.7999243 32.1005414,32.7999243 Z" id="Fill-1" fill="#000000"></path>
|
||||
<path d="M42.6594534,51.6821881 L62.4312981,39.1784411 C63.4807212,39.8603641 63.4807212,41.3967103 62.4312981,42.0792103 L43.051875,54.6780564 C42.7723427,54.8597243 42.4534685,54.9528387 42.1336066,54.9573995 C42.1336066,54.9573995 42.3702896,51.4942608 42.6594534,51.6821881 Z" id="Fill-1-Copy-2" fill="#000000"></path>
|
||||
<g id="Group" transform="translate(11.000000, 32.000000)" fill="#000000">
|
||||
<path d="M23.1648462,1.79890385 C22.7177486,1.57560653 21.9079818,0.775616463 21.12525,0.8 C20.4471662,0.8 20.1819808,1.07951923 19.08525,1.79890385 C20.6106346,2.45198077 26.2588846,4.40082692 27.8390769,4.83755769 C25.3252832,3.17403545 23.7672062,2.16115083 23.1648462,1.79890385 Z" id="Fill-5"></path>
|
||||
<path d="M17.1629423,3.04898077 L15.4269808,4.17744231 C16.9371113,5.2881491 18.4473527,6.15609036 19.9577051,6.7812661 C23.0272183,8.05182074 26.9292047,8.86995809 27.8191154,9.08936538 C32.8706538,10.3349423 37.6418077,11.5107115 41.4783462,15.3478269 C41.6733462,15.54225 41.8562308,15.7407115 42.0373846,15.93975 C42.4308462,15.1880192 42.2335385,14.1957115 41.4466154,13.6845577 L33.8560385,8.74898077 C32.0133462,8.14090385 30.1360385,7.67590385 28.2806538,7.21898077 C26.5308462,6.78744231 23.5727919,6.02059898 21.9181765,5.49156052 C20.8150996,5.13886821 19.2300215,4.32467496 17.1629423,3.04898077 Z" id="Fill-7"></path>
|
||||
<path d="M16.8750849,8.20483098 C15.6193488,7.62821266 14.2831279,6.83594208 12.8664221,5.82801923 L11.2119808,6.91782692 C12.8335577,8.16072333 14.2385577,9.07106402 15.4269808,9.648849 C17.2096154,10.5155265 24.0114808,12.3722308 24.4326346,12.4760769 C29.4841731,13.7210769 34.2553269,14.8968462 38.0924423,18.7339615 C38.0987885,18.7408846 38.1045577,18.7472308 38.1114808,18.7541538 L39.75225,17.6868462 C39.6524423,17.5824231 39.5584038,17.4751154 39.4545577,17.3718462 C35.2384038,13.1551154 29.9791731,11.8587692 24.8941731,10.6051154 C24.3137885,10.4620385 18.7586891,9.06975845 16.8750849,8.20483098 Z" id="Fill-11"></path>
|
||||
<path d="M23.1650769,16.3935 C27.1175769,17.4140769 30.8341154,18.6342692 33.9823846,21.4381154 L35.6439231,20.3581154 C32.0465509,16.9762696 28.005918,15.3433009 23.4551919,14.4789663 C19.3757148,13.7041376 16.6984434,12.7436057 13.6520967,11.5324737 C11.621199,10.7250524 9.97648083,9.72718297 8.71794231,8.53886538 L7.04717308,9.62521154 C9.06194661,11.3700006 10.8411363,12.5664934 12.3847422,13.2146899 C14.4228927,14.0705575 18.0163376,15.1301608 23.1650769,16.3935 Z" id="Fill-17"></path>
|
||||
<path d="M4.57875,11.2299231 L2.92990385,12.3018462 C2.98759615,12.3612692 3.04009615,12.423 3.09951923,12.4818462 C7.31625,16.6985769 12.5743269,17.9949231 17.6599038,19.2485769 C22.0641346,20.3337692 26.2543269,21.3687692 29.7989423,24.1581923 L31.4893269,23.0591538 C27.4958654,19.6968462 22.7385577,18.5158846 18.1214423,17.3781923 C13.1206731,16.1453077 8.39567308,14.9758846 4.57875,11.2299231" id="Fill-19"></path>
|
||||
<path d="M1.07555769,14.5060962 C0.883442308,14.3139808 0.702865385,14.1184038 0.524019231,13.9216731 C-0.227711538,14.6745577 -0.139442308,15.9726346 0.80325,16.5853269 L6.50959615,20.2955192 C9.03536538,21.3409038 11.6765192,21.9945577 14.2738269,22.6349423 C18.3284423,23.6341731 22.2019038,24.5924423 25.5578654,26.9157115 L27.2834423,25.7930192 C23.4676731,22.9245577 19.0403654,21.8255192 14.7347885,20.7639808 C9.68382692,19.5189808 4.91267308,18.3432115 1.07555769,14.5060962" id="Fill-21"></path>
|
||||
<path d="M19.6441154,28.8342692 C20.0243077,29.0188846 20.3998846,29.2133077 20.7691154,29.4221538 C21.2093077,29.5150385 21.6771923,29.4383077 22.0683462,29.1838846 L23.0260385,28.5613846 C19.9493077,26.5035 16.5287308,25.461 13.1196923,24.5927308 L19.6441154,28.8342692 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
<g id="Group-Copy" transform="translate(11.000000, 1.200000)" fill="#000000">
|
||||
<path d="M23.1648462,1.79890385 C22.7177486,1.57560653 21.9079818,0.775616463 21.12525,0.8 C20.4471662,0.8 20.1819808,1.07951923 19.08525,1.79890385 C20.6106346,2.45198077 26.2588846,4.40082692 27.8390769,4.83755769 C25.3252832,3.17403545 23.7672062,2.16115083 23.1648462,1.79890385 Z" id="Fill-5"></path>
|
||||
<path d="M17.1629423,3.04898077 L15.4269808,4.17744231 C16.9371113,5.2881491 18.4473527,6.15609036 19.9577051,6.7812661 C23.0272183,8.05182074 26.9292047,8.86995809 27.8191154,9.08936538 C32.8706538,10.3349423 37.6418077,11.5107115 41.4783462,15.3478269 C41.6733462,15.54225 41.8562308,15.7407115 42.0373846,15.93975 C42.4308462,15.1880192 42.2335385,14.1957115 41.4466154,13.6845577 L33.8560385,8.74898077 C32.0133462,8.14090385 30.1360385,7.67590385 28.2806538,7.21898077 C26.5308462,6.78744231 23.5727919,6.02059898 21.9181765,5.49156052 C20.8150996,5.13886821 19.2300215,4.32467496 17.1629423,3.04898077 Z" id="Fill-7"></path>
|
||||
<path d="M16.8750849,8.20483098 C15.6193488,7.62821266 14.2831279,6.83594208 12.8664221,5.82801923 L11.2119808,6.91782692 C12.8335577,8.16072333 14.2385577,9.07106402 15.4269808,9.648849 C17.2096154,10.5155265 24.0114808,12.3722308 24.4326346,12.4760769 C29.4841731,13.7210769 34.2553269,14.8968462 38.0924423,18.7339615 C38.0987885,18.7408846 38.1045577,18.7472308 38.1114808,18.7541538 L39.75225,17.6868462 C39.6524423,17.5824231 39.5584038,17.4751154 39.4545577,17.3718462 C35.2384038,13.1551154 29.9791731,11.8587692 24.8941731,10.6051154 C24.3137885,10.4620385 18.7586891,9.06975845 16.8750849,8.20483098 Z" id="Fill-11"></path>
|
||||
<path d="M23.1650769,16.3935 C27.1175769,17.4140769 30.8341154,18.6342692 33.9823846,21.4381154 L35.6439231,20.3581154 C32.0465509,16.9762696 28.005918,15.3433009 23.4551919,14.4789663 C19.3757148,13.7041376 16.6984434,12.7436057 13.6520967,11.5324737 C11.621199,10.7250524 9.97648083,9.72718297 8.71794231,8.53886538 L7.04717308,9.62521154 C9.06194661,11.3700006 10.8411363,12.5664934 12.3847422,13.2146899 C14.4228927,14.0705575 18.0163376,15.1301608 23.1650769,16.3935 Z" id="Fill-17"></path>
|
||||
<path d="M4.57875,11.2299231 L2.92990385,12.3018462 C2.98759615,12.3612692 3.04009615,12.423 3.09951923,12.4818462 C7.31625,16.6985769 12.5743269,17.9949231 17.6599038,19.2485769 C22.0641346,20.3337692 26.2543269,21.3687692 29.7989423,24.1581923 L31.4893269,23.0591538 C27.4958654,19.6968462 22.7385577,18.5158846 18.1214423,17.3781923 C13.1206731,16.1453077 8.39567308,14.9758846 4.57875,11.2299231" id="Fill-19"></path>
|
||||
<path d="M1.07555769,14.5060962 C0.883442308,14.3139808 0.702865385,14.1184038 0.524019231,13.9216731 C-0.227711538,14.6745577 -0.139442308,15.9726346 0.80325,16.5853269 L6.50959615,20.2955192 C9.03536538,21.3409038 11.6765192,21.9945577 14.2738269,22.6349423 C18.3284423,23.6341731 22.2019038,24.5924423 25.5578654,26.9157115 L27.2834423,25.7930192 C23.4676731,22.9245577 19.0403654,21.8255192 14.7347885,20.7639808 C9.68382692,19.5189808 4.91267308,18.3432115 1.07555769,14.5060962" id="Fill-21"></path>
|
||||
<path d="M19.6441154,28.8342692 C20.0243077,29.0188846 20.3998846,29.2133077 20.7691154,29.4221538 C21.2093077,29.5150385 21.6771923,29.4383077 22.0683462,29.1838846 L23.0260385,28.5613846 C19.9493077,26.5035 16.5287308,25.461 13.1196923,24.5927308 L19.6441154,28.8342692 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.5 KiB |
BIN
docs/logo/flagger-icon-black@2x.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
28
docs/logo/flagger-icon-color.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="64px" height="64px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>flagger-icon</title>
|
||||
<g id="flagger-icon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M11.7870673,17.7791346 C10.7376442,17.0966346 10.7376442,15.5602885 11.7870673,14.8783654 L31.1659135,2.27951923 C31.4527085,2.09313128 31.7809164,2 32.109115,2 C32.1144833,2 32.1144833,30.6577081 32.1144833,30.6577081 C31.7844966,30.658555 31.4542722,30.565385 31.1659135,30.3779808 L11.7870673,17.7791346 Z" id="Fill-1" fill="#7BB09F"></path>
|
||||
<path d="M1.78706731,24.2791346 C0.737644231,23.5966346 0.737644231,22.0602885 1.78706731,21.3783654 L21.1659135,8.77951923 C21.4527085,8.59313128 21.7809164,8.5 22.109147,8.5 C22.1144833,8.5 16.7504591,14.9302441 16.4621003,14.7428399 L1.78706731,24.2791346 Z" id="Fill-1-Copy" fill="#7BB09F"></path>
|
||||
<path d="M32.1005414,32.7999243 C32.4314477,32.7984255 32.7627112,32.8915919 33.051875,33.0795192 L52.4312981,45.6783654 C53.4807212,46.3602885 53.4807212,47.8966346 52.4312981,48.5791346 L33.051875,61.1779808 C32.7723427,61.3596486 32.4534685,61.452763 32.1336066,61.4575 C32.1336066,61.4575 32.1005414,32.7999243 32.1005414,32.7999243 Z" id="Fill-1" fill="#7BB09F"></path>
|
||||
<path d="M42.6594534,51.6821881 L62.4312981,39.1784411 C63.4807212,39.8603641 63.4807212,41.3967103 62.4312981,42.0792103 L43.051875,54.6780564 C42.7723427,54.8597243 42.4534685,54.9528387 42.1336066,54.9573995 C42.1336066,54.9573995 42.3702896,51.4942608 42.6594534,51.6821881 Z" id="Fill-1-Copy-2" fill="#7BB09F"></path>
|
||||
<g id="Group" transform="translate(11.000000, 32.000000)" fill="#7BB09F">
|
||||
<path d="M23.1648462,1.79890385 C22.7177486,1.57560653 21.9079818,0.775616463 21.12525,0.8 C20.4471662,0.8 20.1819808,1.07951923 19.08525,1.79890385 C20.6106346,2.45198077 26.2588846,4.40082692 27.8390769,4.83755769 C25.3252832,3.17403545 23.7672062,2.16115083 23.1648462,1.79890385 Z" id="Fill-5"></path>
|
||||
<path d="M17.1629423,3.04898077 L15.4269808,4.17744231 C16.9371113,5.2881491 18.4473527,6.15609036 19.9577051,6.7812661 C23.0272183,8.05182074 26.9292047,8.86995809 27.8191154,9.08936538 C32.8706538,10.3349423 37.6418077,11.5107115 41.4783462,15.3478269 C41.6733462,15.54225 41.8562308,15.7407115 42.0373846,15.93975 C42.4308462,15.1880192 42.2335385,14.1957115 41.4466154,13.6845577 L33.8560385,8.74898077 C32.0133462,8.14090385 30.1360385,7.67590385 28.2806538,7.21898077 C26.5308462,6.78744231 23.5727919,6.02059898 21.9181765,5.49156052 C20.8150996,5.13886821 19.2300215,4.32467496 17.1629423,3.04898077 Z" id="Fill-7"></path>
|
||||
<path d="M16.8750849,8.20483098 C15.6193488,7.62821266 14.2831279,6.83594208 12.8664221,5.82801923 L11.2119808,6.91782692 C12.8335577,8.16072333 14.2385577,9.07106402 15.4269808,9.648849 C17.2096154,10.5155265 24.0114808,12.3722308 24.4326346,12.4760769 C29.4841731,13.7210769 34.2553269,14.8968462 38.0924423,18.7339615 C38.0987885,18.7408846 38.1045577,18.7472308 38.1114808,18.7541538 L39.75225,17.6868462 C39.6524423,17.5824231 39.5584038,17.4751154 39.4545577,17.3718462 C35.2384038,13.1551154 29.9791731,11.8587692 24.8941731,10.6051154 C24.3137885,10.4620385 18.7586891,9.06975845 16.8750849,8.20483098 Z" id="Fill-11"></path>
|
||||
<path d="M23.1650769,16.3935 C27.1175769,17.4140769 30.8341154,18.6342692 33.9823846,21.4381154 L35.6439231,20.3581154 C32.0465509,16.9762696 28.005918,15.3433009 23.4551919,14.4789663 C19.3757148,13.7041376 16.6984434,12.7436057 13.6520967,11.5324737 C11.621199,10.7250524 9.97648083,9.72718297 8.71794231,8.53886538 L7.04717308,9.62521154 C9.06194661,11.3700006 10.8411363,12.5664934 12.3847422,13.2146899 C14.4228927,14.0705575 18.0163376,15.1301608 23.1650769,16.3935 Z" id="Fill-17"></path>
|
||||
<path d="M4.57875,11.2299231 L2.92990385,12.3018462 C2.98759615,12.3612692 3.04009615,12.423 3.09951923,12.4818462 C7.31625,16.6985769 12.5743269,17.9949231 17.6599038,19.2485769 C22.0641346,20.3337692 26.2543269,21.3687692 29.7989423,24.1581923 L31.4893269,23.0591538 C27.4958654,19.6968462 22.7385577,18.5158846 18.1214423,17.3781923 C13.1206731,16.1453077 8.39567308,14.9758846 4.57875,11.2299231" id="Fill-19"></path>
|
||||
<path d="M1.07555769,14.5060962 C0.883442308,14.3139808 0.702865385,14.1184038 0.524019231,13.9216731 C-0.227711538,14.6745577 -0.139442308,15.9726346 0.80325,16.5853269 L6.50959615,20.2955192 C9.03536538,21.3409038 11.6765192,21.9945577 14.2738269,22.6349423 C18.3284423,23.6341731 22.2019038,24.5924423 25.5578654,26.9157115 L27.2834423,25.7930192 C23.4676731,22.9245577 19.0403654,21.8255192 14.7347885,20.7639808 C9.68382692,19.5189808 4.91267308,18.3432115 1.07555769,14.5060962" id="Fill-21"></path>
|
||||
<path d="M19.6441154,28.8342692 C20.0243077,29.0188846 20.3998846,29.2133077 20.7691154,29.4221538 C21.2093077,29.5150385 21.6771923,29.4383077 22.0683462,29.1838846 L23.0260385,28.5613846 C19.9493077,26.5035 16.5287308,25.461 13.1196923,24.5927308 L19.6441154,28.8342692 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
<g id="Group-Copy" transform="translate(11.000000, 1.200000)" fill="#7BB09F">
|
||||
<path d="M23.1648462,1.79890385 C22.7177486,1.57560653 21.9079818,0.775616463 21.12525,0.8 C20.4471662,0.8 20.1819808,1.07951923 19.08525,1.79890385 C20.6106346,2.45198077 26.2588846,4.40082692 27.8390769,4.83755769 C25.3252832,3.17403545 23.7672062,2.16115083 23.1648462,1.79890385 Z" id="Fill-5"></path>
|
||||
<path d="M17.1629423,3.04898077 L15.4269808,4.17744231 C16.9371113,5.2881491 18.4473527,6.15609036 19.9577051,6.7812661 C23.0272183,8.05182074 26.9292047,8.86995809 27.8191154,9.08936538 C32.8706538,10.3349423 37.6418077,11.5107115 41.4783462,15.3478269 C41.6733462,15.54225 41.8562308,15.7407115 42.0373846,15.93975 C42.4308462,15.1880192 42.2335385,14.1957115 41.4466154,13.6845577 L33.8560385,8.74898077 C32.0133462,8.14090385 30.1360385,7.67590385 28.2806538,7.21898077 C26.5308462,6.78744231 23.5727919,6.02059898 21.9181765,5.49156052 C20.8150996,5.13886821 19.2300215,4.32467496 17.1629423,3.04898077 Z" id="Fill-7"></path>
|
||||
<path d="M16.8750849,8.20483098 C15.6193488,7.62821266 14.2831279,6.83594208 12.8664221,5.82801923 L11.2119808,6.91782692 C12.8335577,8.16072333 14.2385577,9.07106402 15.4269808,9.648849 C17.2096154,10.5155265 24.0114808,12.3722308 24.4326346,12.4760769 C29.4841731,13.7210769 34.2553269,14.8968462 38.0924423,18.7339615 C38.0987885,18.7408846 38.1045577,18.7472308 38.1114808,18.7541538 L39.75225,17.6868462 C39.6524423,17.5824231 39.5584038,17.4751154 39.4545577,17.3718462 C35.2384038,13.1551154 29.9791731,11.8587692 24.8941731,10.6051154 C24.3137885,10.4620385 18.7586891,9.06975845 16.8750849,8.20483098 Z" id="Fill-11"></path>
|
||||
<path d="M23.1650769,16.3935 C27.1175769,17.4140769 30.8341154,18.6342692 33.9823846,21.4381154 L35.6439231,20.3581154 C32.0465509,16.9762696 28.005918,15.3433009 23.4551919,14.4789663 C19.3757148,13.7041376 16.6984434,12.7436057 13.6520967,11.5324737 C11.621199,10.7250524 9.97648083,9.72718297 8.71794231,8.53886538 L7.04717308,9.62521154 C9.06194661,11.3700006 10.8411363,12.5664934 12.3847422,13.2146899 C14.4228927,14.0705575 18.0163376,15.1301608 23.1650769,16.3935 Z" id="Fill-17"></path>
|
||||
<path d="M4.57875,11.2299231 L2.92990385,12.3018462 C2.98759615,12.3612692 3.04009615,12.423 3.09951923,12.4818462 C7.31625,16.6985769 12.5743269,17.9949231 17.6599038,19.2485769 C22.0641346,20.3337692 26.2543269,21.3687692 29.7989423,24.1581923 L31.4893269,23.0591538 C27.4958654,19.6968462 22.7385577,18.5158846 18.1214423,17.3781923 C13.1206731,16.1453077 8.39567308,14.9758846 4.57875,11.2299231" id="Fill-19"></path>
|
||||
<path d="M1.07555769,14.5060962 C0.883442308,14.3139808 0.702865385,14.1184038 0.524019231,13.9216731 C-0.227711538,14.6745577 -0.139442308,15.9726346 0.80325,16.5853269 L6.50959615,20.2955192 C9.03536538,21.3409038 11.6765192,21.9945577 14.2738269,22.6349423 C18.3284423,23.6341731 22.2019038,24.5924423 25.5578654,26.9157115 L27.2834423,25.7930192 C23.4676731,22.9245577 19.0403654,21.8255192 14.7347885,20.7639808 C9.68382692,19.5189808 4.91267308,18.3432115 1.07555769,14.5060962" id="Fill-21"></path>
|
||||
<path d="M19.6441154,28.8342692 C20.0243077,29.0188846 20.3998846,29.2133077 20.7691154,29.4221538 C21.2093077,29.5150385 21.6771923,29.4383077 22.0683462,29.1838846 L23.0260385,28.5613846 C19.9493077,26.5035 16.5287308,25.461 13.1196923,24.5927308 L19.6441154,28.8342692 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.4 KiB |
BIN
docs/logo/flagger-icon-color@2x.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
28
docs/logo/flagger-icon-white.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="64px" height="64px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>flagger-icon-white</title>
|
||||
<g id="flagger-icon-white" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M11.7870673,17.7791346 C10.7376442,17.0966346 10.7376442,15.5602885 11.7870673,14.8783654 L31.1659135,2.27951923 C31.4527085,2.09313128 31.7809164,2 32.109115,2 C32.1144833,2 32.1144833,30.6577081 32.1144833,30.6577081 C31.7844966,30.658555 31.4542722,30.565385 31.1659135,30.3779808 L11.7870673,17.7791346 Z" id="Fill-1" fill="#FFFFFF"></path>
|
||||
<path d="M1.78706731,24.2791346 C0.737644231,23.5966346 0.737644231,22.0602885 1.78706731,21.3783654 L21.1659135,8.77951923 C21.4527085,8.59313128 21.7809164,8.5 22.109147,8.5 C22.1144833,8.5 16.7504591,14.9302441 16.4621003,14.7428399 L1.78706731,24.2791346 Z" id="Fill-1-Copy" fill="#FFFFFF"></path>
|
||||
<path d="M32.1005414,32.7999243 C32.4314477,32.7984255 32.7627112,32.8915919 33.051875,33.0795192 L52.4312981,45.6783654 C53.4807212,46.3602885 53.4807212,47.8966346 52.4312981,48.5791346 L33.051875,61.1779808 C32.7723427,61.3596486 32.4534685,61.452763 32.1336066,61.4575 C32.1336066,61.4575 32.1005414,32.7999243 32.1005414,32.7999243 Z" id="Fill-1" fill="#FFFFFF"></path>
|
||||
<path d="M42.6594534,51.6821881 L62.4312981,39.1784411 C63.4807212,39.8603641 63.4807212,41.3967103 62.4312981,42.0792103 L43.051875,54.6780564 C42.7723427,54.8597243 42.4534685,54.9528387 42.1336066,54.9573995 C42.1336066,54.9573995 42.3702896,51.4942608 42.6594534,51.6821881 Z" id="Fill-1-Copy-2" fill="#FFFFFF"></path>
|
||||
<g id="Group" transform="translate(11.000000, 32.000000)" fill="#FFFFFF">
|
||||
<path d="M23.1648462,1.79890385 C22.7177486,1.57560653 21.9079818,0.775616463 21.12525,0.8 C20.4471662,0.8 20.1819808,1.07951923 19.08525,1.79890385 C20.6106346,2.45198077 26.2588846,4.40082692 27.8390769,4.83755769 C25.3252832,3.17403545 23.7672062,2.16115083 23.1648462,1.79890385 Z" id="Fill-5"></path>
|
||||
<path d="M17.1629423,3.04898077 L15.4269808,4.17744231 C16.9371113,5.2881491 18.4473527,6.15609036 19.9577051,6.7812661 C23.0272183,8.05182074 26.9292047,8.86995809 27.8191154,9.08936538 C32.8706538,10.3349423 37.6418077,11.5107115 41.4783462,15.3478269 C41.6733462,15.54225 41.8562308,15.7407115 42.0373846,15.93975 C42.4308462,15.1880192 42.2335385,14.1957115 41.4466154,13.6845577 L33.8560385,8.74898077 C32.0133462,8.14090385 30.1360385,7.67590385 28.2806538,7.21898077 C26.5308462,6.78744231 23.5727919,6.02059898 21.9181765,5.49156052 C20.8150996,5.13886821 19.2300215,4.32467496 17.1629423,3.04898077 Z" id="Fill-7"></path>
|
||||
<path d="M16.8750849,8.20483098 C15.6193488,7.62821266 14.2831279,6.83594208 12.8664221,5.82801923 L11.2119808,6.91782692 C12.8335577,8.16072333 14.2385577,9.07106402 15.4269808,9.648849 C17.2096154,10.5155265 24.0114808,12.3722308 24.4326346,12.4760769 C29.4841731,13.7210769 34.2553269,14.8968462 38.0924423,18.7339615 C38.0987885,18.7408846 38.1045577,18.7472308 38.1114808,18.7541538 L39.75225,17.6868462 C39.6524423,17.5824231 39.5584038,17.4751154 39.4545577,17.3718462 C35.2384038,13.1551154 29.9791731,11.8587692 24.8941731,10.6051154 C24.3137885,10.4620385 18.7586891,9.06975845 16.8750849,8.20483098 Z" id="Fill-11"></path>
|
||||
<path d="M23.1650769,16.3935 C27.1175769,17.4140769 30.8341154,18.6342692 33.9823846,21.4381154 L35.6439231,20.3581154 C32.0465509,16.9762696 28.005918,15.3433009 23.4551919,14.4789663 C19.3757148,13.7041376 16.6984434,12.7436057 13.6520967,11.5324737 C11.621199,10.7250524 9.97648083,9.72718297 8.71794231,8.53886538 L7.04717308,9.62521154 C9.06194661,11.3700006 10.8411363,12.5664934 12.3847422,13.2146899 C14.4228927,14.0705575 18.0163376,15.1301608 23.1650769,16.3935 Z" id="Fill-17"></path>
|
||||
<path d="M4.57875,11.2299231 L2.92990385,12.3018462 C2.98759615,12.3612692 3.04009615,12.423 3.09951923,12.4818462 C7.31625,16.6985769 12.5743269,17.9949231 17.6599038,19.2485769 C22.0641346,20.3337692 26.2543269,21.3687692 29.7989423,24.1581923 L31.4893269,23.0591538 C27.4958654,19.6968462 22.7385577,18.5158846 18.1214423,17.3781923 C13.1206731,16.1453077 8.39567308,14.9758846 4.57875,11.2299231" id="Fill-19"></path>
|
||||
<path d="M1.07555769,14.5060962 C0.883442308,14.3139808 0.702865385,14.1184038 0.524019231,13.9216731 C-0.227711538,14.6745577 -0.139442308,15.9726346 0.80325,16.5853269 L6.50959615,20.2955192 C9.03536538,21.3409038 11.6765192,21.9945577 14.2738269,22.6349423 C18.3284423,23.6341731 22.2019038,24.5924423 25.5578654,26.9157115 L27.2834423,25.7930192 C23.4676731,22.9245577 19.0403654,21.8255192 14.7347885,20.7639808 C9.68382692,19.5189808 4.91267308,18.3432115 1.07555769,14.5060962" id="Fill-21"></path>
|
||||
<path d="M19.6441154,28.8342692 C20.0243077,29.0188846 20.3998846,29.2133077 20.7691154,29.4221538 C21.2093077,29.5150385 21.6771923,29.4383077 22.0683462,29.1838846 L23.0260385,28.5613846 C19.9493077,26.5035 16.5287308,25.461 13.1196923,24.5927308 L19.6441154,28.8342692 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
<g id="Group-Copy" transform="translate(11.000000, 1.200000)" fill="#FFFFFF">
|
||||
<path d="M23.1648462,1.79890385 C22.7177486,1.57560653 21.9079818,0.775616463 21.12525,0.8 C20.4471662,0.8 20.1819808,1.07951923 19.08525,1.79890385 C20.6106346,2.45198077 26.2588846,4.40082692 27.8390769,4.83755769 C25.3252832,3.17403545 23.7672062,2.16115083 23.1648462,1.79890385 Z" id="Fill-5"></path>
|
||||
<path d="M17.1629423,3.04898077 L15.4269808,4.17744231 C16.9371113,5.2881491 18.4473527,6.15609036 19.9577051,6.7812661 C23.0272183,8.05182074 26.9292047,8.86995809 27.8191154,9.08936538 C32.8706538,10.3349423 37.6418077,11.5107115 41.4783462,15.3478269 C41.6733462,15.54225 41.8562308,15.7407115 42.0373846,15.93975 C42.4308462,15.1880192 42.2335385,14.1957115 41.4466154,13.6845577 L33.8560385,8.74898077 C32.0133462,8.14090385 30.1360385,7.67590385 28.2806538,7.21898077 C26.5308462,6.78744231 23.5727919,6.02059898 21.9181765,5.49156052 C20.8150996,5.13886821 19.2300215,4.32467496 17.1629423,3.04898077 Z" id="Fill-7"></path>
|
||||
<path d="M16.8750849,8.20483098 C15.6193488,7.62821266 14.2831279,6.83594208 12.8664221,5.82801923 L11.2119808,6.91782692 C12.8335577,8.16072333 14.2385577,9.07106402 15.4269808,9.648849 C17.2096154,10.5155265 24.0114808,12.3722308 24.4326346,12.4760769 C29.4841731,13.7210769 34.2553269,14.8968462 38.0924423,18.7339615 C38.0987885,18.7408846 38.1045577,18.7472308 38.1114808,18.7541538 L39.75225,17.6868462 C39.6524423,17.5824231 39.5584038,17.4751154 39.4545577,17.3718462 C35.2384038,13.1551154 29.9791731,11.8587692 24.8941731,10.6051154 C24.3137885,10.4620385 18.7586891,9.06975845 16.8750849,8.20483098 Z" id="Fill-11"></path>
|
||||
<path d="M23.1650769,16.3935 C27.1175769,17.4140769 30.8341154,18.6342692 33.9823846,21.4381154 L35.6439231,20.3581154 C32.0465509,16.9762696 28.005918,15.3433009 23.4551919,14.4789663 C19.3757148,13.7041376 16.6984434,12.7436057 13.6520967,11.5324737 C11.621199,10.7250524 9.97648083,9.72718297 8.71794231,8.53886538 L7.04717308,9.62521154 C9.06194661,11.3700006 10.8411363,12.5664934 12.3847422,13.2146899 C14.4228927,14.0705575 18.0163376,15.1301608 23.1650769,16.3935 Z" id="Fill-17"></path>
|
||||
<path d="M4.57875,11.2299231 L2.92990385,12.3018462 C2.98759615,12.3612692 3.04009615,12.423 3.09951923,12.4818462 C7.31625,16.6985769 12.5743269,17.9949231 17.6599038,19.2485769 C22.0641346,20.3337692 26.2543269,21.3687692 29.7989423,24.1581923 L31.4893269,23.0591538 C27.4958654,19.6968462 22.7385577,18.5158846 18.1214423,17.3781923 C13.1206731,16.1453077 8.39567308,14.9758846 4.57875,11.2299231" id="Fill-19"></path>
|
||||
<path d="M1.07555769,14.5060962 C0.883442308,14.3139808 0.702865385,14.1184038 0.524019231,13.9216731 C-0.227711538,14.6745577 -0.139442308,15.9726346 0.80325,16.5853269 L6.50959615,20.2955192 C9.03536538,21.3409038 11.6765192,21.9945577 14.2738269,22.6349423 C18.3284423,23.6341731 22.2019038,24.5924423 25.5578654,26.9157115 L27.2834423,25.7930192 C23.4676731,22.9245577 19.0403654,21.8255192 14.7347885,20.7639808 C9.68382692,19.5189808 4.91267308,18.3432115 1.07555769,14.5060962" id="Fill-21"></path>
|
||||
<path d="M19.6441154,28.8342692 C20.0243077,29.0188846 20.3998846,29.2133077 20.7691154,29.4221538 C21.2093077,29.5150385 21.6771923,29.4383077 22.0683462,29.1838846 L23.0260385,28.5613846 C19.9493077,26.5035 16.5287308,25.461 13.1196923,24.5927308 L19.6441154,28.8342692 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.5 KiB |
BIN
docs/logo/flagger-icon-white@2x.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 7.5 KiB |
29
docs/logo/flagger-stacked-black.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="160px" height="160px" viewBox="0 0 160 160" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>flagger-stacked-black</title>
|
||||
<g id="flagger-stacked-black" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M10.1931429,149 L10.1931429,125.648 L15.6811429,125.648 L15.6811429,121.952 L10.1931429,121.952 L10.1931429,119.88 C10.1931429,116.408 11.7051429,114.56 14.5051429,114.56 C15.5131429,114.56 16.2411429,114.784 16.9131429,115.176 L17.9771429,111.984 C16.8571429,111.368 15.4571429,111.088 13.8331429,111.088 C9.18514286,111.088 5.99314286,114.28 5.99314286,119.88 L5.99314286,121.952 L1.51314286,121.952 L1.51314286,125.648 L5.99314286,125.648 L5.99314286,149 L10.1931429,149 Z M24.9211429,149 L24.9211429,111.648 L20.7211429,111.648 L20.7211429,149 L24.9211429,149 Z M10.1931429,149 L10.1931429,125.648 L15.6811429,125.648 L15.6811429,121.952 L10.1931429,121.952 L10.1931429,119.88 C10.1931429,116.408 11.7051429,114.56 14.5051429,114.56 C15.5131429,114.56 16.2411429,114.784 16.9131429,115.176 L17.9771429,111.984 C16.8571429,111.368 15.4571429,111.088 13.8331429,111.088 C9.18514286,111.088 5.99314286,114.28 5.99314286,119.88 L5.99314286,121.952 L1.51314286,121.952 L1.51314286,125.648 L5.99314286,125.648 L5.99314286,149 L10.1931429,149 Z M24.9211429,149 L24.9211429,111.648 L20.7211429,111.648 L20.7211429,149 L24.9211429,149 Z M38.9874286,149.672 C42.6274286,149.672 45.7634286,148.384 47.9474286,145.92 L47.9474286,149 L52.1474286,149 L52.1474286,130.408 C52.1474286,123.856 47.4434286,121.28 41.6754286,121.28 C37.2514286,121.28 33.7794286,122.736 30.8674286,125.76 L32.8274286,128.672 C35.2354286,126.04 37.8674286,124.92 41.1154286,124.92 C45.0354286,124.92 47.9474286,126.992 47.9474286,130.576 L47.9474286,135.448 C45.7634286,132.984 42.6834286,131.808 38.9874286,131.808 C34.3954286,131.808 29.5794286,134.608 29.5794286,140.712 C29.5794286,146.592 34.4514286,149.672 38.9874286,149.672 Z M40.5554286,146.648 C36.5794286,146.648 33.8354286,144.184 33.8354286,140.712 C33.8354286,137.296 36.5794286,134.832 40.5554286,134.832 C43.4674286,134.832 46.3234286,135.952 47.9474286,138.136 L47.9474286,143.288 C46.3234286,145.528 43.4674286,146.648 40.5554286,146.648 Z M69.1817143,159.976 C75.7897143,159.976 82.1177143,157.176 82.1177143,148.608 L82.1177143,121.952 L77.9177143,121.952 L77.9177143,126.04 C75.7337143,123.072 72.4297143,121.28 68.7897143,121.28 C61.6777143,121.28 56.7497143,126.656 56.7497143,135.336 C56.7497143,144.072 61.7337143,149.336 68.7897143,149.336 C72.5977143,149.336 75.9017143,147.264 77.9177143,144.52 L77.9177143,148.608 C77.9177143,154.32 73.6617143,156.504 69.1817143,156.504 C65.3177143,156.504 62.6297143,155.496 60.3897143,152.864 L58.2617143,155.888 C61.5097143,159.08 64.6457143,159.976 69.1817143,159.976 Z M69.8537143,145.584 C64.3657143,145.584 61.1177143,141.272 61.1177143,135.336 C61.1177143,129.344 64.3657143,125.032 69.8537143,125.032 C73.1577143,125.032 76.4057143,127.048 77.9177143,129.344 L77.9177143,141.216 C76.4057143,143.568 73.1577143,145.584 69.8537143,145.584 Z M99.096,159.976 C105.704,159.976 112.032,157.176 112.032,148.608 L112.032,121.952 L107.832,121.952 L107.832,126.04 C105.648,123.072 102.344,121.28 98.704,121.28 C91.592,121.28 86.664,126.656 86.664,135.336 C86.664,144.072 91.648,149.336 98.704,149.336 C102.512,149.336 105.816,147.264 107.832,144.52 L107.832,148.608 C107.832,154.32 103.576,156.504 99.096,156.504 C95.232,156.504 92.544,155.496 90.304,152.864 L88.176,155.888 C91.424,159.08 94.56,159.976 99.096,159.976 Z M99.768,145.584 C94.28,145.584 91.032,141.272 91.032,135.336 C91.032,129.344 94.28,125.032 99.768,125.032 C103.072,125.032 106.32,127.048 107.832,129.344 L107.832,141.216 C106.32,143.568 103.072,145.584 99.768,145.584 Z M130.410286,149.672 C134.778286,149.672 138.418286,148.16 141.162286,145.472 L139.146286,142.728 C136.962286,144.968 133.882286,146.2 130.746286,146.2 C124.922286,146.2 121.394286,141.944 121.058286,136.848 L142.898286,136.848 L142.898286,135.784 C142.898286,127.664 138.082286,121.28 129.906286,121.28 C122.178286,121.28 116.578286,127.608 116.578286,135.448 C116.578286,143.904 122.346286,149.672 130.410286,149.672 Z M138.754286,133.712 L121.002286,133.712 C121.226286,129.624 124.082286,124.752 129.850286,124.752 C136.010286,124.752 138.698286,129.736 138.754286,133.712 Z M151.588571,149 L151.588571,129.848 C152.820571,127.664 156.348571,125.536 158.980571,125.536 C159.596571,125.536 160.100571,125.592 160.604571,125.648 L160.604571,121.336 C156.908571,121.336 153.772571,123.464 151.588571,126.264 L151.588571,121.952 L147.388571,121.952 L147.388571,149 L151.588571,149 Z" id="fflagger" fill="#1A1A1A" fill-rule="nonzero"></path>
|
||||
<g id="flags" transform="translate(26.036697, 0.500000)">
|
||||
<path d="M53.9358922,0.7 L53.9361614,0.7149 L53.9361614,0.7149 L53.9369368,0.9336 C53.9370203,0.972 53.9371029,1.015 53.9371847,1.0625 L53.9378977,1.6088 C53.9379744,1.6824 53.9380503,1.7602 53.9381254,1.8421 L53.9389868,3.0153 C53.9390554,3.1284 53.9391232,3.2452 53.9391903,3.3656 L53.9399577,4.9768 C53.9400186,5.1244 53.9400788,5.2752 53.9401383,5.4291 L53.9409762,7.9576 C53.9410285,8.14 53.9410802,8.325 53.9411311,8.5125 L53.9419772,12.1359 C53.9420204,12.3498 53.9420629,12.5656 53.9421048,12.7832 L53.9429968,18.3 C53.9430294,18.54 53.9430615,18.781 53.943093,19.0229 L53.943952,27.1992 C53.9439728,27.4488 53.9439933,27.6982 53.9440133,27.9473 L53.9449541,50.7 L53.9449541,50.7 C53.3879217,50.7014777 52.830488,50.538921 52.3437254,50.211951 L19.6313575,28.2303499 C19.498497,28.1410415 19.375601,28.0433533 19.2626695,27.9385428 L1.40077569,39.7 C-0.466925231,38.5321603 -0.466925231,35.903287 1.40077569,34.7364344 L33.206,14.047 L52.3437254,1.18768595 C52.8278484,0.862489056 53.3818782,0.7 53.9358922,0.7 Z" id="Combined-Shape" fill="#1A1A1A"></path>
|
||||
<path d="M53.9449541,53.7 C54.518545,53.6973849 55.0927551,53.8599359 55.5939898,54.1878202 L89.1239541,76.1279689 L105.632086,65.7 C107.358112,66.8668656 107.358112,69.4957682 105.632086,70.663621 L73.3882295,91.6036587 C73.3686858,91.6168729 73.348778,91.6191194 73.3286088,91.6113313 L55.5939898,103.212312 C55.1094503,103.529275 54.5567157,103.691735 54.0022691,103.7 L54.0020013,103.4664 C54.0019573,103.428 54.001908,103.385 54.0018535,103.3375 L54.0009599,102.5579 C54.000866,102.476 54.0007674,102.39 54.0006643,102.3 L53.9999912,101.7128 C53.9953913,97.7 53.9845014,88.2 53.9736116,78.7 L53.9718931,77.2008 C53.9627374,69.2136 53.9538164,61.4312 53.9488864,57.1304 L53.9480097,56.3656 C53.9475957,56.0044 53.9472188,55.6756 53.9468821,55.3819 L53.9459959,54.6088 C53.9459115,54.5352 53.945832,54.4658 53.9457573,54.4007 L53.9449541,53.7 L53.9449541,53.7 Z" id="Combined-Shape" fill="#1A1A1A"></path>
|
||||
<g id="Group-Copy" transform="translate(17.363303, 0.000000)" fill="#171818">
|
||||
<path d="M40.0825271,2.57811824 C39.3101975,2.18406772 37.9113821,0.772333321 36.5592679,0.815362703 C35.3879258,0.815362703 34.9298365,1.30862747 33.0353111,2.57811824 C35.6703059,3.73059649 45.4272614,7.16970562 48.1569327,7.9404 C43.8145304,5.00479909 41.1230619,3.21737183 40.0825271,2.57811824 Z" id="Fill-5"></path>
|
||||
<path d="M29.6177773,4.85830684 L26.6147653,6.81885893 C29.4750473,8.76729329 32.2115554,10.2845904 34.8242897,11.3707502 C40.1341913,13.5781702 46.8841749,14.9995752 48.423617,15.3807663 C57.1621923,17.5447908 65.4157347,19.5875337 72.0525009,26.2540122 C72.3898283,26.5917965 72.7061975,26.9365971 73.0195726,27.2824 C73.7002154,25.9763676 73.358896,24.2523647 71.9976104,23.3643028 L58.8667933,14.7893932 C55.6791495,13.7329403 52.4316251,12.9250645 49.222025,12.1312213 C46.1950608,11.3814806 41.0779702,10.0491921 38.2156776,9.13005801 C36.3074826,8.51730196 33.4415158,7.0933849 29.6177773,4.85830684 Z" id="Fill-7"></path>
|
||||
<path d="M29.7315665,14.094497 C27.5581473,13.0954401 25.1789914,11.566935 22.5940987,9.50898164 L19.7614089,11.4291886 C22.680354,13.872933 25.1682837,15.5953444 27.225198,16.5964226 C30.3105695,18.09804 42.0831903,21.3149916 42.8121204,21.4949169 C51.5552876,23.6520212 59.5365954,25.256157 66.1778478,31.9045231 C66.1888316,31.9163913 68.9772132,30.2313417 68.797477,30.052416 C61.5001876,22.7464498 52.4120302,20.425361 43.6109479,18.253263 C42.6064223,18.005366 32.9916953,15.5930823 29.7315665,14.094497 Z" id="Fill-11"></path>
|
||||
<path d="M40.2748943,27.6858128 C47.2416777,29.4577639 53.792549,31.5762923 59.3417736,36.4444 L62.2704462,34.569277 C55.9296207,28.6976319 48.8074918,25.8624309 40.7862587,24.3617515 C33.595662,23.0164746 28.8766311,21.3487752 23.507058,19.2459776 C19.9273426,17.8441125 17.1081118,16.3021039 15.0493654,14.6199518 L12.1044223,16.5060931 C15.496129,19.1544049 18.552383,21.0412683 21.2731845,22.1666833 C24.8656838,23.6526619 31.1995871,25.4923718 40.2748943,27.6858128 Z" id="Fill-17"></path>
|
||||
<path d="M5.18885131,21.1343855 C5.29067424,21.2373258 5.38333311,21.3442637 5.48821073,21.4462046 C12.9304487,28.7509644 21.8300234,30.8575975 30.8057147,33.0293369 C38.5788773,34.9092456 45.6427477,36.4683588 51.8987485,41.3005539 L54.8844037,39.3547126 C47.8362204,33.5300936 39.7691873,31.7600736 31.6202982,29.7892176 C22.7942865,27.6534573 14.8355558,25.7666967 8.09895067,19.2774634 L5.18885131,21.1343855 Z" id="Fill-19"></path>
|
||||
<path d="M1.86538962,23.4720365 C0.558922248,24.8286618 0.712329392,27.1676708 2.35067758,28.271683 L12.2679982,34.9570906 C16.6576484,36.8407725 20.0248373,37.7569569 24.5388174,38.9108681 C31.5855194,40.7113852 38.2525371,42.1959537 44.0850166,46.38226 L46.9264812,44.4396723 C40.2948809,39.2709822 32.8228032,37.452366 25.3399436,35.5395764 C16.5616459,33.2962069 9.49263239,31.439221 2.82393361,24.5251104 C2.49004747,24.178937 2.17621456,23.8265263 1.86538962,23.4720365 Z" id="Fill-21"></path>
|
||||
<path d="M34.1645854,49.6645268 C34.893506,50.0634031 35.1425612,50.5086988 36.1796702,50.7 C36.9305233,50.7 37.7585832,50.659873 38.4352738,50.23418 L40.0920678,49.1926318 C34.7693674,45.7494414 29.2447004,43.7586502 23.3471124,42.3058883 L34.1645854,49.6645268 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
<g id="Group-Copy-2" transform="translate(17.363303, 53.000000)" fill="#131415">
|
||||
<path d="M40.0825271,2.57811824 C39.3101975,2.18406772 37.9113821,0.772333321 36.5592679,0.815362703 C35.3879258,0.815362703 34.9298365,1.30862747 33.0353111,2.57811824 C35.6703059,3.73059649 45.4272614,7.16970562 48.1569327,7.9404 C43.8145304,5.00479909 41.1230619,3.21737183 40.0825271,2.57811824 Z" id="Fill-5"></path>
|
||||
<path d="M29.6177773,4.85830684 L26.6147653,6.81885893 C29.4750473,8.76729329 32.2115554,10.2845904 34.8242897,11.3707502 C40.1341913,13.5781702 46.8841749,14.9995752 48.423617,15.3807663 C57.1621923,17.5447908 65.4157347,19.5875337 72.0525009,26.2540122 C72.3898283,26.5917965 72.7061975,26.9365971 73.0195726,27.2824 C73.7002154,25.9763676 73.358896,24.2523647 71.9976104,23.3643028 L58.8667933,14.7893932 C55.6791495,13.7329403 52.4316251,12.9250645 49.222025,12.1312213 C46.1950608,11.3814806 41.0779702,10.0491921 38.2156776,9.13005801 C36.3074826,8.51730196 33.4415158,7.0933849 29.6177773,4.85830684 Z" id="Fill-7"></path>
|
||||
<path d="M29.7315665,14.094497 C27.5581473,13.0954401 25.1789914,11.566935 22.5940987,9.50898164 L19.7614089,11.4291886 C22.680354,13.872933 25.1682837,15.5953444 27.225198,16.5964226 C30.3105695,18.09804 42.0831903,21.3149916 42.8121204,21.4949169 C51.5552876,23.6520212 59.5365954,25.256157 66.1778478,31.9045231 C66.1888316,31.9163913 68.9772132,30.2313417 68.797477,30.052416 C61.5001876,22.7464498 52.4120302,20.425361 43.6109479,18.253263 C42.6064223,18.005366 32.9916953,15.5930823 29.7315665,14.094497 Z" id="Fill-11"></path>
|
||||
<path d="M40.2748943,27.6858128 C47.2416777,29.4577639 53.792549,31.5762923 59.3417736,36.4444 L62.2704462,34.569277 C55.9296207,28.6976319 48.8074918,25.8624309 40.7862587,24.3617515 C33.595662,23.0164746 28.8766311,21.3487752 23.507058,19.2459776 C19.9273426,17.8441125 17.1081118,16.3021039 15.0493654,14.6199518 L12.1044223,16.5060931 C15.496129,19.1544049 18.552383,21.0412683 21.2731845,22.1666833 C24.8656838,23.6526619 31.1995871,25.4923718 40.2748943,27.6858128 Z" id="Fill-17"></path>
|
||||
<path d="M5.18885131,21.1343855 C5.29067424,21.2373258 5.38333311,21.3442637 5.48821073,21.4462046 C12.9304487,28.7509644 21.8300234,30.8575975 30.8057147,33.0293369 C38.5788773,34.9092456 45.6427477,36.4683588 51.8987485,41.3005539 L54.8844037,39.3547126 C47.8362204,33.5300936 39.7691873,31.7600736 31.6202982,29.7892176 C22.7942865,27.6534573 14.8355558,25.7666967 8.09895067,19.2774634 L5.18885131,21.1343855 Z" id="Fill-19"></path>
|
||||
<path d="M1.86538962,23.4720365 C0.558922248,24.8286618 0.712329392,27.1676708 2.35067758,28.271683 L12.2679982,34.9570906 C16.6576484,36.8407725 20.0248373,37.7569569 24.5388174,38.9108681 C31.5855194,40.7113852 38.2525371,42.1959537 44.0850166,46.38226 L46.9264812,44.4396723 C40.2948809,39.2709822 32.8228032,37.452366 25.3399436,35.5395764 C16.5616459,33.2962069 9.49263239,31.439221 2.82393361,24.5251104 C2.49004747,24.178937 2.17621456,23.8265263 1.86538962,23.4720365 Z" id="Fill-21"></path>
|
||||
<path d="M34.1645854,49.6645268 C34.893506,50.0634031 35.1425612,50.5086988 36.1796702,50.7 C36.9305233,50.7 37.7585832,50.659873 38.4352738,50.23418 L40.0920678,49.1926318 C34.7693674,45.7494414 29.2447004,43.7586502 23.3471124,42.3058883 L34.1645854,49.6645268 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
BIN
docs/logo/flagger-stacked-black@2x.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
29
docs/logo/flagger-stacked-color.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="160px" height="160px" viewBox="0 0 160 160" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>flagger-stacked-color</title>
|
||||
<g id="flagger-stacked-color" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M10.1931429,149 L10.1931429,125.648 L15.6811429,125.648 L15.6811429,121.952 L10.1931429,121.952 L10.1931429,119.88 C10.1931429,116.408 11.7051429,114.56 14.5051429,114.56 C15.5131429,114.56 16.2411429,114.784 16.9131429,115.176 L17.9771429,111.984 C16.8571429,111.368 15.4571429,111.088 13.8331429,111.088 C9.18514286,111.088 5.99314286,114.28 5.99314286,119.88 L5.99314286,121.952 L1.51314286,121.952 L1.51314286,125.648 L5.99314286,125.648 L5.99314286,149 L10.1931429,149 Z M24.9211429,149 L24.9211429,111.648 L20.7211429,111.648 L20.7211429,149 L24.9211429,149 Z M10.1931429,149 L10.1931429,125.648 L15.6811429,125.648 L15.6811429,121.952 L10.1931429,121.952 L10.1931429,119.88 C10.1931429,116.408 11.7051429,114.56 14.5051429,114.56 C15.5131429,114.56 16.2411429,114.784 16.9131429,115.176 L17.9771429,111.984 C16.8571429,111.368 15.4571429,111.088 13.8331429,111.088 C9.18514286,111.088 5.99314286,114.28 5.99314286,119.88 L5.99314286,121.952 L1.51314286,121.952 L1.51314286,125.648 L5.99314286,125.648 L5.99314286,149 L10.1931429,149 Z M24.9211429,149 L24.9211429,111.648 L20.7211429,111.648 L20.7211429,149 L24.9211429,149 Z M38.9874286,149.672 C42.6274286,149.672 45.7634286,148.384 47.9474286,145.92 L47.9474286,149 L52.1474286,149 L52.1474286,130.408 C52.1474286,123.856 47.4434286,121.28 41.6754286,121.28 C37.2514286,121.28 33.7794286,122.736 30.8674286,125.76 L32.8274286,128.672 C35.2354286,126.04 37.8674286,124.92 41.1154286,124.92 C45.0354286,124.92 47.9474286,126.992 47.9474286,130.576 L47.9474286,135.448 C45.7634286,132.984 42.6834286,131.808 38.9874286,131.808 C34.3954286,131.808 29.5794286,134.608 29.5794286,140.712 C29.5794286,146.592 34.4514286,149.672 38.9874286,149.672 Z M40.5554286,146.648 C36.5794286,146.648 33.8354286,144.184 33.8354286,140.712 C33.8354286,137.296 36.5794286,134.832 40.5554286,134.832 C43.4674286,134.832 46.3234286,135.952 47.9474286,138.136 L47.9474286,143.288 C46.3234286,145.528 43.4674286,146.648 40.5554286,146.648 Z M69.1817143,159.976 C75.7897143,159.976 82.1177143,157.176 82.1177143,148.608 L82.1177143,121.952 L77.9177143,121.952 L77.9177143,126.04 C75.7337143,123.072 72.4297143,121.28 68.7897143,121.28 C61.6777143,121.28 56.7497143,126.656 56.7497143,135.336 C56.7497143,144.072 61.7337143,149.336 68.7897143,149.336 C72.5977143,149.336 75.9017143,147.264 77.9177143,144.52 L77.9177143,148.608 C77.9177143,154.32 73.6617143,156.504 69.1817143,156.504 C65.3177143,156.504 62.6297143,155.496 60.3897143,152.864 L58.2617143,155.888 C61.5097143,159.08 64.6457143,159.976 69.1817143,159.976 Z M69.8537143,145.584 C64.3657143,145.584 61.1177143,141.272 61.1177143,135.336 C61.1177143,129.344 64.3657143,125.032 69.8537143,125.032 C73.1577143,125.032 76.4057143,127.048 77.9177143,129.344 L77.9177143,141.216 C76.4057143,143.568 73.1577143,145.584 69.8537143,145.584 Z M99.096,159.976 C105.704,159.976 112.032,157.176 112.032,148.608 L112.032,121.952 L107.832,121.952 L107.832,126.04 C105.648,123.072 102.344,121.28 98.704,121.28 C91.592,121.28 86.664,126.656 86.664,135.336 C86.664,144.072 91.648,149.336 98.704,149.336 C102.512,149.336 105.816,147.264 107.832,144.52 L107.832,148.608 C107.832,154.32 103.576,156.504 99.096,156.504 C95.232,156.504 92.544,155.496 90.304,152.864 L88.176,155.888 C91.424,159.08 94.56,159.976 99.096,159.976 Z M99.768,145.584 C94.28,145.584 91.032,141.272 91.032,135.336 C91.032,129.344 94.28,125.032 99.768,125.032 C103.072,125.032 106.32,127.048 107.832,129.344 L107.832,141.216 C106.32,143.568 103.072,145.584 99.768,145.584 Z M130.410286,149.672 C134.778286,149.672 138.418286,148.16 141.162286,145.472 L139.146286,142.728 C136.962286,144.968 133.882286,146.2 130.746286,146.2 C124.922286,146.2 121.394286,141.944 121.058286,136.848 L142.898286,136.848 L142.898286,135.784 C142.898286,127.664 138.082286,121.28 129.906286,121.28 C122.178286,121.28 116.578286,127.608 116.578286,135.448 C116.578286,143.904 122.346286,149.672 130.410286,149.672 Z M138.754286,133.712 L121.002286,133.712 C121.226286,129.624 124.082286,124.752 129.850286,124.752 C136.010286,124.752 138.698286,129.736 138.754286,133.712 Z M151.588571,149 L151.588571,129.848 C152.820571,127.664 156.348571,125.536 158.980571,125.536 C159.596571,125.536 160.100571,125.592 160.604571,125.648 L160.604571,121.336 C156.908571,121.336 153.772571,123.464 151.588571,126.264 L151.588571,121.952 L147.388571,121.952 L147.388571,149 L151.588571,149 Z" id="fflagger" fill="#1A1A1A" fill-rule="nonzero"></path>
|
||||
<g id="flags" transform="translate(26.036697, 0.500000)" fill="#7BB09F">
|
||||
<path d="M53.9358922,0.7 L53.9361614,0.7149 L53.9361614,0.7149 L53.9369368,0.9336 C53.9370203,0.972 53.9371029,1.015 53.9371847,1.0625 L53.9378977,1.6088 C53.9379744,1.6824 53.9380503,1.7602 53.9381254,1.8421 L53.9389868,3.0153 C53.9390554,3.1284 53.9391232,3.2452 53.9391903,3.3656 L53.9399577,4.9768 C53.9400186,5.1244 53.9400788,5.2752 53.9401383,5.4291 L53.9409762,7.9576 C53.9410285,8.14 53.9410802,8.325 53.9411311,8.5125 L53.9419772,12.1359 C53.9420204,12.3498 53.9420629,12.5656 53.9421048,12.7832 L53.9429968,18.3 C53.9430294,18.54 53.9430615,18.781 53.943093,19.0229 L53.943952,27.1992 C53.9439728,27.4488 53.9439933,27.6982 53.9440133,27.9473 L53.9449541,50.7 L53.9449541,50.7 C53.3879217,50.7014777 52.830488,50.538921 52.3437254,50.211951 L19.6313575,28.2303499 C19.498497,28.1410415 19.375601,28.0433533 19.2626695,27.9385428 L1.40077569,39.7 C-0.466925231,38.5321603 -0.466925231,35.903287 1.40077569,34.7364344 L33.206,14.047 L52.3437254,1.18768595 C52.8278484,0.862489056 53.3818782,0.7 53.9358922,0.7 Z" id="Combined-Shape"></path>
|
||||
<path d="M53.9449541,53.7 C54.518545,53.6973849 55.0927551,53.8599359 55.5939898,54.1878202 L89.1239541,76.1279689 L105.632086,65.7 C107.358112,66.8668656 107.358112,69.4957682 105.632086,70.663621 L73.3882295,91.6036587 C73.3686858,91.6168729 73.348778,91.6191194 73.3286088,91.6113313 L55.5939898,103.212312 C55.1094503,103.529275 54.5567157,103.691735 54.0022691,103.7 L54.0020013,103.4664 C54.0019573,103.428 54.001908,103.385 54.0018535,103.3375 L54.0009599,102.5579 C54.000866,102.476 54.0007674,102.39 54.0006643,102.3 L53.9999912,101.7128 C53.9953913,97.7 53.9845014,88.2 53.9736116,78.7 L53.9718931,77.2008 C53.9627374,69.2136 53.9538164,61.4312 53.9488864,57.1304 L53.9480097,56.3656 C53.9475957,56.0044 53.9472188,55.6756 53.9468821,55.3819 L53.9459959,54.6088 C53.9459115,54.5352 53.945832,54.4658 53.9457573,54.4007 L53.9449541,53.7 L53.9449541,53.7 Z" id="Combined-Shape"></path>
|
||||
<g id="Group-Copy" transform="translate(17.363303, 0.000000)">
|
||||
<path d="M40.0825271,2.57811824 C39.3101975,2.18406772 37.9113821,0.772333321 36.5592679,0.815362703 C35.3879258,0.815362703 34.9298365,1.30862747 33.0353111,2.57811824 C35.6703059,3.73059649 45.4272614,7.16970562 48.1569327,7.9404 C43.8145304,5.00479909 41.1230619,3.21737183 40.0825271,2.57811824 Z" id="Fill-5"></path>
|
||||
<path d="M29.6177773,4.85830684 L26.6147653,6.81885893 C29.4750473,8.76729329 32.2115554,10.2845904 34.8242897,11.3707502 C40.1341913,13.5781702 46.8841749,14.9995752 48.423617,15.3807663 C57.1621923,17.5447908 65.4157347,19.5875337 72.0525009,26.2540122 C72.3898283,26.5917965 72.7061975,26.9365971 73.0195726,27.2824 C73.7002154,25.9763676 73.358896,24.2523647 71.9976104,23.3643028 L58.8667933,14.7893932 C55.6791495,13.7329403 52.4316251,12.9250645 49.222025,12.1312213 C46.1950608,11.3814806 41.0779702,10.0491921 38.2156776,9.13005801 C36.3074826,8.51730196 33.4415158,7.0933849 29.6177773,4.85830684 Z" id="Fill-7"></path>
|
||||
<path d="M29.7315665,14.094497 C27.5581473,13.0954401 25.1789914,11.566935 22.5940987,9.50898164 L19.7614089,11.4291886 C22.680354,13.872933 25.1682837,15.5953444 27.225198,16.5964226 C30.3105695,18.09804 42.0831903,21.3149916 42.8121204,21.4949169 C51.5552876,23.6520212 59.5365954,25.256157 66.1778478,31.9045231 C66.1888316,31.9163913 68.9772132,30.2313417 68.797477,30.052416 C61.5001876,22.7464498 52.4120302,20.425361 43.6109479,18.253263 C42.6064223,18.005366 32.9916953,15.5930823 29.7315665,14.094497 Z" id="Fill-11"></path>
|
||||
<path d="M40.2748943,27.6858128 C47.2416777,29.4577639 53.792549,31.5762923 59.3417736,36.4444 L62.2704462,34.569277 C55.9296207,28.6976319 48.8074918,25.8624309 40.7862587,24.3617515 C33.595662,23.0164746 28.8766311,21.3487752 23.507058,19.2459776 C19.9273426,17.8441125 17.1081118,16.3021039 15.0493654,14.6199518 L12.1044223,16.5060931 C15.496129,19.1544049 18.552383,21.0412683 21.2731845,22.1666833 C24.8656838,23.6526619 31.1995871,25.4923718 40.2748943,27.6858128 Z" id="Fill-17"></path>
|
||||
<path d="M5.18885131,21.1343855 C5.29067424,21.2373258 5.38333311,21.3442637 5.48821073,21.4462046 C12.9304487,28.7509644 21.8300234,30.8575975 30.8057147,33.0293369 C38.5788773,34.9092456 45.6427477,36.4683588 51.8987485,41.3005539 L54.8844037,39.3547126 C47.8362204,33.5300936 39.7691873,31.7600736 31.6202982,29.7892176 C22.7942865,27.6534573 14.8355558,25.7666967 8.09895067,19.2774634 L5.18885131,21.1343855 Z" id="Fill-19"></path>
|
||||
<path d="M1.86538962,23.4720365 C0.558922248,24.8286618 0.712329392,27.1676708 2.35067758,28.271683 L12.2679982,34.9570906 C16.6576484,36.8407725 20.0248373,37.7569569 24.5388174,38.9108681 C31.5855194,40.7113852 38.2525371,42.1959537 44.0850166,46.38226 L46.9264812,44.4396723 C40.2948809,39.2709822 32.8228032,37.452366 25.3399436,35.5395764 C16.5616459,33.2962069 9.49263239,31.439221 2.82393361,24.5251104 C2.49004747,24.178937 2.17621456,23.8265263 1.86538962,23.4720365 Z" id="Fill-21"></path>
|
||||
<path d="M34.1645854,49.6645268 C34.893506,50.0634031 35.1425612,50.5086988 36.1796702,50.7 C36.9305233,50.7 37.7585832,50.659873 38.4352738,50.23418 L40.0920678,49.1926318 C34.7693674,45.7494414 29.2447004,43.7586502 23.3471124,42.3058883 L34.1645854,49.6645268 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
<g id="Group-Copy-2" transform="translate(17.363303, 53.000000)">
|
||||
<path d="M40.0825271,2.57811824 C39.3101975,2.18406772 37.9113821,0.772333321 36.5592679,0.815362703 C35.3879258,0.815362703 34.9298365,1.30862747 33.0353111,2.57811824 C35.6703059,3.73059649 45.4272614,7.16970562 48.1569327,7.9404 C43.8145304,5.00479909 41.1230619,3.21737183 40.0825271,2.57811824 Z" id="Fill-5"></path>
|
||||
<path d="M29.6177773,4.85830684 L26.6147653,6.81885893 C29.4750473,8.76729329 32.2115554,10.2845904 34.8242897,11.3707502 C40.1341913,13.5781702 46.8841749,14.9995752 48.423617,15.3807663 C57.1621923,17.5447908 65.4157347,19.5875337 72.0525009,26.2540122 C72.3898283,26.5917965 72.7061975,26.9365971 73.0195726,27.2824 C73.7002154,25.9763676 73.358896,24.2523647 71.9976104,23.3643028 L58.8667933,14.7893932 C55.6791495,13.7329403 52.4316251,12.9250645 49.222025,12.1312213 C46.1950608,11.3814806 41.0779702,10.0491921 38.2156776,9.13005801 C36.3074826,8.51730196 33.4415158,7.0933849 29.6177773,4.85830684 Z" id="Fill-7"></path>
|
||||
<path d="M29.7315665,14.094497 C27.5581473,13.0954401 25.1789914,11.566935 22.5940987,9.50898164 L19.7614089,11.4291886 C22.680354,13.872933 25.1682837,15.5953444 27.225198,16.5964226 C30.3105695,18.09804 42.0831903,21.3149916 42.8121204,21.4949169 C51.5552876,23.6520212 59.5365954,25.256157 66.1778478,31.9045231 C66.1888316,31.9163913 68.9772132,30.2313417 68.797477,30.052416 C61.5001876,22.7464498 52.4120302,20.425361 43.6109479,18.253263 C42.6064223,18.005366 32.9916953,15.5930823 29.7315665,14.094497 Z" id="Fill-11"></path>
|
||||
<path d="M40.2748943,27.6858128 C47.2416777,29.4577639 53.792549,31.5762923 59.3417736,36.4444 L62.2704462,34.569277 C55.9296207,28.6976319 48.8074918,25.8624309 40.7862587,24.3617515 C33.595662,23.0164746 28.8766311,21.3487752 23.507058,19.2459776 C19.9273426,17.8441125 17.1081118,16.3021039 15.0493654,14.6199518 L12.1044223,16.5060931 C15.496129,19.1544049 18.552383,21.0412683 21.2731845,22.1666833 C24.8656838,23.6526619 31.1995871,25.4923718 40.2748943,27.6858128 Z" id="Fill-17"></path>
|
||||
<path d="M5.18885131,21.1343855 C5.29067424,21.2373258 5.38333311,21.3442637 5.48821073,21.4462046 C12.9304487,28.7509644 21.8300234,30.8575975 30.8057147,33.0293369 C38.5788773,34.9092456 45.6427477,36.4683588 51.8987485,41.3005539 L54.8844037,39.3547126 C47.8362204,33.5300936 39.7691873,31.7600736 31.6202982,29.7892176 C22.7942865,27.6534573 14.8355558,25.7666967 8.09895067,19.2774634 L5.18885131,21.1343855 Z" id="Fill-19"></path>
|
||||
<path d="M1.86538962,23.4720365 C0.558922248,24.8286618 0.712329392,27.1676708 2.35067758,28.271683 L12.2679982,34.9570906 C16.6576484,36.8407725 20.0248373,37.7569569 24.5388174,38.9108681 C31.5855194,40.7113852 38.2525371,42.1959537 44.0850166,46.38226 L46.9264812,44.4396723 C40.2948809,39.2709822 32.8228032,37.452366 25.3399436,35.5395764 C16.5616459,33.2962069 9.49263239,31.439221 2.82393361,24.5251104 C2.49004747,24.178937 2.17621456,23.8265263 1.86538962,23.4720365 Z" id="Fill-21"></path>
|
||||
<path d="M34.1645854,49.6645268 C34.893506,50.0634031 35.1425612,50.5086988 36.1796702,50.7 C36.9305233,50.7 37.7585832,50.659873 38.4352738,50.23418 L40.0920678,49.1926318 C34.7693674,45.7494414 29.2447004,43.7586502 23.3471124,42.3058883 L34.1645854,49.6645268 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
BIN
docs/logo/flagger-stacked-color@2x.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
29
docs/logo/flagger-stacked-white.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="160px" height="160px" viewBox="0 0 160 160" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>flagger-stacked-white</title>
|
||||
<g id="flagger-stacked-white" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M10.1931429,149 L10.1931429,125.648 L15.6811429,125.648 L15.6811429,121.952 L10.1931429,121.952 L10.1931429,119.88 C10.1931429,116.408 11.7051429,114.56 14.5051429,114.56 C15.5131429,114.56 16.2411429,114.784 16.9131429,115.176 L17.9771429,111.984 C16.8571429,111.368 15.4571429,111.088 13.8331429,111.088 C9.18514286,111.088 5.99314286,114.28 5.99314286,119.88 L5.99314286,121.952 L1.51314286,121.952 L1.51314286,125.648 L5.99314286,125.648 L5.99314286,149 L10.1931429,149 Z M24.9211429,149 L24.9211429,111.648 L20.7211429,111.648 L20.7211429,149 L24.9211429,149 Z M10.1931429,149 L10.1931429,125.648 L15.6811429,125.648 L15.6811429,121.952 L10.1931429,121.952 L10.1931429,119.88 C10.1931429,116.408 11.7051429,114.56 14.5051429,114.56 C15.5131429,114.56 16.2411429,114.784 16.9131429,115.176 L17.9771429,111.984 C16.8571429,111.368 15.4571429,111.088 13.8331429,111.088 C9.18514286,111.088 5.99314286,114.28 5.99314286,119.88 L5.99314286,121.952 L1.51314286,121.952 L1.51314286,125.648 L5.99314286,125.648 L5.99314286,149 L10.1931429,149 Z M24.9211429,149 L24.9211429,111.648 L20.7211429,111.648 L20.7211429,149 L24.9211429,149 Z M38.9874286,149.672 C42.6274286,149.672 45.7634286,148.384 47.9474286,145.92 L47.9474286,149 L52.1474286,149 L52.1474286,130.408 C52.1474286,123.856 47.4434286,121.28 41.6754286,121.28 C37.2514286,121.28 33.7794286,122.736 30.8674286,125.76 L32.8274286,128.672 C35.2354286,126.04 37.8674286,124.92 41.1154286,124.92 C45.0354286,124.92 47.9474286,126.992 47.9474286,130.576 L47.9474286,135.448 C45.7634286,132.984 42.6834286,131.808 38.9874286,131.808 C34.3954286,131.808 29.5794286,134.608 29.5794286,140.712 C29.5794286,146.592 34.4514286,149.672 38.9874286,149.672 Z M40.5554286,146.648 C36.5794286,146.648 33.8354286,144.184 33.8354286,140.712 C33.8354286,137.296 36.5794286,134.832 40.5554286,134.832 C43.4674286,134.832 46.3234286,135.952 47.9474286,138.136 L47.9474286,143.288 C46.3234286,145.528 43.4674286,146.648 40.5554286,146.648 Z M69.1817143,159.976 C75.7897143,159.976 82.1177143,157.176 82.1177143,148.608 L82.1177143,121.952 L77.9177143,121.952 L77.9177143,126.04 C75.7337143,123.072 72.4297143,121.28 68.7897143,121.28 C61.6777143,121.28 56.7497143,126.656 56.7497143,135.336 C56.7497143,144.072 61.7337143,149.336 68.7897143,149.336 C72.5977143,149.336 75.9017143,147.264 77.9177143,144.52 L77.9177143,148.608 C77.9177143,154.32 73.6617143,156.504 69.1817143,156.504 C65.3177143,156.504 62.6297143,155.496 60.3897143,152.864 L58.2617143,155.888 C61.5097143,159.08 64.6457143,159.976 69.1817143,159.976 Z M69.8537143,145.584 C64.3657143,145.584 61.1177143,141.272 61.1177143,135.336 C61.1177143,129.344 64.3657143,125.032 69.8537143,125.032 C73.1577143,125.032 76.4057143,127.048 77.9177143,129.344 L77.9177143,141.216 C76.4057143,143.568 73.1577143,145.584 69.8537143,145.584 Z M99.096,159.976 C105.704,159.976 112.032,157.176 112.032,148.608 L112.032,121.952 L107.832,121.952 L107.832,126.04 C105.648,123.072 102.344,121.28 98.704,121.28 C91.592,121.28 86.664,126.656 86.664,135.336 C86.664,144.072 91.648,149.336 98.704,149.336 C102.512,149.336 105.816,147.264 107.832,144.52 L107.832,148.608 C107.832,154.32 103.576,156.504 99.096,156.504 C95.232,156.504 92.544,155.496 90.304,152.864 L88.176,155.888 C91.424,159.08 94.56,159.976 99.096,159.976 Z M99.768,145.584 C94.28,145.584 91.032,141.272 91.032,135.336 C91.032,129.344 94.28,125.032 99.768,125.032 C103.072,125.032 106.32,127.048 107.832,129.344 L107.832,141.216 C106.32,143.568 103.072,145.584 99.768,145.584 Z M130.410286,149.672 C134.778286,149.672 138.418286,148.16 141.162286,145.472 L139.146286,142.728 C136.962286,144.968 133.882286,146.2 130.746286,146.2 C124.922286,146.2 121.394286,141.944 121.058286,136.848 L142.898286,136.848 L142.898286,135.784 C142.898286,127.664 138.082286,121.28 129.906286,121.28 C122.178286,121.28 116.578286,127.608 116.578286,135.448 C116.578286,143.904 122.346286,149.672 130.410286,149.672 Z M138.754286,133.712 L121.002286,133.712 C121.226286,129.624 124.082286,124.752 129.850286,124.752 C136.010286,124.752 138.698286,129.736 138.754286,133.712 Z M151.588571,149 L151.588571,129.848 C152.820571,127.664 156.348571,125.536 158.980571,125.536 C159.596571,125.536 160.100571,125.592 160.604571,125.648 L160.604571,121.336 C156.908571,121.336 153.772571,123.464 151.588571,126.264 L151.588571,121.952 L147.388571,121.952 L147.388571,149 L151.588571,149 Z" id="fflagger" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
<g id="flags" transform="translate(26.036697, 0.500000)" fill="#FFFFFF">
|
||||
<path d="M53.9358922,0.7 L53.9361614,0.7149 L53.9361614,0.7149 L53.9369368,0.9336 C53.9370203,0.972 53.9371029,1.015 53.9371847,1.0625 L53.9378977,1.6088 C53.9379744,1.6824 53.9380503,1.7602 53.9381254,1.8421 L53.9389868,3.0153 C53.9390554,3.1284 53.9391232,3.2452 53.9391903,3.3656 L53.9399577,4.9768 C53.9400186,5.1244 53.9400788,5.2752 53.9401383,5.4291 L53.9409762,7.9576 C53.9410285,8.14 53.9410802,8.325 53.9411311,8.5125 L53.9419772,12.1359 C53.9420204,12.3498 53.9420629,12.5656 53.9421048,12.7832 L53.9429968,18.3 C53.9430294,18.54 53.9430615,18.781 53.943093,19.0229 L53.943952,27.1992 C53.9439728,27.4488 53.9439933,27.6982 53.9440133,27.9473 L53.9449541,50.7 L53.9449541,50.7 C53.3879217,50.7014777 52.830488,50.538921 52.3437254,50.211951 L19.6313575,28.2303499 C19.498497,28.1410415 19.375601,28.0433533 19.2626695,27.9385428 L1.40077569,39.7 C-0.466925231,38.5321603 -0.466925231,35.903287 1.40077569,34.7364344 L33.206,14.047 L52.3437254,1.18768595 C52.8278484,0.862489056 53.3818782,0.7 53.9358922,0.7 Z" id="Combined-Shape"></path>
|
||||
<path d="M53.9449541,53.7 C54.518545,53.6973849 55.0927551,53.8599359 55.5939898,54.1878202 L89.1239541,76.1279689 L105.632086,65.7 C107.358112,66.8668656 107.358112,69.4957682 105.632086,70.663621 L73.3882295,91.6036587 C73.3686858,91.6168729 73.348778,91.6191194 73.3286088,91.6113313 L55.5939898,103.212312 C55.1094503,103.529275 54.5567157,103.691735 54.0022691,103.7 L54.0020013,103.4664 C54.0019573,103.428 54.001908,103.385 54.0018535,103.3375 L54.0009599,102.5579 C54.000866,102.476 54.0007674,102.39 54.0006643,102.3 L53.9999912,101.7128 C53.9953913,97.7 53.9845014,88.2 53.9736116,78.7 L53.9718931,77.2008 C53.9627374,69.2136 53.9538164,61.4312 53.9488864,57.1304 L53.9480097,56.3656 C53.9475957,56.0044 53.9472188,55.6756 53.9468821,55.3819 L53.9459959,54.6088 C53.9459115,54.5352 53.945832,54.4658 53.9457573,54.4007 L53.9449541,53.7 L53.9449541,53.7 Z" id="Combined-Shape"></path>
|
||||
<g id="Group-Copy" transform="translate(17.363303, 0.000000)">
|
||||
<path d="M40.0825271,2.57811824 C39.3101975,2.18406772 37.9113821,0.772333321 36.5592679,0.815362703 C35.3879258,0.815362703 34.9298365,1.30862747 33.0353111,2.57811824 C35.6703059,3.73059649 45.4272614,7.16970562 48.1569327,7.9404 C43.8145304,5.00479909 41.1230619,3.21737183 40.0825271,2.57811824 Z" id="Fill-5"></path>
|
||||
<path d="M29.6177773,4.85830684 L26.6147653,6.81885893 C29.4750473,8.76729329 32.2115554,10.2845904 34.8242897,11.3707502 C40.1341913,13.5781702 46.8841749,14.9995752 48.423617,15.3807663 C57.1621923,17.5447908 65.4157347,19.5875337 72.0525009,26.2540122 C72.3898283,26.5917965 72.7061975,26.9365971 73.0195726,27.2824 C73.7002154,25.9763676 73.358896,24.2523647 71.9976104,23.3643028 L58.8667933,14.7893932 C55.6791495,13.7329403 52.4316251,12.9250645 49.222025,12.1312213 C46.1950608,11.3814806 41.0779702,10.0491921 38.2156776,9.13005801 C36.3074826,8.51730196 33.4415158,7.0933849 29.6177773,4.85830684 Z" id="Fill-7"></path>
|
||||
<path d="M29.7315665,14.094497 C27.5581473,13.0954401 25.1789914,11.566935 22.5940987,9.50898164 L19.7614089,11.4291886 C22.680354,13.872933 25.1682837,15.5953444 27.225198,16.5964226 C30.3105695,18.09804 42.0831903,21.3149916 42.8121204,21.4949169 C51.5552876,23.6520212 59.5365954,25.256157 66.1778478,31.9045231 C66.1888316,31.9163913 68.9772132,30.2313417 68.797477,30.052416 C61.5001876,22.7464498 52.4120302,20.425361 43.6109479,18.253263 C42.6064223,18.005366 32.9916953,15.5930823 29.7315665,14.094497 Z" id="Fill-11"></path>
|
||||
<path d="M40.2748943,27.6858128 C47.2416777,29.4577639 53.792549,31.5762923 59.3417736,36.4444 L62.2704462,34.569277 C55.9296207,28.6976319 48.8074918,25.8624309 40.7862587,24.3617515 C33.595662,23.0164746 28.8766311,21.3487752 23.507058,19.2459776 C19.9273426,17.8441125 17.1081118,16.3021039 15.0493654,14.6199518 L12.1044223,16.5060931 C15.496129,19.1544049 18.552383,21.0412683 21.2731845,22.1666833 C24.8656838,23.6526619 31.1995871,25.4923718 40.2748943,27.6858128 Z" id="Fill-17"></path>
|
||||
<path d="M5.18885131,21.1343855 C5.29067424,21.2373258 5.38333311,21.3442637 5.48821073,21.4462046 C12.9304487,28.7509644 21.8300234,30.8575975 30.8057147,33.0293369 C38.5788773,34.9092456 45.6427477,36.4683588 51.8987485,41.3005539 L54.8844037,39.3547126 C47.8362204,33.5300936 39.7691873,31.7600736 31.6202982,29.7892176 C22.7942865,27.6534573 14.8355558,25.7666967 8.09895067,19.2774634 L5.18885131,21.1343855 Z" id="Fill-19"></path>
|
||||
<path d="M1.86538962,23.4720365 C0.558922248,24.8286618 0.712329392,27.1676708 2.35067758,28.271683 L12.2679982,34.9570906 C16.6576484,36.8407725 20.0248373,37.7569569 24.5388174,38.9108681 C31.5855194,40.7113852 38.2525371,42.1959537 44.0850166,46.38226 L46.9264812,44.4396723 C40.2948809,39.2709822 32.8228032,37.452366 25.3399436,35.5395764 C16.5616459,33.2962069 9.49263239,31.439221 2.82393361,24.5251104 C2.49004747,24.178937 2.17621456,23.8265263 1.86538962,23.4720365 Z" id="Fill-21"></path>
|
||||
<path d="M34.1645854,49.6645268 C34.893506,50.0634031 35.1425612,50.5086988 36.1796702,50.7 C36.9305233,50.7 37.7585832,50.659873 38.4352738,50.23418 L40.0920678,49.1926318 C34.7693674,45.7494414 29.2447004,43.7586502 23.3471124,42.3058883 L34.1645854,49.6645268 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
<g id="Group-Copy-2" transform="translate(17.363303, 53.000000)">
|
||||
<path d="M40.0825271,2.57811824 C39.3101975,2.18406772 37.9113821,0.772333321 36.5592679,0.815362703 C35.3879258,0.815362703 34.9298365,1.30862747 33.0353111,2.57811824 C35.6703059,3.73059649 45.4272614,7.16970562 48.1569327,7.9404 C43.8145304,5.00479909 41.1230619,3.21737183 40.0825271,2.57811824 Z" id="Fill-5"></path>
|
||||
<path d="M29.6177773,4.85830684 L26.6147653,6.81885893 C29.4750473,8.76729329 32.2115554,10.2845904 34.8242897,11.3707502 C40.1341913,13.5781702 46.8841749,14.9995752 48.423617,15.3807663 C57.1621923,17.5447908 65.4157347,19.5875337 72.0525009,26.2540122 C72.3898283,26.5917965 72.7061975,26.9365971 73.0195726,27.2824 C73.7002154,25.9763676 73.358896,24.2523647 71.9976104,23.3643028 L58.8667933,14.7893932 C55.6791495,13.7329403 52.4316251,12.9250645 49.222025,12.1312213 C46.1950608,11.3814806 41.0779702,10.0491921 38.2156776,9.13005801 C36.3074826,8.51730196 33.4415158,7.0933849 29.6177773,4.85830684 Z" id="Fill-7"></path>
|
||||
<path d="M29.7315665,14.094497 C27.5581473,13.0954401 25.1789914,11.566935 22.5940987,9.50898164 L19.7614089,11.4291886 C22.680354,13.872933 25.1682837,15.5953444 27.225198,16.5964226 C30.3105695,18.09804 42.0831903,21.3149916 42.8121204,21.4949169 C51.5552876,23.6520212 59.5365954,25.256157 66.1778478,31.9045231 C66.1888316,31.9163913 68.9772132,30.2313417 68.797477,30.052416 C61.5001876,22.7464498 52.4120302,20.425361 43.6109479,18.253263 C42.6064223,18.005366 32.9916953,15.5930823 29.7315665,14.094497 Z" id="Fill-11"></path>
|
||||
<path d="M40.2748943,27.6858128 C47.2416777,29.4577639 53.792549,31.5762923 59.3417736,36.4444 L62.2704462,34.569277 C55.9296207,28.6976319 48.8074918,25.8624309 40.7862587,24.3617515 C33.595662,23.0164746 28.8766311,21.3487752 23.507058,19.2459776 C19.9273426,17.8441125 17.1081118,16.3021039 15.0493654,14.6199518 L12.1044223,16.5060931 C15.496129,19.1544049 18.552383,21.0412683 21.2731845,22.1666833 C24.8656838,23.6526619 31.1995871,25.4923718 40.2748943,27.6858128 Z" id="Fill-17"></path>
|
||||
<path d="M5.18885131,21.1343855 C5.29067424,21.2373258 5.38333311,21.3442637 5.48821073,21.4462046 C12.9304487,28.7509644 21.8300234,30.8575975 30.8057147,33.0293369 C38.5788773,34.9092456 45.6427477,36.4683588 51.8987485,41.3005539 L54.8844037,39.3547126 C47.8362204,33.5300936 39.7691873,31.7600736 31.6202982,29.7892176 C22.7942865,27.6534573 14.8355558,25.7666967 8.09895067,19.2774634 L5.18885131,21.1343855 Z" id="Fill-19"></path>
|
||||
<path d="M1.86538962,23.4720365 C0.558922248,24.8286618 0.712329392,27.1676708 2.35067758,28.271683 L12.2679982,34.9570906 C16.6576484,36.8407725 20.0248373,37.7569569 24.5388174,38.9108681 C31.5855194,40.7113852 38.2525371,42.1959537 44.0850166,46.38226 L46.9264812,44.4396723 C40.2948809,39.2709822 32.8228032,37.452366 25.3399436,35.5395764 C16.5616459,33.2962069 9.49263239,31.439221 2.82393361,24.5251104 C2.49004747,24.178937 2.17621456,23.8265263 1.86538962,23.4720365 Z" id="Fill-21"></path>
|
||||
<path d="M34.1645854,49.6645268 C34.893506,50.0634031 35.1425612,50.5086988 36.1796702,50.7 C36.9305233,50.7 37.7585832,50.659873 38.4352738,50.23418 L40.0920678,49.1926318 C34.7693674,45.7494414 29.2447004,43.7586502 23.3471124,42.3058883 L34.1645854,49.6645268 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
BIN
docs/logo/flagger-stacked-white@2x.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
29
docs/logo/flagger-vertical-black.svg
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="359px" height="106px" viewBox="0 0 359 106" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>flagger-vertical-black</title>
|
||||
<g id="flagger-vertical-black" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M136.167,78 L136.167,45.891 L143.713,45.891 L143.713,40.809 L136.167,40.809 L136.167,37.96 C136.167,33.186 138.246,30.645 142.096,30.645 C143.482,30.645 144.483,30.953 145.407,31.492 L146.87,27.103 C145.33,26.256 143.405,25.871 141.172,25.871 C134.781,25.871 130.392,30.26 130.392,37.96 L130.392,40.809 L124.232,40.809 L124.232,45.891 L130.392,45.891 L130.392,78 L136.167,78 Z M156.418,78 L156.418,26.641 L150.643,26.641 L150.643,78 L156.418,78 Z M136.167,78 L136.167,45.891 L143.713,45.891 L143.713,40.809 L136.167,40.809 L136.167,37.96 C136.167,33.186 138.246,30.645 142.096,30.645 C143.482,30.645 144.483,30.953 145.407,31.492 L146.87,27.103 C145.33,26.256 143.405,25.871 141.172,25.871 C134.781,25.871 130.392,30.26 130.392,37.96 L130.392,40.809 L124.232,40.809 L124.232,45.891 L130.392,45.891 L130.392,78 L136.167,78 Z M156.418,78 L156.418,26.641 L150.643,26.641 L150.643,78 L156.418,78 Z M178.902,78.924 C183.907,78.924 188.219,77.153 191.222,73.765 L191.222,78 L196.997,78 L196.997,52.436 C196.997,43.427 190.529,39.885 182.598,39.885 C176.515,39.885 171.741,41.887 167.737,46.045 L170.432,50.049 C173.743,46.43 177.362,44.89 181.828,44.89 C187.218,44.89 191.222,47.739 191.222,52.667 L191.222,59.366 C188.219,55.978 183.984,54.361 178.902,54.361 C172.588,54.361 165.966,58.211 165.966,66.604 C165.966,74.689 172.665,78.924 178.902,78.924 Z M181.058,74.766 C175.591,74.766 171.818,71.378 171.818,66.604 C171.818,61.907 175.591,58.519 181.058,58.519 C185.062,58.519 188.989,60.059 191.222,63.062 L191.222,70.146 C188.989,73.226 185.062,74.766 181.058,74.766 Z M223.562,93.092 C232.648,93.092 241.349,89.242 241.349,77.461 L241.349,40.809 L235.574,40.809 L235.574,46.43 C232.571,42.349 228.028,39.885 223.023,39.885 C213.244,39.885 206.468,47.277 206.468,59.212 C206.468,71.224 213.321,78.462 223.023,78.462 C228.259,78.462 232.802,75.613 235.574,71.84 L235.574,77.461 C235.574,85.315 229.722,88.318 223.562,88.318 C218.249,88.318 214.553,86.932 211.473,83.313 L208.547,87.471 C213.013,91.86 217.325,93.092 223.562,93.092 Z M224.486,73.303 C216.94,73.303 212.474,67.374 212.474,59.212 C212.474,50.973 216.94,45.044 224.486,45.044 C229.029,45.044 233.495,47.816 235.574,50.973 L235.574,67.297 C233.495,70.531 229.029,73.303 224.486,73.303 Z M267.837,93.092 C276.923,93.092 285.624,89.242 285.624,77.461 L285.624,40.809 L279.849,40.809 L279.849,46.43 C276.846,42.349 272.303,39.885 267.298,39.885 C257.519,39.885 250.743,47.277 250.743,59.212 C250.743,71.224 257.596,78.462 267.298,78.462 C272.534,78.462 277.077,75.613 279.849,71.84 L279.849,77.461 C279.849,85.315 273.997,88.318 267.837,88.318 C262.524,88.318 258.828,86.932 255.748,83.313 L252.822,87.471 C257.288,91.86 261.6,93.092 267.837,93.092 Z M268.761,73.303 C261.215,73.303 256.749,67.374 256.749,59.212 C256.749,50.973 261.215,45.044 268.761,45.044 C273.304,45.044 277.77,47.816 279.849,50.973 L279.849,67.297 C277.77,70.531 273.304,73.303 268.761,73.303 Z M314.037,78.924 C320.043,78.924 325.048,76.845 328.821,73.149 L326.049,69.376 C323.046,72.456 318.811,74.15 314.499,74.15 C306.491,74.15 301.64,68.298 301.178,61.291 L331.208,61.291 L331.208,59.828 C331.208,48.663 324.586,39.885 313.344,39.885 C302.718,39.885 295.018,48.586 295.018,59.366 C295.018,70.993 302.949,78.924 314.037,78.924 Z M325.51,56.979 L301.101,56.979 C301.409,51.358 305.336,44.659 313.267,44.659 C321.737,44.659 325.433,51.512 325.51,56.979 Z M346.3,78 L346.3,51.666 C347.994,48.663 352.845,45.737 356.464,45.737 C357.311,45.737 358.004,45.814 358.697,45.891 L358.697,39.962 C353.615,39.962 349.303,42.888 346.3,46.738 L346.3,40.809 L340.525,40.809 L340.525,78 L346.3,78 Z" id="fflagger" fill="#1A1A1A" fill-rule="nonzero"></path>
|
||||
<g id="flags" transform="translate(0.036697, 0.500000)" fill="#1A1A1A">
|
||||
<path d="M53.9358922,0.7 L53.9361614,0.7149 L53.9361614,0.7149 L53.9369368,0.9336 C53.9370203,0.972 53.9371029,1.015 53.9371847,1.0625 L53.9378977,1.6088 C53.9379744,1.6824 53.9380503,1.7602 53.9381254,1.8421 L53.9389868,3.0153 C53.9390554,3.1284 53.9391232,3.2452 53.9391903,3.3656 L53.9399577,4.9768 C53.9400186,5.1244 53.9400788,5.2752 53.9401383,5.4291 L53.9409762,7.9576 C53.9410285,8.14 53.9410802,8.325 53.9411311,8.5125 L53.9419772,12.1359 C53.9420204,12.3498 53.9420629,12.5656 53.9421048,12.7832 L53.9429968,18.3 C53.9430294,18.54 53.9430615,18.781 53.943093,19.0229 L53.943952,27.1992 C53.9439728,27.4488 53.9439933,27.6982 53.9440133,27.9473 L53.9449541,50.7 L53.9449541,50.7 C53.3879217,50.7014777 52.830488,50.538921 52.3437254,50.211951 L19.6313575,28.2303499 C19.498497,28.1410415 19.375601,28.0433533 19.2626695,27.9385428 L1.40077569,39.7 C-0.466925231,38.5321603 -0.466925231,35.903287 1.40077569,34.7364344 L33.206,14.047 L52.3437254,1.18768595 C52.8278484,0.862489056 53.3818782,0.7 53.9358922,0.7 Z" id="Combined-Shape"></path>
|
||||
<path d="M53.9449541,53.7 C54.518545,53.6973849 55.0927551,53.8599359 55.5939898,54.1878202 L89.1239541,76.1279689 L105.632086,65.7 C107.358112,66.8668656 107.358112,69.4957682 105.632086,70.663621 L73.3882295,91.6036587 C73.3686858,91.6168729 73.348778,91.6191194 73.3286088,91.6113313 L55.5939898,103.212312 C55.1094503,103.529275 54.5567157,103.691735 54.0022691,103.7 L54.0020013,103.4664 C54.0019573,103.428 54.001908,103.385 54.0018535,103.3375 L54.0009599,102.5579 C54.000866,102.476 54.0007674,102.39 54.0006643,102.3 L53.9999912,101.7128 C53.9953913,97.7 53.9845014,88.2 53.9736116,78.7 L53.9718931,77.2008 C53.9627374,69.2136 53.9538164,61.4312 53.9488864,57.1304 L53.9480097,56.3656 C53.9475957,56.0044 53.9472188,55.6756 53.9468821,55.3819 L53.9459959,54.6088 C53.9459115,54.5352 53.945832,54.4658 53.9457573,54.4007 L53.9449541,53.7 L53.9449541,53.7 Z" id="Combined-Shape"></path>
|
||||
<g id="Group-Copy" transform="translate(17.363303, 0.000000)">
|
||||
<path d="M40.0825271,2.57811824 C39.3101975,2.18406772 37.9113821,0.772333321 36.5592679,0.815362703 C35.3879258,0.815362703 34.9298365,1.30862747 33.0353111,2.57811824 C35.6703059,3.73059649 45.4272614,7.16970562 48.1569327,7.9404 C43.8145304,5.00479909 41.1230619,3.21737183 40.0825271,2.57811824 Z" id="Fill-5"></path>
|
||||
<path d="M29.6177773,4.85830684 L26.6147653,6.81885893 C29.4750473,8.76729329 32.2115554,10.2845904 34.8242897,11.3707502 C40.1341913,13.5781702 46.8841749,14.9995752 48.423617,15.3807663 C57.1621923,17.5447908 65.4157347,19.5875337 72.0525009,26.2540122 C72.3898283,26.5917965 72.7061975,26.9365971 73.0195726,27.2824 C73.7002154,25.9763676 73.358896,24.2523647 71.9976104,23.3643028 L58.8667933,14.7893932 C55.6791495,13.7329403 52.4316251,12.9250645 49.222025,12.1312213 C46.1950608,11.3814806 41.0779702,10.0491921 38.2156776,9.13005801 C36.3074826,8.51730196 33.4415158,7.0933849 29.6177773,4.85830684 Z" id="Fill-7"></path>
|
||||
<path d="M29.7315665,14.094497 C27.5581473,13.0954401 25.1789914,11.566935 22.5940987,9.50898164 L19.7614089,11.4291886 C22.680354,13.872933 25.1682837,15.5953444 27.225198,16.5964226 C30.3105695,18.09804 42.0831903,21.3149916 42.8121204,21.4949169 C51.5552876,23.6520212 59.5365954,25.256157 66.1778478,31.9045231 C66.1888316,31.9163913 68.9772132,30.2313417 68.797477,30.052416 C61.5001876,22.7464498 52.4120302,20.425361 43.6109479,18.253263 C42.6064223,18.005366 32.9916953,15.5930823 29.7315665,14.094497 Z" id="Fill-11"></path>
|
||||
<path d="M40.2748943,27.6858128 C47.2416777,29.4577639 53.792549,31.5762923 59.3417736,36.4444 L62.2704462,34.569277 C55.9296207,28.6976319 48.8074918,25.8624309 40.7862587,24.3617515 C33.595662,23.0164746 28.8766311,21.3487752 23.507058,19.2459776 C19.9273426,17.8441125 17.1081118,16.3021039 15.0493654,14.6199518 L12.1044223,16.5060931 C15.496129,19.1544049 18.552383,21.0412683 21.2731845,22.1666833 C24.8656838,23.6526619 31.1995871,25.4923718 40.2748943,27.6858128 Z" id="Fill-17"></path>
|
||||
<path d="M5.18885131,21.1343855 C5.29067424,21.2373258 5.38333311,21.3442637 5.48821073,21.4462046 C12.9304487,28.7509644 21.8300234,30.8575975 30.8057147,33.0293369 C38.5788773,34.9092456 45.6427477,36.4683588 51.8987485,41.3005539 L54.8844037,39.3547126 C47.8362204,33.5300936 39.7691873,31.7600736 31.6202982,29.7892176 C22.7942865,27.6534573 14.8355558,25.7666967 8.09895067,19.2774634 L5.18885131,21.1343855 Z" id="Fill-19"></path>
|
||||
<path d="M1.86538962,23.4720365 C0.558922248,24.8286618 0.712329392,27.1676708 2.35067758,28.271683 L12.2679982,34.9570906 C16.6576484,36.8407725 20.0248373,37.7569569 24.5388174,38.9108681 C31.5855194,40.7113852 38.2525371,42.1959537 44.0850166,46.38226 L46.9264812,44.4396723 C40.2948809,39.2709822 32.8228032,37.452366 25.3399436,35.5395764 C16.5616459,33.2962069 9.49263239,31.439221 2.82393361,24.5251104 C2.49004747,24.178937 2.17621456,23.8265263 1.86538962,23.4720365 Z" id="Fill-21"></path>
|
||||
<path d="M34.1645854,49.6645268 C34.893506,50.0634031 35.1425612,50.5086988 36.1796702,50.7 C36.9305233,50.7 37.7585832,50.659873 38.4352738,50.23418 L40.0920678,49.1926318 C34.7693674,45.7494414 29.2447004,43.7586502 23.3471124,42.3058883 L34.1645854,49.6645268 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
<g id="Group-Copy-2" transform="translate(17.363303, 53.000000)">
|
||||
<path d="M40.0825271,2.57811824 C39.3101975,2.18406772 37.9113821,0.772333321 36.5592679,0.815362703 C35.3879258,0.815362703 34.9298365,1.30862747 33.0353111,2.57811824 C35.6703059,3.73059649 45.4272614,7.16970562 48.1569327,7.9404 C43.8145304,5.00479909 41.1230619,3.21737183 40.0825271,2.57811824 Z" id="Fill-5"></path>
|
||||
<path d="M29.6177773,4.85830684 L26.6147653,6.81885893 C29.4750473,8.76729329 32.2115554,10.2845904 34.8242897,11.3707502 C40.1341913,13.5781702 46.8841749,14.9995752 48.423617,15.3807663 C57.1621923,17.5447908 65.4157347,19.5875337 72.0525009,26.2540122 C72.3898283,26.5917965 72.7061975,26.9365971 73.0195726,27.2824 C73.7002154,25.9763676 73.358896,24.2523647 71.9976104,23.3643028 L58.8667933,14.7893932 C55.6791495,13.7329403 52.4316251,12.9250645 49.222025,12.1312213 C46.1950608,11.3814806 41.0779702,10.0491921 38.2156776,9.13005801 C36.3074826,8.51730196 33.4415158,7.0933849 29.6177773,4.85830684 Z" id="Fill-7"></path>
|
||||
<path d="M29.7315665,14.094497 C27.5581473,13.0954401 25.1789914,11.566935 22.5940987,9.50898164 L19.7614089,11.4291886 C22.680354,13.872933 25.1682837,15.5953444 27.225198,16.5964226 C30.3105695,18.09804 42.0831903,21.3149916 42.8121204,21.4949169 C51.5552876,23.6520212 59.5365954,25.256157 66.1778478,31.9045231 C66.1888316,31.9163913 68.9772132,30.2313417 68.797477,30.052416 C61.5001876,22.7464498 52.4120302,20.425361 43.6109479,18.253263 C42.6064223,18.005366 32.9916953,15.5930823 29.7315665,14.094497 Z" id="Fill-11"></path>
|
||||
<path d="M40.2748943,27.6858128 C47.2416777,29.4577639 53.792549,31.5762923 59.3417736,36.4444 L62.2704462,34.569277 C55.9296207,28.6976319 48.8074918,25.8624309 40.7862587,24.3617515 C33.595662,23.0164746 28.8766311,21.3487752 23.507058,19.2459776 C19.9273426,17.8441125 17.1081118,16.3021039 15.0493654,14.6199518 L12.1044223,16.5060931 C15.496129,19.1544049 18.552383,21.0412683 21.2731845,22.1666833 C24.8656838,23.6526619 31.1995871,25.4923718 40.2748943,27.6858128 Z" id="Fill-17"></path>
|
||||
<path d="M5.18885131,21.1343855 C5.29067424,21.2373258 5.38333311,21.3442637 5.48821073,21.4462046 C12.9304487,28.7509644 21.8300234,30.8575975 30.8057147,33.0293369 C38.5788773,34.9092456 45.6427477,36.4683588 51.8987485,41.3005539 L54.8844037,39.3547126 C47.8362204,33.5300936 39.7691873,31.7600736 31.6202982,29.7892176 C22.7942865,27.6534573 14.8355558,25.7666967 8.09895067,19.2774634 L5.18885131,21.1343855 Z" id="Fill-19"></path>
|
||||
<path d="M1.86538962,23.4720365 C0.558922248,24.8286618 0.712329392,27.1676708 2.35067758,28.271683 L12.2679982,34.9570906 C16.6576484,36.8407725 20.0248373,37.7569569 24.5388174,38.9108681 C31.5855194,40.7113852 38.2525371,42.1959537 44.0850166,46.38226 L46.9264812,44.4396723 C40.2948809,39.2709822 32.8228032,37.452366 25.3399436,35.5395764 C16.5616459,33.2962069 9.49263239,31.439221 2.82393361,24.5251104 C2.49004747,24.178937 2.17621456,23.8265263 1.86538962,23.4720365 Z" id="Fill-21"></path>
|
||||
<path d="M34.1645854,49.6645268 C34.893506,50.0634031 35.1425612,50.5086988 36.1796702,50.7 C36.9305233,50.7 37.7585832,50.659873 38.4352738,50.23418 L40.0920678,49.1926318 C34.7693674,45.7494414 29.2447004,43.7586502 23.3471124,42.3058883 L34.1645854,49.6645268 Z" id="Fill-23"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |