Merge branch 'main' into patch-1
BIN
docs/_files/commit-status-flow.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
docs/_files/commit-status-github-failure.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
docs/_files/commit-status-github-overview.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
docs/_files/commit-status-github-success.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
docs/_files/commit-status-gitlab-failure.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
docs/_files/commit-status-gitlab-success.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -9,7 +9,6 @@ The bootstrap sub-commands bootstrap the toolkit components on the targeted Git
|
||||
### Options
|
||||
|
||||
```
|
||||
--arch arch cluster architecture, available options are: (amd64, arm, arm64) (default amd64)
|
||||
--branch string default branch (for GitHub this must match the default branch setting for the organization) (default "main")
|
||||
--cluster-domain string internal cluster domain (default "cluster.local")
|
||||
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller,helm-controller,notification-controller])
|
||||
|
||||
@@ -30,7 +30,7 @@ flux bootstrap github [flags]
|
||||
flux bootstrap github --owner=<organization> --repository=<repo name> --path=dev-cluster
|
||||
|
||||
# Run bootstrap for a public repository on a personal account
|
||||
flux bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true
|
||||
flux bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true
|
||||
|
||||
# Run bootstrap for a private repo hosted on GitHub Enterprise using SSH auth
|
||||
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --ssh-hostname=<domain>
|
||||
@@ -61,7 +61,6 @@ flux bootstrap github [flags]
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--arch arch cluster architecture, available options are: (amd64, arm, arm64) (default amd64)
|
||||
--branch string default branch (for GitHub this must match the default branch setting for the organization) (default "main")
|
||||
--cluster-domain string internal cluster domain (default "cluster.local")
|
||||
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller,helm-controller,notification-controller])
|
||||
|
||||
@@ -20,7 +20,7 @@ flux bootstrap gitlab [flags]
|
||||
# Create a GitLab API token and export it as an env var
|
||||
export GITLAB_TOKEN=<my-token>
|
||||
|
||||
# Run bootstrap for a private repo using HTTPS token authentication
|
||||
# Run bootstrap for a private repo using HTTPS token authentication
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repo name> --token-auth
|
||||
|
||||
# Run bootstrap for a private repo using SSH authentication
|
||||
@@ -32,7 +32,7 @@ flux bootstrap gitlab [flags]
|
||||
# Run bootstrap for a public repository on a personal account
|
||||
flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal --token-auth
|
||||
|
||||
# Run bootstrap for a private repo hosted on a GitLab server
|
||||
# Run bootstrap for a private repo hosted on a GitLab server
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain> --token-auth
|
||||
|
||||
# Run bootstrap for a an existing repository with a branch named main
|
||||
@@ -57,7 +57,6 @@ flux bootstrap gitlab [flags]
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--arch arch cluster architecture, available options are: (amd64, arm, arm64) (default amd64)
|
||||
--branch string default branch (for GitHub this must match the default branch setting for the organization) (default "main")
|
||||
--cluster-domain string internal cluster domain (default "cluster.local")
|
||||
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller,helm-controller,notification-controller])
|
||||
|
||||
@@ -18,9 +18,10 @@ flux create image policy <name> [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for policy
|
||||
--image-ref string the name of an image repository object
|
||||
--semver string a semver range to apply to tags; e.g., '1.x'
|
||||
--filter-regex string regular expression pattern used to filter the image tags
|
||||
-h, --help help for policy
|
||||
--image-ref string the name of an image repository object
|
||||
--semver string a semver range to apply to tags; e.g., '1.x'
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
@@ -17,7 +17,7 @@ flux create image update <name> [flags]
|
||||
```
|
||||
--author-email string the email to use for commit author
|
||||
--author-name string the name to use for commit author
|
||||
--branch string the branch to push commits to
|
||||
--branch string the branch to checkout and push commits to
|
||||
--commit-template string a template for commit messages
|
||||
--git-repo-ref string the name of a GitRepository resource with details of the upstream git repository
|
||||
-h, --help help for update
|
||||
|
||||
@@ -29,4 +29,5 @@ The create source sub-commands generate Kubernetes secrets specific to Flux.
|
||||
|
||||
* [flux create](flux_create.md) - Create or update sources and resources
|
||||
* [flux create secret git](flux_create_secret_git.md) - Create or update a Kubernetes secret for Git authentication
|
||||
* [flux create secret helm](flux_create_secret_helm.md) - Create or update a Kubernetes secret for Helm repository authentication
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ flux create secret git [name] [flags]
|
||||
# Create a Git SSH secret on disk and print the deploy key
|
||||
flux create secret git podinfo-auth \
|
||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||
--export > podinfo-auth.yaml
|
||||
--export > podinfo-auth.yaml
|
||||
|
||||
yq read podinfo-auth.yaml 'data."identity.pub"' | base64 --decode
|
||||
|
||||
@@ -40,7 +40,7 @@ flux create secret git [name] [flags]
|
||||
flux create secret git podinfo-auth \
|
||||
--namespace=apps \
|
||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||
--export > podinfo-auth.yaml
|
||||
--export > podinfo-auth.yaml
|
||||
|
||||
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||
--in-place podinfo-auth.yaml
|
||||
|
||||
65
docs/cmd/flux_create_secret_helm.md
Normal file
@@ -0,0 +1,65 @@
|
||||
## flux create secret helm
|
||||
|
||||
Create or update a Kubernetes secret for Helm repository authentication
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
The create secret helm command generates a Kubernetes secret with basic authentication credentials.
|
||||
|
||||
```
|
||||
flux create secret helm [name] [flags]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
# Create a Helm authentication secret on disk and encrypt it with Mozilla SOPS
|
||||
|
||||
flux create secret helm repo-auth \
|
||||
--namespace=my-namespace \
|
||||
--username=my-username \
|
||||
--password=my-password \
|
||||
--export > repo-auth.yaml
|
||||
|
||||
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||
--in-place repo-auth.yaml
|
||||
|
||||
# Create an authentication secret using a custom TLS cert
|
||||
flux create secret helm repo-auth \
|
||||
--username=username \
|
||||
--password=password \
|
||||
--cert-file=./cert.crt \
|
||||
--key-file=./key.crt \
|
||||
--ca-file=./ca.crt
|
||||
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--ca-file string TLS authentication CA file path
|
||||
--cert-file string TLS authentication cert file path
|
||||
-h, --help help for helm
|
||||
--key-file string TLS authentication key file path
|
||||
-p, --password string basic authentication password
|
||||
-u, --username string basic authentication username
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--context string kubernetes context to use
|
||||
--export export in YAML format to stdout
|
||||
--interval duration source sync interval (default 1m0s)
|
||||
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
|
||||
--label strings set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2)
|
||||
-n, --namespace string the namespace scope for this operation (default "flux-system")
|
||||
--timeout duration timeout for this operation (default 5m0s)
|
||||
--verbose print generated objects
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [flux create secret](flux_create_secret.md) - Create or update Kubernetes secrets
|
||||
|
||||
@@ -31,7 +31,6 @@ flux install [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
--arch arch cluster architecture, available options are: (amd64, arm, arm64) (default amd64)
|
||||
--cluster-domain string internal cluster domain (default "cluster.local")
|
||||
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller,helm-controller,notification-controller])
|
||||
--components-extra strings list of components in addition to those supplied or defaulted, accepts comma-separated values
|
||||
|
||||
52
docs/core-concepts/index.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Core Concepts
|
||||
|
||||
!!! note "Work in progress"
|
||||
This document is a work in progress.
|
||||
|
||||
These are some core concepts in Flux.
|
||||
|
||||
## GitOps
|
||||
|
||||
GitOps is a way of managing your infrastructure and applications so that whole system is described declaratively and version controlled (most likely in a Git repository), and having an automated process that ensures that the deployed environment matches the state specified in a repository.
|
||||
|
||||
For more information, take a look at ["What is GitOps?"](https://www.gitops.tech/#what-is-gitops).
|
||||
|
||||
## Sources
|
||||
|
||||
A *Source* defines the origin of a source and the requirements to obtain
|
||||
it (e.g. credentials, version selectors). For example, the latest `1.x` tag
|
||||
available from a Git repository over SSH.
|
||||
|
||||
Sources produce an artifact that is consumed by other Flux elements to perform
|
||||
actions, like applying the contents of the artifact on the cluster. A source
|
||||
may be shared by multiple consumers to deduplicate configuration and/or storage.
|
||||
|
||||
The origin of the source is checked for changes on a defined interval, if
|
||||
there is a newer version available that matches the criteria, a new artifact
|
||||
is produced.
|
||||
|
||||
All sources are specified as Custom Resources in a Kubernetes cluster, examples
|
||||
of sources are `GitRepository`, `HelmRepository` and `Bucket` resources.
|
||||
|
||||
For more information, take a look at [the source controller documentation](../components/source/source.md).
|
||||
|
||||
## Reconciliation
|
||||
|
||||
Reconciliation refers to ensuring that a given state (e.g application running in the cluster, infrastructure) matches a desired state declaratively defined somewhere (e.g a git repository). There are various examples of these in flux e.g:
|
||||
|
||||
- HelmRelease reconciliation: ensures the state of the Helm release matches what is defined in the resource, performs a release if this is not the case (including revision changes of a HelmChart resource).
|
||||
- Bucket reconciliation: downloads and archives the contents of the declared bucket on a given interval and stores this as an artifact, records the observed revision of the artifact and the artifact itself in the status of resource.
|
||||
- [Kustomization](#kustomization) reconciliation: ensures the state of the application deployed on a cluster matches resources contained in a git repository.
|
||||
|
||||
## Kustomization
|
||||
|
||||
The kustomization represents a local set of Kubernetes resources that Flux is supposed to reconcile in the cluster. The reconciliation runs every one minute by default but this can be specified in the kustomization. If you make any changes to the cluster using `kubectl edit` or `kubectl patch`, it will be promptly reverted. You either suspend the reconciliation or push your changes to a Git repository.
|
||||
|
||||
For more information, take a look at [this documentation](../components/kustomize/kustomization.md).
|
||||
|
||||
## Bootstrap
|
||||
|
||||
The process of installing the Flux components in a complete GitOps way is called a bootstrap. The manifests are applied to the cluster, a `GitRepository` and `Kustomization` are created for the Flux components, and the manifests are pushed to an existing Git repository (or a new one is created). Flux can manage itself just as it manages other resources.
|
||||
The bootstrap is done using the `flux` CLI `flux bootstrap`.
|
||||
|
||||
For more information, take a look at [the documentation for the bootstrap command](../cmd/flux_bootstrap.md).
|
||||
@@ -17,7 +17,7 @@ On your dev machine install the following tools:
|
||||
* kustomize >= 3.5
|
||||
* docker >= 19.03
|
||||
|
||||
## Install the GitOps Toolkit
|
||||
## Install Flux
|
||||
|
||||
Create a cluster for testing:
|
||||
|
||||
@@ -25,7 +25,7 @@ Create a cluster for testing:
|
||||
kind create cluster --name dev
|
||||
```
|
||||
|
||||
Install the toolkit CLI:
|
||||
Install the Flux CLI:
|
||||
|
||||
```sh
|
||||
curl -s https://toolkit.fluxcd.io/install.sh | sudo bash
|
||||
@@ -37,7 +37,7 @@ Verify that your dev machine satisfies the prerequisites with:
|
||||
flux check --pre
|
||||
```
|
||||
|
||||
Install the toolkit controllers on the dev cluster:
|
||||
Install source-controller on the dev cluster:
|
||||
|
||||
```sh
|
||||
flux install
|
||||
@@ -45,13 +45,13 @@ flux install
|
||||
|
||||
## Clone the sample controller
|
||||
|
||||
You'll be using [stefanprodan/source-watcher](https://github.com/stefanprodan/source-watcher) as
|
||||
You'll be using [fluxcd/source-watcher](https://github.com/fluxcd/source-watcher) as
|
||||
a template for developing your own controller. The source-watcher was scaffolded with `kubebuilder init`.
|
||||
|
||||
Clone the source-watcher repo:
|
||||
Clone the source-watcher repository:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/stefanprodan/source-watcher
|
||||
git clone https://github.com/fluxcd/source-watcher
|
||||
cd source-watcher
|
||||
```
|
||||
|
||||
@@ -115,7 +115,7 @@ The source-controller reports the revision under `GitRepository.Status.Artifact.
|
||||
|
||||
## How it works
|
||||
|
||||
The [GitRepositoryWatcher](https://github.com/stefanprodan/source-watcher/blob/master/controllers/gitrepository_watcher.go)
|
||||
The [GitRepositoryWatcher](https://github.com/fluxcd/source-watcher/blob/main/controllers/gitrepository_watcher.go)
|
||||
controller does the following:
|
||||
|
||||
* subscribes to `GitRepository` events
|
||||
@@ -186,8 +186,8 @@ func (r *GitRepositoryWatcher) SetupWithManager(mgr ctrl.Manager) error {
|
||||
|
||||
To add the watcher to an existing project, copy the controller and the revision change predicate to your `controllers` dir:
|
||||
|
||||
* [gitrepository_watcher.go](https://github.com/stefanprodan/source-watcher/blob/master/controllers/gitrepository_watcher.go)
|
||||
* [gitrepository_predicate.go](https://github.com/stefanprodan/source-watcher/blob/master/controllers/gitrepository_predicate.go)
|
||||
* [gitrepository_watcher.go](https://github.com/fluxcd/source-watcher/blob/main/controllers/gitrepository_watcher.go)
|
||||
* [gitrepository_predicate.go](https://github.com/fluxcd/source-watcher/blob/main/controllers/gitrepository_predicate.go)
|
||||
|
||||
In your `main.go` init function, register the Source API schema:
|
||||
|
||||
@@ -224,9 +224,9 @@ Your `go.mod` should require controller-runtime v0.6 or newer:
|
||||
|
||||
```go
|
||||
require (
|
||||
k8s.io/apimachinery v0.18.4
|
||||
k8s.io/client-go v0.18.4
|
||||
sigs.k8s.io/controller-runtime v0.6.0
|
||||
k8s.io/apimachinery v0.19.4
|
||||
k8s.io/client-go v0.19.4
|
||||
sigs.k8s.io/controller-runtime v0.6.4
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
# Get started with Flux v2
|
||||
|
||||
!!! note "Basic knowledge"
|
||||
This guide assumes you have some understanding of the core concepts and have read the introduction to Flux.
|
||||
The core concepts used in this guide are [GitOps](../core-concepts/index.md#gitops),
|
||||
[Sources](../core-concepts/index.md#sources), [Kustomization](../core-concepts/index.md#kustomization).
|
||||
|
||||
In this tutorial, you will deploy an application to a kubernetes cluster with Flux
|
||||
and manage the cluster in a complete GitOps manner.
|
||||
You'll be using a dedicated Git repository e.g. `fleet-infra` to manage your Kubernetes clusters.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You will need two Kubernetes clusters version 1.16 or newer and kubectl version 1.18.
|
||||
In order to follow the guide, you will need a Kubernetes cluster version 1.16 or newer and kubectl version 1.18.
|
||||
For a quick local test, you can use [Kubernetes kind](https://kind.sigs.k8s.io/docs/user/quick-start/).
|
||||
Any other Kubernetes setup will work as well though.
|
||||
|
||||
In order to follow the guide you'll need a GitHub account and a
|
||||
Flux is installed in a GitOps way and its manifest will be pushed to the repository,
|
||||
so you will also need a GitHub account and a
|
||||
[personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)
|
||||
that can create repositories (check all permissions under `repo`).
|
||||
that can create repositories (check all permissions under `repo`) to enable Flux do this.
|
||||
|
||||
Export your GitHub personal access token and username:
|
||||
|
||||
@@ -51,24 +61,13 @@ To configure your shell to load `flux` [bash completions](../cmd/flux_completion
|
||||
|
||||
[`zsh`](../cmd/flux_completion_zsh.md), [`fish`](../cmd/flux_completion_fish.md), and [`powershell`](../cmd/flux_completion_powershell.md) are also supported with their own sub-commands.
|
||||
|
||||
## GitOps workflow
|
||||
## Install Flux components
|
||||
|
||||
You'll be using a dedicated Git repository e.g. `fleet-infra` to manage one or more Kubernetes clusters.
|
||||
This guide assumes that you have two clusters, one for staging and one for production.
|
||||
|
||||
Using the Flux CLI you'll do the following:
|
||||
|
||||
- configure each cluster to synchronise with a directory inside the fleet repository
|
||||
- register app sources (git repositories) that contain plain Kubernetes manifests or Kustomize overlays
|
||||
- configure app deployments on both clusters (pre-releases on staging, semver releases on production)
|
||||
|
||||
## Staging bootstrap
|
||||
|
||||
Create the staging cluster using Kubernetes kind or set the kubectl context to an existing cluster:
|
||||
Create the cluster using Kubernetes kind or set the kubectl context to an existing cluster:
|
||||
|
||||
```sh
|
||||
kind create cluster --name staging
|
||||
kubectl cluster-info --context kind-staging
|
||||
kind create cluster
|
||||
kubectl cluster-info
|
||||
```
|
||||
|
||||
Verify that your staging cluster satisfies the prerequisites with:
|
||||
@@ -88,17 +87,18 @@ flux bootstrap github \
|
||||
--owner=$GITHUB_USER \
|
||||
--repository=fleet-infra \
|
||||
--branch=main \
|
||||
--path=staging-cluster \
|
||||
--path=./clusters/my-cluster \
|
||||
--personal
|
||||
```
|
||||
|
||||
!!! hint "ARM"
|
||||
When deploying to a Kubernetes cluster with ARM architecture,
|
||||
you can use `--arch=arm` for ARMv7 32-bit container images
|
||||
and `--arch=arm64` for ARMv8 64-bit container images.
|
||||
!!! hint "Multi-arch images"
|
||||
The component images are published as [multi-arch container images](https://docs.docker.com/docker-for-mac/multi-arch/)
|
||||
with support for Linux `amd64`, `arm64` and `armv7` (e.g. 32bit Raspberry Pi)
|
||||
architectures.
|
||||
|
||||
The bootstrap command creates a repository if one doesn't exist, and
|
||||
commits the manifests for the Flux components to the default branch at the specified path.
|
||||
The bootstrap command creates a repository if one doesn't exist,
|
||||
commits the manifests for the Flux components to the default branch at the specified path,
|
||||
and installs the Flux components.
|
||||
Then it configures the target cluster to synchronize with the specified path inside the repository.
|
||||
|
||||
If you wish to create the repository under a GitHub organization:
|
||||
@@ -110,13 +110,13 @@ flux bootstrap github \
|
||||
--branch=<organization default branch> \
|
||||
--team=<team1-slug> \
|
||||
--team=<team2-slug> \
|
||||
--path=staging-cluster
|
||||
--path=./clusters/my-cluster
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```console
|
||||
$ flux bootstrap github --owner=gitopsrun --repository=fleet-infra --path=staging-cluster --team=devs
|
||||
$ flux bootstrap github --owner=gitopsrun --team=devs --repository=fleet-infra --path=./clusters/my-cluster
|
||||
► connecting to github.com
|
||||
✔ repository created
|
||||
✔ devs team access granted
|
||||
@@ -138,7 +138,8 @@ deployment "notification-controller" successfully rolled out
|
||||
✔ bootstrap finished
|
||||
```
|
||||
|
||||
If you prefer GitLab, export `GITLAB_TOKEN` env var and use the command [flux bootstrap gitlab](../cmd/flux_bootstrap_gitlab.md).
|
||||
If you prefer GitLab, export `GITLAB_TOKEN` env var and
|
||||
use the command [flux bootstrap gitlab](../guides/installation.md#gitlab-and-gitlab-enterprise).
|
||||
|
||||
!!! hint "Idempotency"
|
||||
It is safe to run the bootstrap command as many times as you want.
|
||||
@@ -147,225 +148,152 @@ If you prefer GitLab, export `GITLAB_TOKEN` env var and use the command [flux bo
|
||||
You can target a specific Flux [version](https://github.com/fluxcd/flux2/releases)
|
||||
with `flux bootstrap --version=<semver>`.
|
||||
|
||||
## Staging workflow
|
||||
## Clone the git repository
|
||||
|
||||
Clone the repository with:
|
||||
We are going to drive app deployments in a GitOps manner,
|
||||
using the Git repository as the desired state for our cluster.
|
||||
Instead of applying the manifests directly to the cluster,
|
||||
Flux will apply it for us instead.
|
||||
|
||||
Therefore, we need to clone the repository to our local machine:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/$GITHUB_USER/fleet-infra
|
||||
cd fleet-infra
|
||||
```
|
||||
|
||||
Create a git source pointing to a public repository master branch:
|
||||
## Add podinfo repository to Flux
|
||||
|
||||
We will be using a public repository [github.com/stefanprodan/podinfo](https://github.com/stefanprodan/podinfo),
|
||||
podinfo is a tiny web application made with Go.
|
||||
|
||||
Create a [GitRepository](../components/source/gitrepositories/)
|
||||
manifest pointing to podinfo repository's master branch:
|
||||
|
||||
```sh
|
||||
flux create source git webapp \
|
||||
flux create source git podinfo \
|
||||
--url=https://github.com/stefanprodan/podinfo \
|
||||
--branch=master \
|
||||
--interval=30s \
|
||||
--export > ./staging-cluster/webapp-source.yaml
|
||||
--export > ./clusters/my-cluster/podinfo-source.yaml
|
||||
```
|
||||
|
||||
Create a kustomization for synchronizing the common manifests on the cluster:
|
||||
The above command generates the following manifest:
|
||||
|
||||
```yaml
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 30s
|
||||
ref:
|
||||
branch: master
|
||||
url: https://github.com/stefanprodan/podinfo
|
||||
```
|
||||
|
||||
Commit and push it to the `fleet-infra` repository:
|
||||
|
||||
```sh
|
||||
flux create kustomization webapp-common \
|
||||
--source=webapp \
|
||||
--path="./deploy/webapp/common" \
|
||||
git add -A && git commit -m "Add podinfo GitRepository"
|
||||
git push
|
||||
```
|
||||
|
||||
## Deploy podinfo application
|
||||
|
||||
We will create a Flux [Kustomization](../components/kustomize/kustomization/) manifest for podinfo.
|
||||
This configures Flux to build and apply the [kustomize](https://github.com/stefanprodan/podinfo/tree/master/kustomize)
|
||||
directory located in the podinfo repository.
|
||||
|
||||
```sh
|
||||
flux create kustomization podinfo \
|
||||
--source=podinfo \
|
||||
--path="./kustomize" \
|
||||
--prune=true \
|
||||
--validation=client \
|
||||
--interval=1h \
|
||||
--export > ./staging-cluster/webapp-common.yaml
|
||||
--interval=5m \
|
||||
--export > ./clusters/my-cluster/podinfo-kustomization.yaml
|
||||
```
|
||||
|
||||
Create a kustomization for the backend service that depends on common:
|
||||
The above command generates the following manifest:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./kustomize
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: podinfo
|
||||
validation: client
|
||||
```
|
||||
|
||||
Commit and push the `Kustomization` manifest to the repository:
|
||||
|
||||
```sh
|
||||
flux create kustomization webapp-backend \
|
||||
--depends-on=webapp-common \
|
||||
--source=webapp \
|
||||
--path="./deploy/webapp/backend" \
|
||||
--prune=true \
|
||||
--validation=client \
|
||||
--interval=10m \
|
||||
--health-check="Deployment/backend.webapp" \
|
||||
--health-check-timeout=2m \
|
||||
--export > ./staging-cluster/webapp-backend.yaml
|
||||
git add -A && git commit -m "Add podinfo Kustomization"
|
||||
git push
|
||||
```
|
||||
|
||||
Create a kustomization for the frontend service that depends on backend:
|
||||
The structure of your repository should look like this:
|
||||
|
||||
```sh
|
||||
flux create kustomization webapp-frontend \
|
||||
--depends-on=webapp-backend \
|
||||
--source=webapp \
|
||||
--path="./deploy/webapp/frontend" \
|
||||
--prune=true \
|
||||
--validation=client \
|
||||
--interval=10m \
|
||||
--health-check="Deployment/frontend.webapp" \
|
||||
--health-check-timeout=2m \
|
||||
--export > ./staging-cluster/webapp-frontend.yaml
|
||||
```
|
||||
fleet-infra
|
||||
└── clusters/
|
||||
└── my-cluster/
|
||||
├── flux-system/
|
||||
│ ├── gotk-components.yaml
|
||||
│ ├── gotk-sync.yaml
|
||||
│ └── kustomization.yaml
|
||||
├── podinfo-kustomization.yaml
|
||||
└── podinfo-source.yaml
|
||||
```
|
||||
|
||||
Push changes to origin:
|
||||
|
||||
```sh
|
||||
git add -A && git commit -m "add staging webapp" && git push
|
||||
```
|
||||
## Watch Flux sync the application
|
||||
|
||||
In about 30s the synchronization should start:
|
||||
|
||||
```console
|
||||
$ watch flux get kustomizations
|
||||
NAME READY MESSAGE
|
||||
flux-system True Applied revision: main/6eea299fe9997c8561b826b67950afaf9a476cf8
|
||||
webapp-backend False dependency 'flux-system/webapp-common' is not ready
|
||||
webapp-common True Applied revision: master/7411da595c25183daba255068814b83843fe3395
|
||||
webapp-frontend False dependency 'flux-system/webapp-backend' is not ready
|
||||
flux-system True Applied revision: main/fc07af652d3168be329539b30a4c3943a7d12dd8
|
||||
podinfo True Applied revision: master/855f7724be13f6146f61a893851522837ad5b634
|
||||
```
|
||||
|
||||
When the synchronization finishes you can check that the webapp services are running:
|
||||
When the synchronization finishes you can check that podinfo has been deployed on your cluster:
|
||||
|
||||
```console
|
||||
$ kubectl -n webapp get deployments,services
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/backend 1/1 1 1 4m1s
|
||||
deployment.apps/frontend 1/1 1 1 3m31s
|
||||
$ kubectl -n default get deployments,services
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/podinfo 2/2 2 2 108s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/backend ClusterIP 10.52.10.22 <none> 9898/TCP,9999/TCP 4m1s
|
||||
service/frontend ClusterIP 10.52.9.85 <none> 80/TCP 3m31s
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/podinfo ClusterIP 10.100.149.126 <none> 9898/TCP,9999/TCP 108s
|
||||
```
|
||||
|
||||
!!! tip
|
||||
From this moment forward, any changes made to the webapp
|
||||
Kubernetes manifests in the master branch will be synchronised with the staging cluster.
|
||||
From this moment forward, any changes made to the podinfo
|
||||
Kubernetes manifests in the master branch will be synchronised with your cluster.
|
||||
|
||||
If a Kubernetes manifest is removed from the webapp repository, the reconciler will remove it from your cluster.
|
||||
If you delete a kustomization from the `fleet-infra` repo, the reconciler will remove all Kubernetes objects that
|
||||
were previously applied from that kustomization.
|
||||
If a Kubernetes manifest is removed from the podinfo repository, Flux will remove it from your cluster.
|
||||
If you delete a `Kustomization` from the fleet-infra repository, Flux will remove all Kubernetes objects that
|
||||
were previously applied from that `Kustomization`.
|
||||
|
||||
If you alter the webapp deployment using `kubectl edit`, the changes will be reverted to match
|
||||
the state described in git. When dealing with an incident, you can pause the reconciliation of a
|
||||
If you alter the podinfo deployment using `kubectl edit`, the changes will be reverted to match
|
||||
the state described in Git. When dealing with an incident, you can pause the reconciliation of a
|
||||
kustomization with `flux suspend kustomization <name>`. Once the debugging session
|
||||
is over, you can re-enable the reconciliation with `flux resume kustomization <name>`.
|
||||
|
||||
## Production bootstrap
|
||||
## Multi-cluster Setup
|
||||
|
||||
On production clusters, you may wish to deploy stable releases of an application.
|
||||
When creating a git source instead of a branch, you can specify a git tag or a semver expression.
|
||||
To use Flux to manage more than one cluster or promote deployments from staging to production, take a look at the
|
||||
two approaches in the repositories listed below.
|
||||
|
||||
Create the production cluster using Kubernetes kind or set the kubectl context to an existing cluster:
|
||||
|
||||
```sh
|
||||
kind create cluster --name production
|
||||
kubectl cluster-info --context kind-production
|
||||
```
|
||||
|
||||
Run the bootstrap for the production environment:
|
||||
|
||||
```sh
|
||||
flux bootstrap github \
|
||||
--owner=$GITHUB_USER \
|
||||
--repository=fleet-infra \
|
||||
--path=prod-cluster \
|
||||
--personal
|
||||
```
|
||||
Pull the changes locally:
|
||||
|
||||
```sh
|
||||
git pull
|
||||
```
|
||||
|
||||
## Production workflow
|
||||
|
||||
Create a git source using a semver range to target stable releases:
|
||||
|
||||
```sh
|
||||
flux create source git webapp \
|
||||
--url=https://github.com/stefanprodan/podinfo \
|
||||
--tag-semver=">=4.0.0 <4.0.2" \
|
||||
--interval=30s \
|
||||
--export > ./prod-cluster/webapp-source.yaml
|
||||
```
|
||||
|
||||
Create a kustomization for webapp pointing to the production overlay:
|
||||
|
||||
```sh
|
||||
flux create kustomization webapp \
|
||||
--source=webapp \
|
||||
--path="./deploy/overlays/production" \
|
||||
--prune=true \
|
||||
--validation=client \
|
||||
--interval=10m \
|
||||
--health-check="Deployment/frontend.production" \
|
||||
--health-check="Deployment/backend.production" \
|
||||
--health-check-timeout=2m \
|
||||
--export > ./prod-cluster/webapp-production.yaml
|
||||
```
|
||||
|
||||
Push changes to origin:
|
||||
|
||||
```sh
|
||||
git add -A && git commit -m "add prod webapp" && git push
|
||||
```
|
||||
|
||||
List git sources:
|
||||
|
||||
```console
|
||||
$ flux get sources git
|
||||
NAME REVISION READY MESSAGE
|
||||
flux-system main/5ae055e24b2c8a78f981708b61507a97a30bd7a6 True Fetched revision: main/113360052b3153e439a0cf8de76b8e3d2a7bdf27
|
||||
webapp 4.0.1/113360052b3153e439a0cf8de76b8e3d2a7bdf27 True Fetched revision: 4.0.1/113360052b3153e439a0cf8de76b8e3d2a7bdf27
|
||||
```
|
||||
|
||||
The kubectl equivalent is `kubectl -n flux-system get gitrepositories`.
|
||||
|
||||
List kustomization:
|
||||
|
||||
```console
|
||||
$ flux get kustomizations
|
||||
NAME REVISION SUSPENDED READY MESSAGE
|
||||
flux-system main/5ae055e24b2c8a78f981708b61507a97a30bd7a6 False True Applied revision: main/5ae055e24b2c8a78f981708b61507a97a30bd7a6
|
||||
webapp 4.0.1/113360052b3153e439a0cf8de76b8e3d2a7bdf27 False True Applied revision: 4.0.1/113360052b3153e439a0cf8de76b8e3d2a7bdf27
|
||||
```
|
||||
|
||||
The kubectl equivalent is `kubectl -n flux-system get kustomizations`.
|
||||
|
||||
If you want to upgrade to the latest 4.x version, you can change the semver expression to:
|
||||
|
||||
```sh
|
||||
flux create source git webapp \
|
||||
--url=https://github.com/stefanprodan/podinfo \
|
||||
--tag-semver=">=4.0.0 <5.0.0" \
|
||||
--interval=30s \
|
||||
--export > ./prod-cluster/webapp-source.yaml
|
||||
|
||||
git add -A && git commit -m "update prod webapp" && git push
|
||||
```
|
||||
|
||||
Trigger a git sync:
|
||||
|
||||
```console
|
||||
$ flux reconcile ks flux-system --with-source
|
||||
► annotating source flux-system
|
||||
✔ source annotated
|
||||
◎ waiting for reconcilitation
|
||||
✔ git reconciliation completed
|
||||
✔ fetched revision main/d751ea264d48bf0db8b588d1d08184834ac8fec9
|
||||
◎ waiting for kustomization reconcilitation
|
||||
✔ kustomization reconcilitation completed
|
||||
✔ applied revision main/d751ea264d48bf0db8b588d1d08184834ac8fec9
|
||||
```
|
||||
|
||||
The kubectl equivalent is `kubectl -n flux-system annotate gitrepository/flux-system fluxcd.io/reconcileAt="$(date +%s)"`.
|
||||
|
||||
Wait for the webapp to be upgraded:
|
||||
|
||||
```console
|
||||
$ watch flux get kustomizations
|
||||
NAME REVISION SUSPENDED READY MESSAGE
|
||||
flux-system main/d751ea264d48bf0db8b588d1d08184834ac8fec9 False True Applied revision: main/d751ea264d48bf0db8b588d1d08184834ac8fec9
|
||||
webapp 4.0.6/26a630c0b4b3452833d96c511d93f6f2d2e90a99 False True Applied revision: 4.0.6/26a630c0b4b3452833d96c511d93f6f2d2e90a99
|
||||
```
|
||||
1. [https://github.com/fluxcd/flux2-kustomize-helm-example](https://github.com/fluxcd/flux2-kustomize-helm-example)
|
||||
2. [https://github.com/fluxcd/flux2-multi-tenancy](https://github.com/fluxcd/flux2-multi-tenancy)
|
||||
@@ -21,12 +21,6 @@ To be able to release a Helm chart, the source that contains the chart
|
||||
first to the source-controller, so that the `HelmRelease` can reference
|
||||
to it.
|
||||
|
||||
A cluster administrator should register trusted sources by creating
|
||||
the resources in the `flux-system` namespace. By default, the
|
||||
source-controller watches for sources only in the `flux-system`
|
||||
namespace, this way cluster admins can prevent untrusted sources from
|
||||
being registered by users.
|
||||
|
||||
### Helm repository
|
||||
|
||||
Helm repositories are the recommended source to retrieve Helm charts
|
||||
@@ -117,52 +111,79 @@ repository and omits all other files.
|
||||
HTTP/S basic and SSH authentication can be configured for private
|
||||
Git repositories. See the [`GitRepository` CRD docs](../components/source/gitrepositories.md)
|
||||
for more details.
|
||||
|
||||
### Bucket
|
||||
|
||||
Charts from S3 compatible storage buckets can be released by declaring
|
||||
a `Bucket`, the source-controller will fetch the contents of the bucket
|
||||
on an interval and expose it as an artifact.
|
||||
### Cloud Storage
|
||||
|
||||
**There is one caveat you should be aware of:** to make the
|
||||
source-controller produce a new chart artifact, the `version` in the
|
||||
`Chart.yaml` of the chart must be bumped.
|
||||
It is inadvisable while still possible to use a `Bucket` as a source for a `HelmRelease`,
|
||||
as the whole storage bucket will be downloaded by source controller at each sync. The
|
||||
bucket can easily become very large if there are frequent releases of multiple charts
|
||||
that are stored in the same bucket.
|
||||
|
||||
An example `Bucket`:
|
||||
A better option is to use [Chartmuseum](https://github.com/helm/chartmuseum) and run a cluster
|
||||
local Helm repository that can be used by source controller. Chartmuseum has support
|
||||
for multiple different cloud storage solutions such as S3, GCS, and Azure Blob Storage,
|
||||
meaning that you are not limited to only using storage providers that support the S3 protocol.
|
||||
|
||||
You can deploy a Chartmuseum instance with a `HelmRelease` that exposes a Helm repository stored
|
||||
in a S3 bucket. Please refer to [Chartmuseums how to run documentation](https://chartmuseum.com/docs/#how-to-run)
|
||||
for details about how to use other storage backends.
|
||||
|
||||
```yaml
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||
kind: Bucket
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: gotk-system
|
||||
name: chartmuseum
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1m
|
||||
provider: generic
|
||||
bucketName: podinfo
|
||||
endpoint: minio.minio.svc.cluster.local:9000
|
||||
ignore: |
|
||||
# exclude all
|
||||
/*
|
||||
# include charts directory
|
||||
!/charts/
|
||||
url: https://chartmuseum.github.io/charts
|
||||
interval: 10m
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: chartmuseum
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 5m
|
||||
chart:
|
||||
spec:
|
||||
chart: chartmuseum
|
||||
version: "2.14.2"
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: chartmuseum
|
||||
namespace: flux-system
|
||||
interval: 1m
|
||||
values:
|
||||
env:
|
||||
open:
|
||||
AWS_SDK_LOAD_CONFIG: true
|
||||
STORAGE: amazon
|
||||
STORAGE_AMAZON_BUCKET: "bucket-name"
|
||||
STORAGE_AMAZON_PREFIX: ""
|
||||
STORAGE_AMAZON_REGION: "region-name"
|
||||
serviceAccount:
|
||||
create: true
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: "role-arn"
|
||||
securityContext:
|
||||
enabled: true
|
||||
fsGroup: 65534
|
||||
```
|
||||
|
||||
The `interval` defines at which interval the Git repository contents
|
||||
are fetched, and should be at least `1m`. Setting this to a higher
|
||||
value means newer chart versions will be detected at a slower pace,
|
||||
a push-based fetch can be introduced using [webhook receivers](webhook-receivers.md)
|
||||
After Chartmuseum is up and running it should be possible to use the accompanying
|
||||
service as the url for the `HelmRepository`.
|
||||
|
||||
The `provider`, `bucketName` and `endpoint` together define what
|
||||
S3 compatible storage should be connected to. For more information,
|
||||
see the [`Bucket` CRD docs](../components/source/buckets.md).
|
||||
|
||||
|
||||
The `ignore` defines file and folder exclusion for the
|
||||
artifact produced, and follows the [`.gitignore` pattern
|
||||
format](https://git-scm.com/docs/gitignore#_pattern_format).
|
||||
The above example only includes the `charts` directory of the
|
||||
repository and omits all other files.
|
||||
```yaml
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: helm-charts
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1m
|
||||
url: http://chartmuseum-chartmuseum:8080
|
||||
```
|
||||
|
||||
## Define a Helm release
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ synchronize with the specified path inside the repository.
|
||||
|
||||
## Deploy a demo app
|
||||
|
||||
We'll be using a tiny webapp called [podinfo](https://github.com/stefanprodan/podinfo) to
|
||||
We'll be using a tiny webapp called [podinfo](https://github.com/stefanprodan/podinfo) to
|
||||
showcase the image update feature.
|
||||
|
||||
Clone your repository with:
|
||||
@@ -183,7 +183,7 @@ spec:
|
||||
A semver range that includes stable releases can be defined with
|
||||
`1.0.x` (patch versions only) or `>=1.0.0 <2.0.0` (minor and patch versions).
|
||||
If you want to include pre-release e.g. `1.0.0-rc.1`,
|
||||
you can define a range like: `>1.0.0-rc <2.0.0`.
|
||||
you can define a range like: `^1.x-0` or `>1.0.0-rc <2.0.0-rc`.
|
||||
|
||||
Commit and push changes to main branch:
|
||||
|
||||
@@ -217,7 +217,7 @@ podinfo True Latest image tag for 'ghcr.io/stefanprodan/podinfo' resolved to: 5
|
||||
|
||||
## Configure image updates
|
||||
|
||||
Edit the `podinfo-deploy.yaml` and add a maker to tell Flux which policy to use when updating the container image:
|
||||
Edit the `podinfo-deploy.yaml` and add a marker to tell Flux which policy to use when updating the container image:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
@@ -235,7 +235,7 @@ flux create image update flux-system \
|
||||
--author-name=fluxcdbot \
|
||||
--author-email=fluxcdbot@users.noreply.github.com \
|
||||
--commit-template="[ci skip] update image" \
|
||||
--export ./clusters/my-cluster/flux-system-automation.yaml
|
||||
--export > ./clusters/my-cluster/flux-system-automation.yaml
|
||||
```
|
||||
|
||||
The above command generates the following manifest:
|
||||
@@ -358,3 +358,258 @@ images:
|
||||
newName: ghcr.io/stefanprodan/podinfo
|
||||
newTag: 5.0.0 # {"$imagepolicy": "flux-system:podinfo:tag"}
|
||||
```
|
||||
|
||||
## ImageRepository cloud providers authentication
|
||||
|
||||
If relying on a cloud provider image repository, you might need to do some extra
|
||||
work in order to configure the ImageRepository resource credentials. Here are
|
||||
some common examples for the most popular cloud provider docker registries.
|
||||
|
||||
!!! warning "Workarounds"
|
||||
The examples below are intended as workaround solutions until native
|
||||
authentication mechanisms are implemented in Flux itself to support this in
|
||||
a more straightforward manner.
|
||||
|
||||
### AWS Elastic Container Registry
|
||||
|
||||
The registry authentication credentials for ECR expire every 12 hours.
|
||||
Considering this limitation, one needs to ensure the credentials are being
|
||||
refreshed before expiration so that the controller can rely on them for
|
||||
authentication.
|
||||
|
||||
The solution proposed is to create a cronjob that runs every 6 hours which would
|
||||
re-create the `docker-registry` secret using a new token.
|
||||
|
||||
Edit and save the following snippet to a file
|
||||
`./clusters/my-cluster/ecr-sync.yaml`, commit and push it to git.
|
||||
|
||||
```yaml
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: ecr-credentials-sync
|
||||
namespace: flux-system
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- delete
|
||||
- create
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: ecr-credentials-sync
|
||||
namespace: flux-system
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: ecr-credentials-sync
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: ecr-credentials-sync
|
||||
apiGroup: ""
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: ecr-credentials-sync
|
||||
# Uncomment and edit if using IRSA
|
||||
# annotations:
|
||||
# eks.amazonaws.com/role-arn: <role arn>
|
||||
---
|
||||
apiVersion: batch/v1beta1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: ecr-credentials-sync
|
||||
namespace: flux-system
|
||||
spec:
|
||||
suspend: false
|
||||
schedule: 0 */6 * * *
|
||||
failedJobsHistoryLimit: 1
|
||||
successfulJobsHistoryLimit: 1
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
serviceAccountName: ecr-credentials-sync
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: token
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
initContainers:
|
||||
- image: amazon/aws-cli
|
||||
name: get-token
|
||||
imagePullPolicy: IfNotPresent
|
||||
# You will need to set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables if not using
|
||||
# IRSA. It is recommended to store the values in a Secret and load them in the container using envFrom.
|
||||
# envFrom:
|
||||
# - secretRef:
|
||||
# name: aws-credentials
|
||||
env:
|
||||
- name: REGION
|
||||
value: us-east-1 # change this if ECR repo is in a different region
|
||||
volumeMounts:
|
||||
- mountPath: /token
|
||||
name: token
|
||||
command:
|
||||
- /bin/sh
|
||||
- -ce
|
||||
- aws ecr get-login-password --region ${REGION} > /token/ecr-token
|
||||
containers:
|
||||
- image: bitnami/kubectl
|
||||
name: create-secret
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: SECRET_NAME
|
||||
value: <secret name> # this is the generated Secret name
|
||||
- name:
|
||||
value: <account id>.dkr.ecr.<region>.amazonaws.com # fill in the account id and region
|
||||
volumeMounts:
|
||||
- mountPath: /token
|
||||
name: token
|
||||
command:
|
||||
- /bin/bash
|
||||
- -ce
|
||||
- |-
|
||||
kubectl delete secret --ignore-not-found $SECRET_NAME
|
||||
kubectl create secret docker-registry $SECRET_NAME \
|
||||
--docker-server="$ECR_REGISTRY" \
|
||||
--docker-username=AWS \
|
||||
--docker-password="$(</token/ecr-token)"
|
||||
```
|
||||
|
||||
!!! hint "Using IAM Roles for Service Accounts (IRSA)"
|
||||
If using IRSA, make sure the role attached to the service account has
|
||||
readonly access to ECR. The AWS managed policy
|
||||
`arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly` can be attached
|
||||
to the role.
|
||||
|
||||
Since the cronjob will not create a job right away, after applying the manifest,
|
||||
you can manually create an init job using the following command:
|
||||
|
||||
```console
|
||||
$ kubectl create job --from=cronjob/ecr-credentials-sync -n flux-system ecr-credentials-sync-init
|
||||
```
|
||||
|
||||
### GCP Container Registry
|
||||
|
||||
#### Using access token [short-lived]
|
||||
|
||||
!!!note "Workload Identity"
|
||||
Please ensure that you enable workload identity for your cluster, create a GCP service account that has access to the container registry and create an IAM policy binding between the GCP service account and the Kubernetes service account so that the pods created by the cronjob can access GCP APIs and get the token.
|
||||
Take a look at [this guide](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
|
||||
|
||||
|
||||
The access token for GCR expires hourly.
|
||||
Considering this limitation, one needs to ensure the credentials are being
|
||||
refreshed before expiration so that the controller can rely on them for
|
||||
authentication.
|
||||
|
||||
The solution proposed is to create a cronjob that runs every 45 minutes which would
|
||||
re-create the `docker-registry` secret using a new token.
|
||||
|
||||
Edit and save the following snippet to a file
|
||||
`./clusters/my-cluster/gcr-sync.yaml`, commit and push it to git.
|
||||
|
||||
```yaml
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: gcr-credentials-sync
|
||||
namespace: flux-system
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- delete
|
||||
- create
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: gcr-credentials-sync
|
||||
namespace: flux-system
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: gcr-credentials-sync
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: gcr-credentials-sync
|
||||
apiGroup: ""
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
annotations:
|
||||
iam.gke.io/gcp-service-account: <name-of-service-account>@<project-id>.iam.gserviceaccount.com
|
||||
name: gcr-credentials-sync
|
||||
namespace: flux-system
|
||||
---
|
||||
apiVersion: batch/v1beta1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: gcr-credentials-sync
|
||||
namespace: flux-system
|
||||
spec:
|
||||
suspend: false
|
||||
schedule: "*/45 * * * *"
|
||||
failedJobsHistoryLimit: 1
|
||||
successfulJobsHistoryLimit: 1
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
serviceAccountName: gcr-credentials-sync
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- image: google/cloud-sdk
|
||||
name: create-secret
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: SECRET_NAME
|
||||
value: <SECRET_NAME> # this is the generated Secret name
|
||||
- name: GCR_REGISTRY
|
||||
value: <REGISTRY_NAME> # fill in the registry name e.g gcr.io, eu.gcr.io
|
||||
command:
|
||||
- /bin/bash
|
||||
- -ce
|
||||
- |-
|
||||
kubectl delete secret --ignore-not-found $SECRET_NAME
|
||||
kubectl create secret docker-registry $SECRET_NAME \
|
||||
--docker-server="$GCR_REGISTRY" \
|
||||
--docker-username=oauth2accesstoken \
|
||||
--docker-password="$(gcloud auth print-access-token)"
|
||||
```
|
||||
|
||||
Since the cronjob will not create a job right away, after applying the manifest,
|
||||
you can manually create an init job using the following command:
|
||||
|
||||
```console
|
||||
$ kubectl create job --from=cronjob/gcr-credentials-sync -n flux-system gcr-credentials-sync-init
|
||||
```
|
||||
|
||||
#### Using a JSON key [long-lived]
|
||||
|
||||
!!! warning "Less secure option"
|
||||
From [Google documentation on authenticating container registry](https://cloud.google.com/container-registry/docs/advanced-authentication#json-key)
|
||||
> A user-managed key-pair that you can use as a credential for a service account. Because the credential is long-lived, it is the least secure option of all the available authentication methods. When possible, use an access token or another available authentication method to reduce the risk of unauthorized access to your artifacts. If you must use a service account key, ensure that you follow best practices for managing credentials.
|
||||
|
||||
|
||||
Json keys doesn't expire so we don't need a cronjob, we just need to create the secret and reference it in the ImagePolicy.
|
||||
|
||||
First, create a json key file by following this [documentation](https://cloud.google.com/container-registry/docs/advanced-authentication). Grant the service account the role of `Container Registry Service Agent` so that it can access GCR and download the json file.
|
||||
|
||||
Then create a secret, encrypt it using [Mozilla SOPS](mozilla-sops.md) or [Sealed Secrets](sealed-secrets.md) , commit and push the encypted file to git.
|
||||
```
|
||||
kubectl create secret docker-registry <secret-name> \
|
||||
--docker-server=<GCR-REGISTRY> \ # e.g gcr.io
|
||||
--docker-username=_json_key \
|
||||
--docker-password="$(cat <downloaded-json-file>)"
|
||||
```
|
||||
|
||||
### Azure Container Registry
|
||||
|
||||
TODO
|
||||
@@ -62,10 +62,10 @@ flux bootstrap <GIT-PROVIDER> \
|
||||
--version=latest
|
||||
```
|
||||
|
||||
!!! hint "ARM"
|
||||
When deploying to a Kubernetes cluster with ARM architecture,
|
||||
you can use `--arch=arm` for ARMv7 32-bit container images
|
||||
and `--arch=arm64` for ARMv8 64-bit container images.
|
||||
!!! hint "Multi-arch images"
|
||||
The component images are published as [multi-arch container images](https://docs.docker.com/docker-for-mac/multi-arch/)
|
||||
with support for Linux `amd64`, `arm64` and `armv7` (e.g. 32bit Raspberry Pi)
|
||||
architectures.
|
||||
|
||||
If you wish to install a specific version, use the Flux
|
||||
[release tag](https://github.com/fluxcd/flux2/releases) e.g. `--version=v0.2.0`.
|
||||
@@ -118,11 +118,11 @@ flux bootstrap github \
|
||||
--personal
|
||||
```
|
||||
|
||||
!!! hint "Deploy Key"
|
||||
The bootstrap command creates a ssh key which it stores as a secret in the
|
||||
!!! hint "Deploy key"
|
||||
The bootstrap command creates an SSH key which it stores as a secret in the
|
||||
Kubernetes cluster. The key is also used to create a deploy key in the GitHub
|
||||
repository. The new deploy key will be linked to the personal access token used
|
||||
to authenticate. Removing the personal access token will remove the deploy key.
|
||||
to authenticate. **Removing the personal access token will also remove the deploy key.**
|
||||
|
||||
Run the bootstrap for a repository owned by a GitHub organization:
|
||||
|
||||
@@ -320,7 +320,7 @@ If you don't specify the SSH algorithm, then `flux` will generate an RSA 2048 bi
|
||||
```sh
|
||||
flux create source git flux-system \
|
||||
--git-implementation=libgit2 \
|
||||
--url=git@ssh.dev.azure.com/v3/org/project/repository \
|
||||
--url=ssh://git@ssh.dev.azure.com/v3/org/project/repository \
|
||||
--branch=master \
|
||||
--interval=1m
|
||||
```
|
||||
|
||||
@@ -104,13 +104,15 @@ flux create kustomization my-secrets \
|
||||
Note that the `sops-gpg` can contain more than one key, sops will try to decrypt the
|
||||
secrets by iterating over all the private keys until it finds one that works.
|
||||
|
||||
### AWS/Azure/GCP
|
||||
### Using various cloud providers
|
||||
|
||||
When using AWS/GCP KMS, you'll have to bind an IAM Role with access to the KMS
|
||||
keys to the `default` service account of the `flux-system` namespace for
|
||||
kustomize-controller to be able to fetch keys from KMS.
|
||||
|
||||
AWS IAM Role example:
|
||||
#### AWS
|
||||
|
||||
IAM Role example:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -131,10 +133,27 @@ AWS IAM Role example:
|
||||
}
|
||||
```
|
||||
|
||||
#### Azure
|
||||
|
||||
When using Azure Key Vault you need to authenticate the kustomize controller either by passing
|
||||
[Service Principal credentials as environment variables](https://github.com/mozilla/sops#encrypting-using-azure-key-vault)
|
||||
or with [add-pod-identity](https://github.com/Azure/aad-pod-identity).
|
||||
|
||||
#### Google Cloud
|
||||
|
||||
Please ensure that the GKE cluster has Workload Identity enabled.
|
||||
|
||||
1. Create a service account with the role `Cloud KMS CryptoKey Encrypter/Decrypter`.
|
||||
2. Create an IAM policy binding between the GCP service account to the `default` service account of the `flux-system`.
|
||||
3. Annotate the `default` service account in the `flux-system` with the GCP service account.
|
||||
|
||||
```sh
|
||||
kubectl annotate serviceaccount \
|
||||
--namespace flux-system \
|
||||
default \
|
||||
iam.gke.io/gcp-service-account=<name-of-serviceaccount>@project-id.iam.gserviceaccount.com
|
||||
```
|
||||
|
||||
## GitOps workflow
|
||||
|
||||
A cluster admin should create the Kubernetes secret with the PGP keys on each cluster and
|
||||
|
||||
@@ -105,47 +105,104 @@ When the verbosity is set to `info`, the controller will alert if:
|
||||
|
||||
## Git commit status
|
||||
|
||||
The `github` and `gitlab` provider are slightly different to the other chat providers. These providers will
|
||||
link an event back to its source by writing a commit status event to the repository. For more information about how a
|
||||
commit status works, refer to the [GitHub](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-status-checks)
|
||||
or [GitLab](https://docs.gitlab.com/ee/api/commits.html) documentation.
|
||||
The GitHub, GitLab, Bitbucket, and Azure DevOps providers are slightly different to the other providers. Instead of
|
||||
a stateless stream of events, the git notification providers will link the event with accompanying git commit which
|
||||
triggered the event. The linking is done by updating the commit status of a specific commit.
|
||||
|
||||
The first image is an example of how it may look like in GitHub while the one below is an example for GitLab.
|
||||

|
||||

|
||||
- [GitHub](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-status-checks)
|
||||
- [GitLab](https://docs.gitlab.com/ee/api/commits.html)
|
||||
- [Bitbucket](https://developer.atlassian.com/server/bitbucket/how-tos/updating-build-status-for-commits/)
|
||||
- [Azure DevOps](https://docs.microsoft.com/en-us/rest/api/azure/devops/git/statuses?view=azure-devops-rest-6.0)
|
||||
|
||||
Currently the provider will only work with Alerts for Kustomization resources as the events have to be linked with a
|
||||
specific git commit. Any other event that does not contain a commit reference will be ignored by the provider.
|
||||
Each status will contain some additional information from the event which includes the resource kind, name and reason for the event.
|
||||
It will be displayed in the format of `{{ .Kind }}/{{ .Name }} - {{ .Reason }}`.
|
||||
In GitHub the commit status set by notification-controller will result in a green checkmark or red cross next to the commit hash.
|
||||
Clicking the icon will show more detailed information about the status.
|
||||

|
||||
|
||||
To get started the git provider require an authentication token to communicate with the API.
|
||||
Follow the [GitHub](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)
|
||||
or [Gitlab](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) for a detailed guide how to create a token.
|
||||
Store the generated token in a Secret with the following data format.
|
||||
Receiving an event in the form of a commit status rather than a message in a chat conversation has the benefit
|
||||
that it closes the deployment loop giving quick and visible feedback if a commit has reconciled and if it succeeded.
|
||||
This means that a deployment will work in a similar manner that people are used to with "traditional" push based CD pipelines.
|
||||
Additionally the status can be fetched from the git providers API for a specific commit. Allowing for custom automation tools
|
||||
that can automatically promote, commit to a new directory, after receiving a successful commit status. This can all be
|
||||
done without requiring any access to the Kubernetes cluster.
|
||||
|
||||
As stated before the provider works by referencing the same git repository as the Kustomization controller does.
|
||||
When a new commit is pushed to the repository, source-controller will sync the commit, triggering the kustomize-controller
|
||||
to reconcile the new commit. After this is done the kustomize-controller sends an event to the notification-controller
|
||||
with the result and the commit hash it reconciled. Then notification-controller can update the correct commit and repository
|
||||
when receiving the event.
|
||||

|
||||
|
||||
!!! hint "Limitations"
|
||||
The git notification providers require that a commit hash present in the meta data
|
||||
of the event. There for the the providers will only work with `Kustomization` as an
|
||||
event source, as it is the only resource which includes this data.
|
||||
|
||||
First follow the [get started guide](../../get-started) if you do not have a Kubernetes cluster with Flux installed in it.
|
||||
You will need a authentication token to communicate with the API. The authentication method depends on
|
||||
the git provider used, refer to the [Provider CRD](../../components/notification/provider/#git-commit-status)
|
||||
for details about how to get the correct token. The guide will use GitHub, but the other providers will work in a very similar manner.
|
||||
The token will need to have write access to the repository it is going to update the commit status in.
|
||||
Store the generated token in a Secret with the following data format in the cluster.
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: github
|
||||
namespace: gitops-system
|
||||
namespace: flux-system
|
||||
data:
|
||||
token: <token>
|
||||
```
|
||||
|
||||
Creating a git provider is very similar to creating other types of providers.
|
||||
The only caveat being that the provider address needs to point to the same
|
||||
git repository as the Kustomization resource refers to.
|
||||
When sending notification events the kustomization-controller will include the commit hash related to the event.
|
||||
Note that the commit hash in the event does not come from the git repository the `Kustomization` resource
|
||||
comes from but rather the kustomization source ref. This mean that commit status notifications will not work
|
||||
if the manifests comes from a repository which the API token is not allowed to write to.
|
||||
|
||||
Copy the manifest content in the "[kustomize](https://github.com/stefanprodan/podinfo/tree/master/kustomize)" directory
|
||||
into the directory "./clusters/my-cluster/podinfo" in your fleet-infra repository. Make sure that you also add the
|
||||
namespace podinfo.
|
||||
```yaml
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta1
|
||||
kind: Provider
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: podinfo
|
||||
```
|
||||
|
||||
Then create a Kustomization to deploy podinfo.
|
||||
```yaml
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 5m
|
||||
targetNamespace: podinfo
|
||||
path: ./clusters/my-cluster/podinfo
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
healthChecks:
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: podinfo
|
||||
namespace: podinfo
|
||||
timeout: 1m
|
||||
```
|
||||
|
||||
Creating a git provider is very similar to creating other types of providers.
|
||||
The only caveat being that the provider address needs to point to the same
|
||||
git repository as the event source originates from.
|
||||
```yaml
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta1
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
spec:
|
||||
type: github
|
||||
channel: general
|
||||
address: https://github.com/stefanprodan/podinfo
|
||||
address: https://github.com/<username>/fleet-infra
|
||||
secretRef:
|
||||
name: github
|
||||
---
|
||||
@@ -156,7 +213,7 @@ metadata:
|
||||
namespace: flux-system
|
||||
spec:
|
||||
providerRef:
|
||||
name: podinfo
|
||||
name: flux-system
|
||||
eventSeverity: info
|
||||
eventSources:
|
||||
- kind: Kustomization
|
||||
@@ -164,14 +221,75 @@ spec:
|
||||
namespace: flux-system
|
||||
```
|
||||
|
||||
The secret referenced in the provider is expected to contain a [personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)
|
||||
to authenticate with the GitHub API.
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: github
|
||||
namespace: flux-system
|
||||
data:
|
||||
token: <token>
|
||||
By now the fleet-infra repository should have a similar directory structure.
|
||||
```
|
||||
fleet-infra
|
||||
└── clusters/
|
||||
└── my-cluster/
|
||||
├── flux-system/
|
||||
│ ├── gotk-components.yaml
|
||||
│ ├── gotk-sync.yaml
|
||||
│ └── kustomization.yaml
|
||||
├── podinfo/
|
||||
│ ├── namespace.yaml
|
||||
│ ├── deployment.yaml
|
||||
│ ├── hpa.yaml
|
||||
│ ├── service.yaml
|
||||
│ └── kustomization.yaml
|
||||
├── podinfo-kustomization.yaml
|
||||
└── podinfo-notification.yaml
|
||||
```
|
||||
|
||||
If podinfo is deployed and the health checks pass you should get a successful status in
|
||||
your forked podinfo repository.
|
||||
|
||||
If everything is setup correctly there should now be a green check-mark next to the latest commit.
|
||||
Clicking the check-mark should show a detailed view.
|
||||
|
||||
| GitHub | GitLab |
|
||||
| ------------- | ------------- |
|
||||
|  |  |
|
||||
|
||||
Generate error
|
||||
|
||||
A deployment failure can be forced by setting an invalid image tag in the podinfo deployment.
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: ghcr.io/stefanprodan/podinfo:fake
|
||||
```
|
||||
|
||||
After the commit has been reconciled it should return a failed commit status.
|
||||
This is where the health check in the Kustomization comes into play together
|
||||
with the timeout. The health check is used to asses the health of the Kustomization.
|
||||
A failed commit status will not be sent until the health check timeout. Setting
|
||||
a lower timeout will give feedback faster, but may sometimes not allow enough time
|
||||
for a new application to deploy.
|
||||
|
||||
| GitHub | GitLab |
|
||||
| ------------- | ------------- |
|
||||
|  |  |
|
||||
|
||||
|
||||
### Status changes
|
||||
|
||||
The provider will continuously receive events as they happen, and multiple events may
|
||||
be received for the same commit hash. The git providers are configured to only update
|
||||
the status if the status has changed. This is to avoid spamming the commit status
|
||||
history with the same status over and over again.
|
||||
|
||||
There is an aspect of state fullness that needs to be considered, compared to the other
|
||||
notification providers, as the events are stored by the git provider. This means that
|
||||
the status of a commit can change over time. Initially a deployment may be healthy, resulting
|
||||
in a successful status. Down the line the application, and the health check, may start failing
|
||||
due to the amount of traffic it receives or external dependencies no longer being available.
|
||||
The change in the health check would cause the status to go from successful to failed.
|
||||
It is important to keep this in mind when building any automation tools that deals with the
|
||||
status, and consider the fact that receiving a successful status once does not mean it will
|
||||
always be successful.
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ the sealed-secrets controller from its [Helm chart](https://hub.kubeapps.com/cha
|
||||
First you have to register the Helm repository where the sealed-secrets chart is published:
|
||||
|
||||
```sh
|
||||
flux create source helm stable \
|
||||
flux create source helm sealed-secrets \
|
||||
--interval=1h \
|
||||
--url=https://charts.helm.sh/stable
|
||||
--url=https://bitnami-labs.github.io/sealed-secrets
|
||||
```
|
||||
|
||||
With `interval` we configure [source-controller](../components/source/controller.md) to download
|
||||
@@ -50,7 +50,7 @@ flux create helmrelease sealed-secrets \
|
||||
--interval=1h \
|
||||
--release-name=sealed-secrets \
|
||||
--target-namespace=flux-system \
|
||||
--source=HelmRepository/stable \
|
||||
--source=HelmRepository/sealed-secrets \
|
||||
--chart=sealed-secrets \
|
||||
--chart-version="1.10.x"
|
||||
```
|
||||
|
||||
@@ -84,20 +84,20 @@ Depending on what you want to do, some of the following bits might be your first
|
||||
- And if you are completely new to Flux v2 and the GitOps Toolkit, take a look at our [Get Started guide](get-started/index.md) and give us feedback
|
||||
- Check out [how to contribute](contributing/index.md) to the project
|
||||
|
||||
### Featured Talks
|
||||
### Upcoming Events
|
||||
- 25 Jan 2021 - [GitOps Core Concepts & How to Teach Your Teams with Leigh Capili](https://www.meetup.com/GitOps-Community/events/275625806/)
|
||||
|
||||
### Featured Talks
|
||||
- 11 Jan 2021 - [Helm + GitOps = ⚡️⚡️⚡️ with Scott Rigby](https://youtu.be/YG8jMFrYQvM)
|
||||
- 14 Dec 2020 - [The Power of GitOps with Flux and Flagger (GitOps Hands-On) with Leigh Capili](https://youtu.be/cB7iXeNLteE)
|
||||
- 30 Nov 2020 - [The Power of GItOps with Flux 2 - Part 3 with Leigh Capili](https://youtu.be/N_K5g7o9JKg)
|
||||
- 24 Nov 2020 - [Flux CD v2 with GitOps Toolkit - Kubernetes Deployment and Sync Mechanism](https://youtu.be/R6OeIgb7lUI)
|
||||
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 2 with Leigh Capili](https://youtu.be/fC2YCxQRUwU)
|
||||
- 02 Nov 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 2 with Leigh Capili](https://youtu.be/fC2YCxQRUwU)
|
||||
- 28 Oct 2020 - [The Kubelist Podcast: Flux with Michael Bridgen](https://www.heavybit.com/library/podcasts/the-kubelist-podcast/ep-5-flux-with-michael-bridgen-of-weaveworks/)
|
||||
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 1 with Leigh Capili](https://youtu.be/0v5bjysXTL8)
|
||||
- 12 Oct 2020 - [Rawkode Live: Introduction to GitOps Toolkit with Stefan Prodan](https://youtu.be/HqTzuOBP0eY)
|
||||
- 4 Sep 2020 - [KubeCon Europe: The road to Flux v2 and Progressive Delivery with Stefan Prodan & Hidde Beydals](https://youtu.be/8v94nUkXsxU)
|
||||
- 04 Sep 2020 - [KubeCon Europe: The road to Flux v2 and Progressive Delivery with Stefan Prodan & Hidde Beydals](https://youtu.be/8v94nUkXsxU)
|
||||
- 25 June 2020 - [Cloud Native Nordics: Introduction to GitOps & GitOps Toolkit with Alexis Richardson & Stefan Prodan](https://youtu.be/qQBtSkgl7tI)
|
||||
- 7 May 2020 - [GitOps Days - Community Special: GitOps Toolkit Experimentation with Stefan Prodan](https://youtu.be/WHzxunv4DKk?t=6521)
|
||||
- 07 May 2020 - [GitOps Days - Community Special: GitOps Toolkit Experimentation with Stefan Prodan](https://youtu.be/WHzxunv4DKk?t=6521)
|
||||
|
||||
### Upcoming Events
|
||||
|
||||
- 12-13 Nov 2020 - [GitOps Days EMEA](https://www.gitopsdays.com/) with talks and workshops on migrating to Flux v2 and Helm Controller
|
||||
- 19 Nov 2020 - [KubeCon NA: Progressive Delivery Techniques with Flagger and Flux v2 with Stefan Prodan](https://kccncna20.sched.com/event/1b04f8408b49976b843a5d0019cb8112)
|
||||
|
||||
We are looking forward to seeing you with us!
|
||||
We look forward to seeing you with us!
|
||||
|
||||
@@ -48,11 +48,11 @@ Tasks
|
||||
|
||||
### Flux image update feature parity
|
||||
|
||||
[= 70% "70%"]
|
||||
[= 80% "80%"]
|
||||
|
||||
Image automation is available as a prerelease. See [the
|
||||
README](https://github.com/fluxcd/image-automation-controller#readme)
|
||||
for instructions on installing it.
|
||||
Image automation is available as a prerelease. See [this
|
||||
guide](https://toolkit.fluxcd.io/guides/image-update/) for how to
|
||||
install and use it.
|
||||
|
||||
Goals
|
||||
|
||||
@@ -73,7 +73,8 @@ Tasks
|
||||
- [ ] Azure-specific support [fluxcd/image-reflector-controller#11](https://github.com/fluxcd/image-reflector-controller/issues/11)
|
||||
- [x] <span style="color:grey">Design the automation component</span>
|
||||
- [x] <span style="color:grey">Implement the image scan/patch/push workflow</span>
|
||||
- [ ] Integrate the new components in the Flux CLI [fluxcd/flux2#538](https://github.com/fluxcd/flux2/pull/538)
|
||||
- [x] <span style="color:grey">Integrate the new components in the Flux CLI [fluxcd/flux2#538](https://github.com/fluxcd/flux2/pull/538)</span>
|
||||
- [x] <span style="color:grey">Write a guide for how to use image automation ([guide here](https://toolkit.fluxcd.io/guides/image-update/))</span>
|
||||
- [ ] Write a migration guide from Flux annotations
|
||||
|
||||
## The road to Helm Operator v2
|
||||
|
||||