Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10cc6d7e08 | ||
|
|
83c236c829 | ||
|
|
b6ab37691f | ||
|
|
c85af78025 | ||
|
|
2c2fc6dd97 | ||
|
|
3620b76139 |
@@ -118,6 +118,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
} else if installExport {
|
} else if installExport {
|
||||||
fmt.Println("---")
|
fmt.Println("---")
|
||||||
fmt.Println("# GitOps Toolkit revision", installVersion, time.Now().Format(time.RFC3339))
|
fmt.Println("# GitOps Toolkit revision", installVersion, time.Now().Format(time.RFC3339))
|
||||||
|
fmt.Println("# Components:", strings.Join(installComponents, ","))
|
||||||
fmt.Print(yaml)
|
fmt.Print(yaml)
|
||||||
fmt.Println("---")
|
fmt.Println("---")
|
||||||
return nil
|
return nil
|
||||||
@@ -183,7 +184,7 @@ fieldSpecs:
|
|||||||
`
|
`
|
||||||
|
|
||||||
var kustomizationTmpl = `---
|
var kustomizationTmpl = `---
|
||||||
{{- $version := .Version }}
|
{{- $eventsAddr := .EventsAddr }}
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
namespace: {{.Namespace}}
|
namespace: {{.Namespace}}
|
||||||
@@ -196,6 +197,21 @@ resources:
|
|||||||
{{- range .Components }}
|
{{- range .Components }}
|
||||||
- {{.}}.yaml
|
- {{.}}.yaml
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
patchesJson6902:
|
||||||
|
{{- range $i, $v := .Components }}
|
||||||
|
{{- if ne $v "notification-controller" }}
|
||||||
|
- target:
|
||||||
|
group: apps
|
||||||
|
version: v1
|
||||||
|
kind: Deployment
|
||||||
|
name: {{$v}}
|
||||||
|
patch: |-
|
||||||
|
- op: replace
|
||||||
|
path: /spec/template/spec/containers/0/args/0
|
||||||
|
value: --events-addr={{$eventsAddr}}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
`
|
`
|
||||||
|
|
||||||
var kustomizationRolesTmpl = `---
|
var kustomizationRolesTmpl = `---
|
||||||
@@ -241,14 +257,21 @@ func downloadManifests(version string, tmpDir string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func genInstallManifests(version string, namespace string, components []string, tmpDir string) error {
|
func genInstallManifests(version string, namespace string, components []string, tmpDir string) error {
|
||||||
|
eventsAddr := ""
|
||||||
|
if utils.containsItemString(components, defaultNotification) {
|
||||||
|
eventsAddr = fmt.Sprintf("http://%s/", defaultNotification)
|
||||||
|
}
|
||||||
|
|
||||||
model := struct {
|
model := struct {
|
||||||
Version string
|
Version string
|
||||||
Namespace string
|
Namespace string
|
||||||
Components []string
|
Components []string
|
||||||
|
EventsAddr string
|
||||||
}{
|
}{
|
||||||
Version: version,
|
Version: version,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Components: components,
|
Components: components,
|
||||||
|
EventsAddr: eventsAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := downloadManifests(version, tmpDir); err != nil {
|
if err := downloadManifests(version, tmpDir); err != nil {
|
||||||
|
|||||||
@@ -104,9 +104,10 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultComponents = []string{"source-controller", "kustomize-controller", "helm-controller", "notification-controller"}
|
defaultComponents = []string{"source-controller", "kustomize-controller", "helm-controller", "notification-controller"}
|
||||||
defaultVersion = "latest"
|
defaultVersion = "latest"
|
||||||
defaultNamespace = "gitops-system"
|
defaultNamespace = "gitops-system"
|
||||||
|
defaultNotification = "notification-controller"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -166,3 +166,12 @@ func (*Utils) copyFile(src, dst string) error {
|
|||||||
}
|
}
|
||||||
return out.Close()
|
return out.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*Utils) containsItemString(s []string, e string) bool {
|
||||||
|
for _, a := range s {
|
||||||
|
if a == e {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
173
docs/guides/sealed-secrets.md
Normal file
173
docs/guides/sealed-secrets.md
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
# Sealed Secrets
|
||||||
|
|
||||||
|
In order to store secrets safely in a public or private Git repository, you can use
|
||||||
|
Bitnami's [sealed-secrets controller](https://github.com/bitnami-labs/sealed-secrets)
|
||||||
|
and encrypt your Kubernetes Secrets into SealedSecrets.
|
||||||
|
The sealed secrets can be decrypted only by the controller running in your cluster and
|
||||||
|
nobody else can obtain the original secret, even if they have access to the Git repository.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
To follow this guide you'll need a Kubernetes cluster with the GitOps
|
||||||
|
toolkit controllers installed on it.
|
||||||
|
Please see the [get started guide](../get-started/index.md)
|
||||||
|
or the [install command docs](../cmd/tk_install.md).
|
||||||
|
|
||||||
|
The sealed-secrets controller comes with a companion CLI tool called kubeseal.
|
||||||
|
With kubeseal you can create SealedSecret custom resources in YAML format
|
||||||
|
and store those in your Git repository.
|
||||||
|
|
||||||
|
Install the kubeseal CLI:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install kubeseal
|
||||||
|
```
|
||||||
|
|
||||||
|
For Linux or Windows you can download the kubeseal binary from
|
||||||
|
[GitHub](https://github.com/bitnami-labs/sealed-secrets/releases).
|
||||||
|
|
||||||
|
## Deploy sealed-secrets with a HelmRelease
|
||||||
|
|
||||||
|
You'll be using [helm-controller](../components/helm/controller.md) APIs to install
|
||||||
|
the sealed-secrets controller from its [Helm chart](https://hub.kubeapps.com/charts/stable/sealed-secrets).
|
||||||
|
|
||||||
|
First you have to register the Helm repository where the sealed-secrets chart is published:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tk create source helm stable \
|
||||||
|
--interval=1h \
|
||||||
|
--url=https://kubernetes-charts.storage.googleapis.com
|
||||||
|
```
|
||||||
|
|
||||||
|
With `interval` we configure [source-controller](../components/source/controller.md) to download
|
||||||
|
the Helm repository index every hour. If a newer version of sealed-secrets is published,
|
||||||
|
source-controller will signal helm-controller that a new chart is available.
|
||||||
|
|
||||||
|
Create a Helm release that installs the latest version of sealed-secrets controller:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tk create helmrelease sealed-secrets \
|
||||||
|
--interval=1h \
|
||||||
|
--release-name=sealed-secrets \
|
||||||
|
--target-namespace=gitops-system \
|
||||||
|
--source=stable \
|
||||||
|
--chart-name=sealed-secrets \
|
||||||
|
--chart-version="^1.10.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
With chart version `^1.10.0` we configure helm-controller to automatically upgrade the release
|
||||||
|
when a new chart version is fetch by source-controller.
|
||||||
|
|
||||||
|
At startup, the sealed-secrets controller generates a 4096-bit RSA key pair and
|
||||||
|
persists the private and public keys as Kubernetes secrets in the `gitops-system` namespace.
|
||||||
|
|
||||||
|
You can retrieve the public key with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubeseal --fetch-cert \
|
||||||
|
--controller-name=sealed-secrets \
|
||||||
|
--controller-namespace=gitops-system \
|
||||||
|
> pub-sealed-secrets.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
The public key can be safely stored in Git, and can be used to encrypt secrets
|
||||||
|
without direct access to the Kubernetes cluster.
|
||||||
|
|
||||||
|
## Encrypt secrets
|
||||||
|
|
||||||
|
Generate a Kubernetes secret manifest with kubectl:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubectl -n default create secret generic basic-auth \
|
||||||
|
--from-literal=user=admin \
|
||||||
|
--from-literal=password=change-me \
|
||||||
|
--dry-run \
|
||||||
|
-o yaml > basic-auth.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Encrypt the secret with kubeseal:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubeseal --format=yaml --cert=pub-sealed-secrets.pem \
|
||||||
|
< basic-auth.yaml > basic-auth-sealed.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Delete the plain secret and apply the sealed one:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
rm basic-auth.yaml
|
||||||
|
kubectl apply -f basic-auth-sealed.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify that the sealed-secrets controller has created the `basic-auth` Kubernetes Secret:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ kubectl -n default get secrets basic-auth
|
||||||
|
|
||||||
|
NAME TYPE DATA AGE
|
||||||
|
basic-auth Opaque 2 1m43s
|
||||||
|
```
|
||||||
|
|
||||||
|
## GitOps workflow
|
||||||
|
|
||||||
|
A cluster admin should add the stable `HelmRepository` manifest and the sealed-secrets `HelmRelease`
|
||||||
|
to the fleet repository.
|
||||||
|
|
||||||
|
Helm repository manifest:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: source.fluxcd.io/v1alpha1
|
||||||
|
kind: HelmRepository
|
||||||
|
metadata:
|
||||||
|
name: stable
|
||||||
|
namespace: gitops-system
|
||||||
|
spec:
|
||||||
|
interval: 1h0m0s
|
||||||
|
url: https://kubernetes-charts.storage.googleapis.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Helm release manifest:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: helm.fluxcd.io/v2alpha1
|
||||||
|
kind: HelmRelease
|
||||||
|
metadata:
|
||||||
|
name: sealed-secrets
|
||||||
|
namespace: gitops-system
|
||||||
|
spec:
|
||||||
|
chart:
|
||||||
|
name: sealed-secrets
|
||||||
|
sourceRef:
|
||||||
|
kind: HelmRepository
|
||||||
|
name: stable
|
||||||
|
version: "^1.10.0"
|
||||||
|
interval: 1h0m0s
|
||||||
|
releaseName: sealed-secrets
|
||||||
|
targetNamespace: gitops-system
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! hint
|
||||||
|
You can generate the above manifests using `tk create <kind> --export > manifest.yaml`.
|
||||||
|
|
||||||
|
Once the sealed-secrets controller is installed, the admin fetches the
|
||||||
|
public key and shares it with the teams that operate on the fleet clusters via Git.
|
||||||
|
|
||||||
|
When a team member wants to create a Kubernetes Secret on a cluster,
|
||||||
|
they uses kubeseal and the public key corresponding to that cluster to generate a SealedSecret.
|
||||||
|
|
||||||
|
Assuming a team member wants to deploy an application that needs to connect
|
||||||
|
to a database using a username and password, they'll be doing the following:
|
||||||
|
|
||||||
|
* create a Kubernetes Secret manifest locally with the db credentials e.g. `db-auth.yaml`
|
||||||
|
* encrypt the secret with kubeseal as `db-auth-sealed.yaml`
|
||||||
|
* delete the original secret file `db-auth.yaml`
|
||||||
|
* create a Kubernetes Deployment manifest for the app e.g. `app-deployment.yaml`
|
||||||
|
* add the Secret to the Deployment manifest as a [volume mount or env var](https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets) using the original name `db-auth`
|
||||||
|
* commit the manifests `db-auth-sealed.yaml` and `app-deployment.yaml` to a Git repository that's being synced by the GitOps toolkit controllers
|
||||||
|
|
||||||
|
Once the manifests have been pushed to the Git repository, the following happens:
|
||||||
|
|
||||||
|
* source-controller pulls the changes from Git
|
||||||
|
* kustomize-controller applies the SealedSecret and the Deployment manifests
|
||||||
|
* sealed-secrets controller decrypts the SealedSecret and creates a Kubernetes Secret
|
||||||
|
* kubelet creates the pods and mounts the secret as a volume or env variable inside the app container
|
||||||
2
go.mod
2
go.mod
@@ -4,7 +4,7 @@ go 1.14
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/blang/semver v3.5.1+incompatible
|
github.com/blang/semver v3.5.1+incompatible
|
||||||
github.com/fluxcd/helm-controller v0.0.1-beta.3
|
github.com/fluxcd/helm-controller v0.0.1-beta.4
|
||||||
github.com/fluxcd/kustomize-controller v0.0.5
|
github.com/fluxcd/kustomize-controller v0.0.5
|
||||||
github.com/fluxcd/pkg v0.0.3
|
github.com/fluxcd/pkg v0.0.3
|
||||||
github.com/fluxcd/source-controller v0.0.6
|
github.com/fluxcd/source-controller v0.0.6
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -172,8 +172,8 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwC
|
|||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fluxcd/helm-controller v0.0.1-beta.3 h1:S6XOwAM0IbJxYDbasv85Zk7W1gJ51S3ZqYylMtGcuEE=
|
github.com/fluxcd/helm-controller v0.0.1-beta.4 h1:Go7ZGI91BY6A69Qp9TdJg3nufaahQCYhpj7Lum9oyKA=
|
||||||
github.com/fluxcd/helm-controller v0.0.1-beta.3/go.mod h1:asoN9pG8J0oQ9iXpkxNwvch1EKspus6RxH818ZYVo+4=
|
github.com/fluxcd/helm-controller v0.0.1-beta.4/go.mod h1:asoN9pG8J0oQ9iXpkxNwvch1EKspus6RxH818ZYVo+4=
|
||||||
github.com/fluxcd/kustomize-controller v0.0.5 h1:jjBJT/UbblMaeQpYn5TjH/oXXnORO6C3Cka77bs9K3Q=
|
github.com/fluxcd/kustomize-controller v0.0.5 h1:jjBJT/UbblMaeQpYn5TjH/oXXnORO6C3Cka77bs9K3Q=
|
||||||
github.com/fluxcd/kustomize-controller v0.0.5/go.mod h1:1O78f9Qigs74BMxO/ThzLt5XGGQnwQPgzi+47ntie5M=
|
github.com/fluxcd/kustomize-controller v0.0.5/go.mod h1:1O78f9Qigs74BMxO/ThzLt5XGGQnwQPgzi+47ntie5M=
|
||||||
github.com/fluxcd/pkg v0.0.3 h1:yhjtpGtD9LxFo8JtwTuUxJyFcX2wSSb0TPptIEpGSmA=
|
github.com/fluxcd/pkg v0.0.3 h1:yhjtpGtD9LxFo8JtwTuUxJyFcX2wSSb0TPptIEpGSmA=
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- github.com/fluxcd/helm-controller/config//crd?ref=v0.0.1-beta.3
|
- github.com/fluxcd/helm-controller/config//crd?ref=v0.0.1-beta.4
|
||||||
- github.com/fluxcd/helm-controller/config//manager?ref=v0.0.1-beta.3
|
- github.com/fluxcd/helm-controller/config//manager?ref=v0.0.1-beta.4
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
group: apps
|
group: apps
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ nav:
|
|||||||
- Manage Helm Releases: guides/helmreleases.md
|
- Manage Helm Releases: guides/helmreleases.md
|
||||||
- Setup Notifications: guides/notifications.md
|
- Setup Notifications: guides/notifications.md
|
||||||
- Setup Webhook Receivers: guides/webhook-receivers.md
|
- Setup Webhook Receivers: guides/webhook-receivers.md
|
||||||
|
- Sealed Secrets: guides/sealed-secrets.md
|
||||||
- Toolkit Components:
|
- Toolkit Components:
|
||||||
- Source Controller:
|
- Source Controller:
|
||||||
- Overview: components/source/controller.md
|
- Overview: components/source/controller.md
|
||||||
|
|||||||
Reference in New Issue
Block a user