Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
1706d26
Fixing crossplane install
diegopso Jun 8, 2025
f65d7ed
Fixing crossplane install
diegopso Jun 8, 2025
fd870bc
Separating job steps
diegopso Jun 8, 2025
2178323
Fixing path
diegopso Jun 8, 2025
feeb93f
Adjusting paths
diegopso Jun 8, 2025
447b655
Fixing action
diegopso Jun 8, 2025
3dcefd3
Initial cluster
diegopso Jun 9, 2025
2a5df9e
Removing AWS config
diegopso Jun 9, 2025
292506e
Removing wrong char
diegopso Jun 9, 2025
42b6931
Adding shell
diegopso Jun 9, 2025
d848a2c
Converting syncWaves to string
diegopso Jun 9, 2025
31f9618
quoting syncwaves
diegopso Jun 9, 2025
1b7b639
Reducing syncwave numbers
diegopso Jun 9, 2025
a726f0e
Adding syncwave to sops secret
diegopso Jun 9, 2025
31c6967
Using sealed secrets
diegopso Jun 9, 2025
0a8175d
Allow creating namespace
diegopso Jun 9, 2025
c4ba826
Changing namespace of secret
diegopso Jun 9, 2025
298217a
Adding finalizers
diegopso Jun 9, 2025
3bd3f9b
Allow disable infrastructure
diegopso Jun 9, 2025
a27675c
Random bucket name
diegopso Jun 9, 2025
470b56e
Testing sync waves
diegopso Jun 9, 2025
b65f8aa
Testing sync waves
diegopso Jun 9, 2025
790eab6
Using argo hooks
diegopso Jun 10, 2025
4a6e1cd
Adding comment
diegopso Jun 10, 2025
61a6e02
Removing sync waves
diegopso Jun 10, 2025
8d2cf3d
Removing auto-sync
diegopso Jun 10, 2025
852d753
Moving providers to foundation
diegopso Jun 10, 2025
c3b9353
Re-adding syncwaves
diegopso Jun 10, 2025
44a9314
Spin up resources in action
diegopso Jun 10, 2025
696d2ed
Removing deps update
diegopso Jun 10, 2025
ef8a077
Loading secret before install
diegopso Jun 10, 2025
ad755f6
Loading secret before install
diegopso Jun 10, 2025
2241359
Removing debug command
diegopso Jun 10, 2025
bfc0598
Adding namespace
diegopso Jun 10, 2025
1912446
Adding timeout to wait
diegopso Jun 10, 2025
069dd06
Adding debug lines
diegopso Jun 10, 2025
cf63547
More debug lines
diegopso Jun 10, 2025
47bddce
debugging
diegopso Jun 10, 2025
bcee328
Using minikube instead of kind
diegopso Jun 10, 2025
d98a21b
Debug line
diegopso Jun 15, 2025
3729fcb
Adding debug lines
diegopso Jun 15, 2025
89d06d5
Fixing namespace
diegopso Jun 15, 2025
fdb2ca1
Collecting argo logs
diegopso Jun 15, 2025
ad2680c
Fixing namespace
diegopso Jun 15, 2025
16b8c82
Debuging aws creds
diegopso Jun 15, 2025
a57d0f2
Masking secrets before adding to file
diegopso Jun 15, 2025
34d361d
Fixing variables export
diegopso Jun 15, 2025
0124f7e
Fixing secret retrieval
diegopso Jun 15, 2025
a5eba19
Wait for deletion
diegopso Jun 15, 2025
7d9cfdd
Masking secrets
diegopso Jun 15, 2025
2ba9b4d
Masking secrets in separate step
diegopso Jun 15, 2025
d91952d
Fixing step id
diegopso Jun 15, 2025
69f0800
Fixing secret masks
diegopso Jun 15, 2025
80622c7
Waiting for bucket to be ready
diegopso Jun 15, 2025
863a779
waiting on namespace
diegopso Jun 15, 2025
2721cfc
Waiting with --all flag
diegopso Jun 15, 2025
23357c1
Removing wait for buckets
diegopso Jun 15, 2025
ede7578
Using wait command
diegopso Jun 15, 2025
92a7b09
Waiting for creation of bucket
diegopso Jun 15, 2025
d25926f
Using sleep...
diegopso Jun 15, 2025
19600ea
Adding docs
diegopso Jun 15, 2025
e873353
Waiting for crossplane resources
diegopso Jun 15, 2025
8bb6058
Waiting for crossplane resources
diegopso Jun 15, 2025
2628728
Rewritting retry logic
diegopso Jun 15, 2025
3ad4d41
Remove sleep line
diegopso Jun 15, 2025
949665b
Fixing var name
diegopso Jun 15, 2025
d20d639
Fixing variable name
diegopso Jun 15, 2025
b5be4da
Increasing wait time
diegopso Jun 15, 2025
b6da736
New AWS key
diegopso Jun 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/actions/setup-helm/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Setup Helm
description: This action sets up Docker, kubectl, and Helm in the GitHub Actions environment.
runs:
using: "composite"
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Set up kubectl
uses: azure/setup-kubectl@v4

- name: Set up Helm
uses: azure/setup-helm@v4
34 changes: 34 additions & 0 deletions .github/actions/wait/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Setup SOPS
description: This action sets up Docker, kubectl, and Helm in the GitHub Actions environment.

inputs:
resource:
required: true
description: "Resource to wait for"
max_retries:
required: false
default: "10"
description: "Resource to wait for"

runs:
using: "composite"
steps:
- name: Wait for ${{ inputs.resource }} to be ready
shell: bash
run: |
retry=1
while [[ $retry -le ${{ inputs.max_retries }} ]]; do
if kubectl wait ${{ inputs.resource }} --for=condition=Ready --all --timeout 1s; then
echo "Succeeded."
break
else
echo "Attempt $retry/${{ inputs.max_retries }} failed. Retrying in 10 seconds..."
sleep 10
((retry++))
fi
done

if [[ $retry -gt ${{ inputs.max_retries }} ]]; then
echo "Wait failed after ${{ inputs.max_retries }} attempts."
exit 1
fi
82 changes: 50 additions & 32 deletions .github/workflows/create-cluster.yaml
Original file line number Diff line number Diff line change
@@ -1,48 +1,66 @@
name: Create Cluster
run-name: Creating Cluster
on: [push]

env:
resource_app: app/aws-eu1
provider_secret: secret/aws-secret
infrastructure_namespace: infrastructure

jobs:
SpinUpCluster:
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Set up kubectl
uses: azure/setup-kubectl@v4

- name: Set up Helm
uses: azure/setup-helm@v4

- name: Install kind
run: |
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
uses: ./.github/actions/setup-helm

- name: Create kind cluster
run: |
kind create cluster --wait 60s

- name: Get Cluster status
- name: start minikube
id: minikube
uses: medyagh/setup-minikube@latest

- name: Spin-up resources
shell: bash
run: |
# wait network is ready
kubectl wait --for=condition=ready pods --namespace=kube-system -l k8s-app=kube-dns
kubectl get nodes -o wide
kubectl get pods -A

- name: Install Crossplane
cat << EOF > ./foundation/tls.pem
${{ secrets.SEALED_SECRETS_PKEY }}
EOF
helm dependencies build ./foundation
helm upgrade --install platform-foundation ./foundation --wait

- name: Wait for Crossplane resources
uses: ./.github/actions/wait
with:
resource: buckets

- name: Export AWS credentials
id: export_aws_secrets
shell: bash
run: |
helm upgrade --install crossplane crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace \
--repo https://charts.crossplane.io/stable/ \
--wait
kubectl wait --timeout 60s --for=create ${provider_secret} -n ${infrastructure_namespace}
kubectl get ${provider_secret} -n ${infrastructure_namespace} --template={{.data.creds}} | base64 -d | tail -n2 | tr -d ' ' >> aws.txt
set -a
. ./aws.txt
set +a
echo "::add-mask::$aws_access_key_id"
echo "::add-mask::$aws_secret_access_key"
cat aws.txt >> "$GITHUB_OUTPUT"

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ steps.export_aws_secrets.outputs.aws_access_key_id }}
aws-secret-access-key: ${{ steps.export_aws_secrets.outputs.aws_secret_access_key }}
aws-region: us-east-2

- name: Check Crossplane status
- name: List AWS resources
shell: bash
run: aws s3 ls | grep crossplane

- name: Destroy resources
shell: bash
run: |
kubectl get pods -n crossplane-system
kubectl get crds | grep crossplane.io
kubectl delete ${resource_app}
kubectl wait --timeout 60s --for=delete ${resource_app}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.secrets/
*.tgz
*.lock
*.pem
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## Pre-requisties

- A `kubectl`, `helm`, and `kubeseal`.

> Kubeseal is only needed to seal secrets, but not for deployment.

## Provision resources from local

Add the private key to `foundation/tls.pem`, then:

```bash
cp /path/to/my-key/tls.pem ./foundation
helm dependencies build ./foundation
helm upgrade --install platform-foundation ./foundation --namespace platform-foundation --create-namespace --wait
```

### Uninstall

```bash
kubectl delete app/aws-eu1 -n platform-foundation # delete this first to avoid race condition
helm uninstall platform-foundation --namespace platform-foundation --wait
```

## View ArgoCD UI

```bash
kubectl get secret argocd-initial-admin-secret -n platform-foundation --template={{.data.password}} | base64 -d
kubectl port-forward svc/platform-foundation-argocd-server -n platform-foundation 8080:443
```

Use the secret printed and the user `admin` to see the [UI](https://localhost:8080/).

## Sealing required secrets with Kubeseal

Create a file `./.secrets/aws-creds.yaml` with:

```
[default]
aws_access_key_id = your-key-id-here
aws_secret_access_key = your-secret-here
```

Then:

```bash
kubectl create secret generic aws-secret --from-file=creds=./.secrets/aws-credentials.txt --dry-run=client -o yaml > ./.secrets/aws-creds.yaml
cat ./.secrets/aws-creds.yaml | kubeseal --cert foundation/tls.crt -o yaml -n infrastructure > aws-eu1/infrastructure/templates/aws-creds.yaml
```
13 changes: 13 additions & 0 deletions aws-eu1/apps/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v2
name: base-cluster-application
description: A Helm chart for Kubernetes

type: application
version: 0.1.0
appVersion: "0.1.0"
icon: https://docs.crossplane.io/favicon-32x32.png

# dependencies:
# - name: crossplane
# version: "1.20.0"
# repository: https://charts.crossplane.io/stable
26 changes: 26 additions & 0 deletions aws-eu1/apps/templates/infrastructure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{{- if .Values.infrastructureApp.enabled -}}
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: infrastructure
finalizers:
- resources-finalizer.argocd.argoproj.io
annotations:
argocd.argoproj.io/sync-wave: {{ .Values.argoSyncWaves.infrastructureApp | quote }}
spec:
project: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
source:
repoURL: https://github.com/diegopso/crossplane-example.git
targetRevision: cluster-creation
path: aws-eu1/infrastructure
destination:
server: https://kubernetes.default.svc
namespace: infrastructure
{{- end -}}
5 changes: 5 additions & 0 deletions aws-eu1/apps/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
argoSyncWaves:
infrastructureApp: "-10000"

infrastructureApp:
enabled: true
13 changes: 13 additions & 0 deletions aws-eu1/infrastructure/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v2
name: crossplane-infrastructure
description: A Helm chart for Kubernetes

type: application
version: 0.1.0
appVersion: "1.20.0"
icon: https://docs.crossplane.io/favicon-32x32.png

# dependencies:
# - name: crossplane
# version: "1.20.0"
# repository: https://charts.crossplane.io/stable
15 changes: 15 additions & 0 deletions aws-eu1/infrastructure/templates/aws-creds.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: aws-secret
namespace: infrastructure
spec:
encryptedData:
creds: AgAqzcrd2DmhzTKYzHG/AG4SrIHwYljieg+Tm9SsB9F4aYo3MZOd1BAcNBIExo1szuFJgTBtPpr8E369LFLLcp12Sc9Q1L2xVLjguS49qGPze69sF4q8SeyT7/fn5RNGbvr4QJ0/RMXh9Lt8+S+0eKWdLTdbE4/ldc0pwEHDSaClAxFgKYbLy+B/h6aVvguAznskHVSE0oCpCM3FFLtLuFkaUXTBwWhdtGRC9auJbisqcS6Vho7qwjdRDx5ZFeRcQ983t4+7KGy51IieDIE9IyW0OQno+H/7V9l5AoZXTt7dJ2FN2skBk9cJMOVPHEgJccosHj8znDPnYG2OROeQJ3bFv0d/gbh8FJSvbWl4jzP6PdXB11w4tXfHfTb6Xj8X86Qq5KqJH2Dm665yaRyHV+x9v6j2JUA9Ba2BaSZMhZd+kZTbf2+GcbB0UiodqZAW5YKUkY4nTugRoGbbjca24M0hu022yUErADjHJNWzdE4WGNr1cF6VTV4Ky5mJ/ACpRKsNLxJkl5KJKDXjpO/ny/B55IHNWCJnxkSyusMvH2J/072LURQZio5+GsWH48MzhS6HXXVqsv7vXZHm/P6XsMX43aL8wxlBGLebFWb8kI5yLP1DFxF8w4G+AJXNrksE9nddO+nFWvy4C4eNbjm3wibL77bkZ7RemvErbKylNj+qaSNjHRMcBtuNe7Tg+SGhALqPOcdY0w8tIZ9lUbrQak4sjX2v+Evx3e8tuRbJmKJRPMEV72cMVcYzxXbW+LGicrxtEgER3M87AfB30uc82w9JrHnoH0U1Jlnh/gB+4Lm8eiaERoIB70He+8SP/bMmy+K9nUH2VxwZBwC+Zz9cLesz3IJieW4piA==
template:
metadata:
creationTimestamp: null
name: aws-secret
namespace: infrastructure
10 changes: 10 additions & 0 deletions aws-eu1/infrastructure/templates/buckets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
name: crossplane-bucket-{{ uuidv4 }}
spec:
forProvider:
region: us-east-2
providerConfigRef:
name: default
14 changes: 14 additions & 0 deletions aws-eu1/infrastructure/templates/provider-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
annotations:
argocd.argoproj.io/sync-wave: {{ .Values.argoSyncWaves.configs | quote }}
spec:
credentials:
source: Secret
secretRef:
namespace: {{ .Release.Namespace }}
name: aws-secret
key: creds
3 changes: 3 additions & 0 deletions aws-eu1/infrastructure/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
argoSyncWaves:
secrets: "-1000"
configs: "-990"
19 changes: 19 additions & 0 deletions foundation/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v2
name: foundation
description: A foundation Helm chart for a cluster

type: application
version: 0.1.0
appVersion: "1.20.0"
icon: https://docs.crossplane.io/favicon-32x32.png

dependencies:
- name: crossplane
version: "1.20.0"
repository: https://charts.crossplane.io/stable
- name: argo-cd
version: "8.0.16"
repository: https://argoproj.github.io/argo-helm
- name: sealed-secrets
version: "2.17.2"
repository: https://bitnami-labs.github.io/sealed-secrets
22 changes: 22 additions & 0 deletions foundation/templates/aws-eu1-apps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: aws-eu1
annotations:
helm.sh/hook: post-install
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/diegopso/crossplane-example.git
path: aws-eu1/apps
targetRevision: cluster-creation
destination:
server: https://kubernetes.default.svc
namespace: {{ .Release.Namespace }}
syncPolicy:
automated:
prune: true
selfHeal: true
9 changes: 9 additions & 0 deletions foundation/templates/providers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
annotations:
helm.sh/hook: post-install
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v1.21.1
13 changes: 13 additions & 0 deletions foundation/templates/sealed-secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Secret
metadata:
name: sealed-secrets-initial-key
annotations:
helm.sh/hook: pre-install # for install when only Helm is present
argocd.argoproj.io/hook: PreSync # for later syncs when ArgoCD is in controll
labels:
sealedsecrets.bitnami.com/sealed-secrets-key: active
type: kubernetes.io/tls
data:
tls.crt: {{ .Files.Get "tls.crt" | b64enc }}
tls.key: {{ .Files.Get "tls.pem" | b64enc }}
Loading
Loading