├── deploy
├── crossplane-core
│ ├── crossplane-system-namespace.yaml
│ ├── crossplane-repository.yaml
│ ├── kustomization.yaml
│ └── crossplane-release.yaml
├── crossplane-xr
│ ├── kustomization.yaml
│ └── eks-cluster-xr.yaml
├── crossplane-aws-provider
│ ├── kustomization.yaml
│ ├── aws-provider.yaml
│ └── sealed-secrets-controller.yaml
├── crossplane-composition
│ ├── kustomization.yaml
│ ├── aws-providerconfig.yaml
│ ├── crossplane-eks-composition.yaml
│ └── aws-credentials-sealed.yaml
├── monitoring
│ ├── prometheus-repository.yaml
│ ├── kustomizeconfig.yaml
│ ├── kustomization.yaml
│ ├── prometheus-release.yaml
│ └── prometheus-values.yaml
└── webapp
│ └── deployment-webapp.yaml
├── images
├── Component-Relationship.png
└── Deployment-Architecture.png
├── crossplane-imperative
├── aws-provider.yaml
├── eks-configuration
│ ├── crossplane.yaml
│ ├── compositeresourcedefinition.yaml
│ └── composition.yaml
├── aws-providerconfig.yaml
└── eks-cluster-xr.yaml
├── CODE_OF_CONDUCT.md
├── crossplane
├── crossplane-composite-resources.yaml
├── crossplane-configuration-package.yaml
├── crossplane-provider-package.yaml
└── crossplane-helmrelease.yaml
├── applications
├── application-webapp.yaml
└── application-prometheus.yaml
├── LICENSE
├── remote
├── remote-cluster-setup.md
└── service-account-rbac.yaml
├── CONTRIBUTING.md
├── README.md
├── flux.md
├── crossplane.sh
└── Grafana-Metrics-Dashboard.json
/deploy/crossplane-core/crossplane-system-namespace.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Namespace
4 | metadata:
5 | name: crossplane-system
--------------------------------------------------------------------------------
/images/Component-Relationship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/eks-gitops-crossplane-flux/HEAD/images/Component-Relationship.png
--------------------------------------------------------------------------------
/images/Deployment-Architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/eks-gitops-crossplane-flux/HEAD/images/Deployment-Architecture.png
--------------------------------------------------------------------------------
/deploy/crossplane-xr/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - eks-cluster-xr.yaml
6 |
7 |
8 |
--------------------------------------------------------------------------------
/deploy/crossplane-aws-provider/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - sealed-secrets-controller.yaml
6 | - aws-provider.yaml
7 |
8 |
9 |
--------------------------------------------------------------------------------
/crossplane-imperative/aws-provider.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: pkg.crossplane.io/v1
2 | kind: Provider
3 | metadata:
4 | name: crossplane-provider-aws
5 | spec:
6 | package: "public.ecr.aws/awsvijisarathy/crossplane-provider-aws:v0.23.0"
--------------------------------------------------------------------------------
/deploy/crossplane-aws-provider/aws-provider.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: pkg.crossplane.io/v1
3 | kind: Provider
4 | metadata:
5 | name: crossplane-provider-aws
6 | spec:
7 | package: "public.ecr.aws/awsvijisarathy/crossplane-provider-aws:v0.23.0"
--------------------------------------------------------------------------------
/deploy/crossplane-composition/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - aws-credentials-sealed.yaml
6 | - aws-providerconfig.yaml
7 | - crossplane-eks-composition.yaml
8 |
9 |
10 |
--------------------------------------------------------------------------------
/deploy/crossplane-core/crossplane-repository.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: source.toolkit.fluxcd.io/v1beta1
3 | kind: HelmRepository
4 | metadata:
5 | name: crossplane-repository
6 | namespace: crossplane-system
7 | spec:
8 | interval: 5m
9 | url: https://charts.crossplane.io/stable
--------------------------------------------------------------------------------
/deploy/crossplane-core/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | namespace: crossplane-system
5 | resources:
6 | - crossplane-system-namespace.yaml
7 | - crossplane-repository.yaml
8 | - crossplane-release.yaml
9 |
10 |
--------------------------------------------------------------------------------
/deploy/monitoring/prometheus-repository.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: source.toolkit.fluxcd.io/v1beta1
3 | kind: HelmRepository
4 | metadata:
5 | name: prometheus-community
6 | namespace: flux-system
7 | spec:
8 | interval: 5m
9 | url: https://prometheus-community.github.io/helm-charts
10 |
11 |
12 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/deploy/crossplane-composition/aws-providerconfig.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: aws.crossplane.io/v1beta1
3 | kind: ProviderConfig
4 | metadata:
5 | name: default
6 | spec:
7 | credentials:
8 | source: Secret
9 | secretRef:
10 | namespace: crossplane-system
11 | name: aws-credentials
12 | key: credentials
13 |
--------------------------------------------------------------------------------
/crossplane-imperative/eks-configuration/crossplane.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: meta.pkg.crossplane.io/v1alpha1
2 | kind: Configuration
3 | metadata:
4 | name: eks-cluster-composition
5 | annotations:
6 | provider: aws
7 | spec:
8 | crossplane:
9 | version: ">=v1.0.0"
10 | dependsOn:
11 | - provider: public.ecr.aws/awsvijisarathy/crossplane-provider-aws
12 | version: ">=v0.14.0"
13 |
--------------------------------------------------------------------------------
/deploy/crossplane-composition/crossplane-eks-composition.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: pkg.crossplane.io/v1
2 | kind: Configuration
3 | metadata:
4 | name: crossplane-eks-composition
5 | spec:
6 | ignoreCrossplaneConstraints: false
7 | package: public.ecr.aws/awsvijisarathy/crossplane-eks-composition:7.0.0
8 | packagePullPolicy: IfNotPresent
9 | revisionActivationPolicy: Automatic
10 | revisionHistoryLimit: 0
11 | skipDependencyResolution: false
12 |
--------------------------------------------------------------------------------
/crossplane/crossplane-composite-resources.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
3 | kind: Kustomization
4 | metadata:
5 | name: crossplane-resources
6 | namespace: flux-system
7 | spec:
8 | dependsOn:
9 | - name: crossplane-configuration-package
10 | interval: 30s
11 | path: ./deploy/crossplane-xr
12 | prune: true
13 | sourceRef:
14 | kind: GitRepository
15 | name: flux-system
16 | validation: client
17 |
18 |
--------------------------------------------------------------------------------
/deploy/crossplane-composition/aws-credentials-sealed.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: bitnami.com/v1alpha1
2 | kind: SealedSecret
3 | metadata:
4 | creationTimestamp: null
5 | name: aws-credentials
6 | namespace: crossplane-system
7 | spec:
8 | encryptedData:
9 | credentials: XXXXXXXXXXXXXX
10 | template:
11 | data: null
12 | metadata:
13 | creationTimestamp: null
14 | name: aws-credentials
15 | namespace: crossplane-system
16 |
17 |
--------------------------------------------------------------------------------
/applications/application-webapp.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
3 | kind: Kustomization
4 | metadata:
5 | name: application-webapp
6 | namespace: flux-system
7 | spec:
8 | interval: 30s
9 | path: ./deploy/webapp
10 | prune: true
11 | sourceRef:
12 | kind: GitRepository
13 | name: flux-system
14 | kubeConfig:
15 | secretRef:
16 | name: crossplane-workload-cluster-connection
17 | validation: client
18 |
--------------------------------------------------------------------------------
/crossplane/crossplane-configuration-package.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
3 | kind: Kustomization
4 | metadata:
5 | name: crossplane-configuration-package
6 | namespace: flux-system
7 | spec:
8 | dependsOn:
9 | - name: crossplane-provider-package
10 | interval: 30s
11 | path: ./deploy/crossplane-composition
12 | prune: true
13 | sourceRef:
14 | kind: GitRepository
15 | name: flux-system
16 | validation: client
17 |
18 |
--------------------------------------------------------------------------------
/deploy/crossplane-core/crossplane-release.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: helm.toolkit.fluxcd.io/v2beta1
2 | kind: HelmRelease
3 | metadata:
4 | name: crossplane-core
5 | namespace: flux-system
6 | spec:
7 | releaseName: crossplane-core
8 | interval: 5m
9 | chart:
10 | spec:
11 | chart: crossplane
12 | version: '1.6.2'
13 | sourceRef:
14 | kind: HelmRepository
15 | name: crossplane-repository
16 | namespace: crossplane-system
17 | interval: 1m
18 |
19 |
20 |
--------------------------------------------------------------------------------
/deploy/monitoring/kustomizeconfig.yaml:
--------------------------------------------------------------------------------
1 | #
2 | # It is possible to use Kustomize ConfigMap generator to trigger a Helm release upgrade every time the encoded values change.
3 | # First, create a kustomizeconfig.yaml for Kustomize to be able to patch ConfigMap referenced in HelmRelease manifest
4 | # The 'fieldSpecs/path' identifies the ConfigMap referenced in the HelmRelease.
5 | # Create a HelmRelease definition that references a ConfigMap
6 | # Create a 'kustomization.yaml' that generates the ConfigMap using the configurations from 'kustomizeconfig.yaml'
7 | #
8 | nameReference:
9 | - kind: ConfigMap
10 | version: v1
11 | fieldSpecs:
12 | - path: spec/valuesFrom/name
13 | kind: HelmRelease
14 |
15 |
--------------------------------------------------------------------------------
/crossplane/crossplane-provider-package.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
3 | kind: Kustomization
4 | metadata:
5 | name: crossplane-provider-package
6 | namespace: flux-system
7 | spec:
8 | dependsOn:
9 | - name: crossplane-helmrelease
10 | interval: 30s
11 | path: ./deploy/crossplane-aws-provider
12 | prune: true
13 | sourceRef:
14 | kind: GitRepository
15 | name: flux-system
16 | healthChecks:
17 | - kind: Deployment
18 | name: sealed-secrets-controller
19 | namespace: sealed-secrets
20 | - kind: Deployment
21 | name: crossplane-provider-aws-45985ebe751d
22 | namespace: crossplane-system
23 | validation: client
24 | timeout: 2m
25 |
26 |
--------------------------------------------------------------------------------
/applications/application-prometheus.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
3 | kind: Kustomization
4 | metadata:
5 | name: application-prometheus
6 | namespace: flux-system
7 | spec:
8 | dependsOn:
9 | - name: application-webapp
10 | interval: 30s
11 | path: ./deploy/monitoring
12 | prune: true
13 | sourceRef:
14 | kind: GitRepository
15 | name: flux-system
16 | healthChecks:
17 | - apiVersion: helm.toolkit.fluxcd.io/v2beta1
18 | kind: HelmRelease
19 | name: prometheus-helmrelease
20 | namespace: flux-system
21 | #
22 | # Prometheus is deployed using a HelmRelease.
23 | # Hence, the 'kubeConfig' field that points to the remote workload cluster is set in the HelmRelease manifest
24 | #
25 | validation: client
26 | timeout: 2m
27 |
28 |
--------------------------------------------------------------------------------
/deploy/monitoring/kustomization.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.config.k8s.io/v1beta1
3 | kind: Kustomization
4 | resources:
5 | - prometheus-repository.yaml
6 | - prometheus-release.yaml
7 | #
8 | # Generate a ConfigMap resources from the specified file
9 | # This will generate a ConfigMap which will contain a key named 'value.yaml'
10 | # The value associated with this key will be the contents of the file 'prometheus-nosidecar-values.yaml'
11 | # This ConfigMap can then be references in a HelmRelease to override the default values for a Helm chart
12 | #
13 | configMapGenerator:
14 | - name: prometheus-configmap
15 | namespace: flux-system
16 | files:
17 | - values.yaml=prometheus-values.yaml
18 | #
19 | # Trigger a Helm release upgrade everytime the values in prometheus-values.yaml change
20 | #
21 | configurations:
22 | - kustomizeconfig.yaml
23 |
24 |
--------------------------------------------------------------------------------
/crossplane-imperative/aws-providerconfig.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: aws.crossplane.io/v1beta1
2 | kind: ProviderConfig
3 | metadata:
4 | #
5 | # In order to authenticate with the AWS API, the provider controllers need to have access to credentials. It could be an IAM User for AWS
6 | # Note that every Crossplane managed resource has a 'providerConfig' field which allows us to specify a separate ProviderConfig per Managed Resource.
7 | # This allows us to use IAM credentials that are limited in scope to perform the operations related to only that managed resource.
8 | # If 'providerConfigRef' is not specified for a Managed Resource, Crossplane will attempt to use a ProviderConfig named 'default'
9 | #
10 | name: default
11 | spec:
12 | credentials:
13 | source: Secret
14 | secretRef:
15 | namespace: crossplane-system
16 | name: aws-credentials
17 | key: credentials
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software is furnished to do so.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15 |
16 |
--------------------------------------------------------------------------------
/deploy/monitoring/prometheus-release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: helm.toolkit.fluxcd.io/v2beta1
3 | kind: HelmRelease
4 | #
5 | # Note that this HelmRelease is deployed on the workload cluster
6 | # The release itself is made in a namespace that equals to the namespace of the HelmRelease which is 'flux-system' here.
7 | # As this namespace should already exist, we have to create a 'flux-system' namespace on the workload cluster.
8 | #
9 | metadata:
10 | name: prometheus-helmrelease
11 | namespace: flux-system
12 | spec:
13 | # install:
14 | # createNamespace: true
15 | targetNamespace: monitoring
16 | releaseName: prometheus-for-amp
17 | interval: 5m
18 | kubeConfig:
19 | secretRef:
20 | name: crossplane-workload-cluster-connection
21 | chart:
22 | spec:
23 | chart: prometheus
24 | sourceRef:
25 | kind: HelmRepository
26 | name: prometheus-community
27 | namespace: flux-system
28 | interval: 1m
29 | valuesFrom:
30 | - kind: ConfigMap
31 | name: prometheus-configmap
32 |
33 |
34 |
--------------------------------------------------------------------------------
/deploy/monitoring/prometheus-values.yaml:
--------------------------------------------------------------------------------
1 | serviceAccounts:
2 | server:
3 | name: prometheus-service-account
4 | annotations:
5 | #
6 | # Set this to the ARN of an IAM role for the service account.
7 | # For details, refer to the documentation here: https://docs.aws.amazon.com/prometheus/latest/userguide/set-up-irsa.html
8 | #
9 | eks.amazonaws.com/role-arn: XXXXXXXXXX
10 |
11 | nodeExporter:
12 | enabled: false
13 | alertmanager:
14 | enabled: false
15 | pushgateway:
16 | enabled: false
17 | kubeStateMetrics:
18 | enabled: false
19 |
20 | server:
21 | statefulSet:
22 | enabled: false
23 | persistentVolume:
24 | enabled: false
25 |
26 | remoteWrite:
27 | #
28 | # Set the ID of an AMP workspace
29 | #
30 | - url: https://aps-workspaces.us-west-2.amazonaws.com/workspaces/XXXXXXXXXXXXX/api/v1/remote_write
31 | sigv4:
32 | region: us-west-2
33 | queue_config:
34 | max_samples_per_send: 1000
35 | max_shards: 200
36 | capacity: 2500
--------------------------------------------------------------------------------
/crossplane/crossplane-helmrelease.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
3 | kind: Kustomization
4 | metadata:
5 | name: crossplane-helmrelease
6 | namespace: flux-system
7 | spec:
8 | interval: 30s
9 | path: ./deploy/crossplane-core
10 | prune: true
11 | sourceRef:
12 | kind: GitRepository
13 | name: flux-system
14 | #
15 | # A Kustomization can contain a series of health checks used to determine the rollout status of the deployed workloads and the ready status of custom resources.
16 | # A health check entry can reference either one of the Kubernetes builtin types or GitOps Toolkit types such as HelmRelease, HelmRepository, GitRepository, etc.
17 | # When a Kustomization contains HelmRelease objects, instead of checking the underling Deployments, you can define a health check that waits for the HelmReleases to be reconciled with
18 | #
19 | healthChecks:
20 | - apiVersion: helm.toolkit.fluxcd.io/v2beta1
21 | kind: HelmRelease
22 | name: crossplane-core
23 | namespace: crossplane-system
24 | - kind: Deployment
25 | name: crossplane
26 | namespace: crossplane-system
27 | - kind: Deployment
28 | name: crossplane-rbac-manager
29 | namespace: crossplane-system
30 | validation: client
31 | timeout: 2m
32 |
33 |
--------------------------------------------------------------------------------
/crossplane-imperative/eks-cluster-xr.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: eks.sarathy.io/v1beta1
3 | kind: EKSCluster
4 | metadata:
5 | name: crossplane-cluster
6 | spec:
7 | parameters:
8 | region: us-west-2
9 | vpc-name: "EKS-CROSSPLANE-VPC"
10 | vpc-cidrBlock: "192.168.48.0/20"
11 |
12 | subnet1-public-name: "PUBLIC-WORKER-1"
13 | subnet1-public-cidrBlock: "192.168.48.0/24"
14 | subnet1-public-availabilityZone: "us-west-2a"
15 |
16 | subnet2-public-name: "PUBLIC-WORKER-2"
17 | subnet2-public-cidrBlock: "192.168.49.0/24"
18 | subnet2-public-availabilityZone: "us-west-2b"
19 |
20 | subnet1-private-name: "PRIVATE-WORKER-1"
21 | subnet1-private-cidrBlock: "192.168.50.0/24"
22 | subnet1-private-availabilityZone: "us-west-2a"
23 |
24 | subnet2-private-name: "PRIVATE-WORKER-2"
25 | subnet2-private-cidrBlock: "192.168.51.0/24"
26 | subnet2-private-availabilityZone: "us-west-2b"
27 |
28 | cluster-role: arn:aws:iam::XXXX:role/EKS-Cluster-Role
29 | workernode-role: arn:aws:iam::XXXX:role/EKS-WorkerNode-Role
30 |
31 | k8s-version: "1.21"
32 | workload-type: "non-gpu"
33 | workers-size: 2
34 |
35 | compositionRef:
36 | name: amazon-eks-cluster
37 |
38 | writeConnectionSecretToRef:
39 | namespace: flux-system
40 | name: crossplane-cluster-connection
--------------------------------------------------------------------------------
/deploy/crossplane-xr/eks-cluster-xr.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: eks.sarathy.io/v1beta1
3 | kind: EKSCluster
4 | metadata:
5 | name: crossplane-flux-cluster
6 | spec:
7 | parameters:
8 | region: us-west-2
9 | vpc-name: "EKS-CROSSPLANE-FLUX-VPC"
10 | vpc-cidrBlock: "192.168.48.0/20"
11 |
12 | subnet1-public-name: "PUBLIC-WORKER-1 "
13 | subnet1-public-cidrBlock: "192.168.48.0/24"
14 | subnet1-public-availabilityZone: "us-west-2a"
15 |
16 | subnet2-public-name: "PUBLIC-WORKER-2"
17 | subnet2-public-cidrBlock: "192.168.49.0/24"
18 | subnet2-public-availabilityZone: "us-west-2b"
19 |
20 | subnet1-private-name: "PRIVATE-WORKER-1"
21 | subnet1-private-cidrBlock: "192.168.50.0/24"
22 | subnet1-private-availabilityZone: "us-west-2a"
23 |
24 | subnet2-private-name: "PRIVATE-WORKER-2"
25 | subnet2-private-cidrBlock: "192.168.51.0/24"
26 | subnet2-private-availabilityZone: "us-west-2b"
27 |
28 | cluster-role: "arn:aws:iam::XXXXXXXX:role/EKS-Cluster-Role"
29 | workernode-role: "arn:aws:iam::XXXXXXXX:role/EKS-WorkerNode-Role"
30 |
31 | k8s-version: "1.20"
32 | workload-type: "non-gpu"
33 | workers-size: 2
34 |
35 | compositionRef:
36 | name: amazon-eks-cluster
37 |
38 | writeConnectionSecretToRef:
39 | namespace: flux-system
40 | name: crossplane-flux-cluster-connection
--------------------------------------------------------------------------------
/deploy/webapp/deployment-webapp.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Namespace
4 | metadata:
5 | name: flux-system
6 |
7 | ---
8 | apiVersion: v1
9 | kind: Namespace
10 | metadata:
11 | name: monitoring
12 |
13 | ---
14 | apiVersion: v1
15 | kind: Namespace
16 | metadata:
17 | name: golang
18 |
19 | ---
20 | apiVersion: apps/v1
21 | kind: Deployment
22 | metadata:
23 | name: webapp
24 | namespace: golang
25 | spec:
26 | replicas: 3
27 | selector:
28 | matchLabels:
29 | app: webapp
30 | role: scrape-target
31 | template:
32 | metadata:
33 | labels:
34 | app: webapp
35 | role: scrape-target
36 | annotations:
37 | prometheus.io/scrape: 'true'
38 | prometheus.io/port: '3000'
39 | prometheus.io/path: '/metrics'
40 | spec:
41 | containers:
42 | - name: golang
43 | image: public.ecr.aws/awsvijisarathy/prometheus-webapp:2.0
44 | imagePullPolicy: Always
45 | resources:
46 | requests:
47 | cpu: "128m"
48 | memory: "128Mi"
49 | ports:
50 | - name: http
51 | containerPort: 3000
52 | protocol: TCP
53 | ---
54 | apiVersion: v1
55 | kind: Service
56 | metadata:
57 | name: webapp-svc
58 | namespace: golang
59 | spec:
60 | sessionAffinity: None
61 | type: ClusterIP
62 | ports:
63 | - port: 80
64 | protocol: TCP
65 | targetPort: 3000
66 | selector:
67 | app: webapp
68 | role: scrape-target
69 |
70 |
--------------------------------------------------------------------------------
/remote/remote-cluster-setup.md:
--------------------------------------------------------------------------------
1 | ```shell
2 | #
3 | # After the remote EKS cluster creation is completed using Crossplane, do the following:
4 | # 'kubeconfig-admin' file contains the KubeConfig data created by Crossplane when the remote cluster is provisioned.
5 | # This can be obtained from the Secret 'crossplane-workload-cluster-connection' created in the 'flux-system' namespace by Crossplane.
6 | # These credentials pertain to that of the cluster creator and has system:masters permissions in the EKS cluster and are rorated on a continual basis.
7 | # Using this KubeConfig data, create a service account in the workload cluster
8 | #
9 | kubectl apply -f service-account-rbac.yaml --kubeconfig ./kubeconfig-admin
10 |
11 | #
12 | # After applying the above change, a service account named 'apprunner' is created in the 'applications' namespace of the remote cluster.
13 | # The service account is configured to have 'cluster-admin' permissions in the EKS cluster.
14 | # Next, create a file 'kubeconfig-sa' with the KubeConfig data that pertains to the this service account's credentials.
15 | # These credentials are not rotated and are permanent.
16 | #
17 | cp kubeconfig-admin kubeconfig-sa
18 | SERVICE_ACCOUNT_NAME=apprunner
19 | SERVICE_ACCOUNT_NAMESPACE=applications
20 | SERVICE_ACCOUNT_SECRET_NAME=$(kubectl -n $SERVICE_ACCOUNT_NAMESPACE get sa $SERVICE_ACCOUNT_NAME -o jsonpath='{.secrets[0].name}' --kubeconfig ./kubeconfig-admin)
21 | SERVICE_ACCOUNT_TOKEN=$(kubectl -n $SERVICE_ACCOUNT_NAMESPACE get secret $SERVICE_ACCOUNT_SECRET_NAME -o jsonpath={.data.token} --kubeconfig ./kubeconfig-admin | base64 -d)
22 | kubectl config set-credentials $SERVICE_ACCOUNT_NAME --token=$SERVICE_ACCOUNT_TOKEN --kubeconfig=./kubeconfig-sa
23 | kubectl config set-context --current --user=$SERVICE_ACCOUNT_NAME --kubeconfig=./kubeconfig-sa
24 |
25 | #
26 | # Create a Secret named 'crossplane-workload-cluster-sa-connection' in the 'flux-system' namespace
27 | # Reference this Secret in Kustomization/HelmRelease that are targeting deployments to the workload cluster
28 | #
29 | kubectl -n flux-system create secret generic crossplane-workload-cluster-sa-connection --from-file=value=./kubeconfig-sa
30 | ```
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *main* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Amazon EKS cluser management with Crossplane and Flux
2 |
3 | This Git repository contains software artifacts to deploy [Crossplane](https://crossplane.io/) server and [Flux](https://fluxcd.io/) to an existing Amazon EKS cluster and then leverage the GitOps workflow to manage both provisioning a remote EKS cluster with Crossplane and subsequently manage application deployments to it using Flux. Please refer to the [accompanying blog post](https://aws.amazon.com/blogs/containers/gitops-model-for-provisioning-and-bootstrapping-amazon-eks-clusters-using-crossplane-and-flux) for details about how this works. Please also refer to the [earlier blog in this series](https://aws.amazon.com/blogs/containers/gitops-model-for-provisioning-and-bootstrapping-amazon-eks-clusters-using-crossplane-and-argo-cd/) for additional context.
4 |
5 |
6 |
7 | ### Solution overview
8 |
9 | Here’s the high level overview of the solution architecture.
10 |
11 | - Start off with an Amazon EKS cluster that was created using any one of the approaches outlined [here](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html).
12 | - Install and bootstrap Flux on this cluster to manage all deployment tasks, pointing to a Git repository containing the deployment artifacts.
13 | - Deploy Crossplane components needed to manage the lifecycle of AWS managed service resources.
14 | - Deploy Crossplane composite resource to provision an Amazon EKS cluster
15 | - Deploy a set of workloads to the new cluster
16 |
17 | The goal is to manage all of these tasks in a declarative style based on the [GitOps](https://www.weave.works/blog/what-is-gitops-really) approach.
18 |
19 | ### Deployment overview
20 |
21 | #### Imperative approach
22 | The script [crossplane.sh](https://github.com/aws-samples/eks-gitops-crossplane-flux/blob/main/crossplane.sh) outlines the CLI commands to install Crossplane to a management EKS cluster and then provision a workload EKS cluster. The implementation uses Crossplane's [Composition](https://crossplane.io/docs/v1.4/concepts/composition.html) and [CompositeResourceDefinition](https://crossplane.io/docs/v1.4/concepts/composition.html) to create a Crossplane [Configuration package](https://crossplane.io/docs/v1.4/concepts/packages.html#configuration-packages) that will provision the complete infrastructure for setting up an EKS cluster - VPC, subnets, internet gateway, NAT gateways, route tables, and the EKS cluster with a managed node group. The figure below shows the relationship between various Crossplane custom resources used in this Configuration package and the set of AWS managed resources that they provision.
23 |
24 |
25 |
26 | #### Declarative approach
27 | The script [flux.sh](https://github.com/aws-samples/eks-gitops-crossplane-flux/blob/main/flux.sh) outlines the steps involved in installing and bootstrapping Flux on the management EKS cluster and then leveraging the GitOps workflow in Flux to manage both provisioning and management of a remote workload cluster.
28 |
29 | ## Security
30 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
31 |
32 | ## License
33 | This library is licensed under the MIT-0 License. See the LICENSE file.
--------------------------------------------------------------------------------
/remote/service-account-rbac.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Namespace
4 | metadata:
5 | name: applications
6 |
7 | ---
8 | apiVersion: v1
9 | kind: ServiceAccount
10 | metadata:
11 | name: apprunner
12 | namespace: applications
13 |
14 | #
15 | # When Flux reconciles a HelmRelease to a remote cluster, the list of Helm releases are created in the flux-system.
16 | # TO facilitate this, the 'apprunner' service account is granted full access to the 'flux-system' namespace in the workload cluster.
17 | # The actual application workloads that makeup the chart are deployed into the namespace specified by the 'targetNamespace' field in the HelmRelease resource.
18 | #
19 | ---
20 | apiVersion: v1
21 | kind: Namespace
22 | metadata:
23 | name: flux-system
24 |
25 | ---
26 | apiVersion: rbac.authorization.k8s.io/v1
27 | kind: RoleBinding
28 | metadata:
29 | name: apprunner-rolebinding
30 | namespace: flux-system
31 | roleRef:
32 | apiGroup: rbac.authorization.k8s.io
33 | kind: ClusterRole
34 | name: cluster-admin
35 | subjects:
36 | - kind: ServiceAccount
37 | name: apprunner
38 | namespace: applications
39 |
40 | ---
41 | apiVersion: v1
42 | kind: Namespace
43 | metadata:
44 | name: golang
45 |
46 | ---
47 | apiVersion: rbac.authorization.k8s.io/v1
48 | kind: RoleBinding
49 | metadata:
50 | name: apprunner-rolebinding
51 | namespace: golang
52 | roleRef:
53 | apiGroup: rbac.authorization.k8s.io
54 | kind: ClusterRole
55 | name: cluster-admin
56 | subjects:
57 | - kind: ServiceAccount
58 | name: apprunner
59 | namespace: applications
60 |
61 | ---
62 | apiVersion: v1
63 | kind: Namespace
64 | metadata:
65 | name: monitoring
66 |
67 | ---
68 | apiVersion: rbac.authorization.k8s.io/v1
69 | kind: RoleBinding
70 | metadata:
71 | name: apprunner-rolebinding
72 | namespace: monitoring
73 | roleRef:
74 | apiGroup: rbac.authorization.k8s.io
75 | kind: ClusterRole
76 | name: cluster-admin
77 | subjects:
78 | - kind: ServiceAccount
79 | name: apprunner
80 | namespace: applications
81 |
82 | #
83 | # When Prometheus server is deployed using the prometheus-community Helm chart it creates a ClusterRole that grants permission to [get,list,watch] resources in the core API group.
84 | # Therefore, the 'apprunner' service account should be able to create ClusterRoles and ClusterRoleBindings that can grant these permissions to a Kubernetes subject.
85 | # In order to facilitate this, the ClusterRole below is created and bound to the 'apprunner' service account
86 | #
87 | ---
88 | apiVersion: rbac.authorization.k8s.io/v1
89 | kind: ClusterRole
90 | metadata:
91 | name: apprunner-role
92 | rules:
93 | - apiGroups:
94 | - rbac.authorization.k8s.io
95 | resources:
96 | - clusterrolebindings
97 | verbs:
98 | - get
99 | - list
100 | - watch
101 | - create
102 | - apiGroups:
103 | - rbac.authorization.k8s.io
104 | resources:
105 | - clusterroles
106 | verbs:
107 | - get
108 | - list
109 | - watch
110 | - create
111 | - bind
112 | - apiGroups:
113 | - ""
114 | resources:
115 | - nodes
116 | - nodes/proxy
117 | - nodes/metrics
118 | - services
119 | - endpoints
120 | - pods
121 | - ingresses
122 | - configmaps
123 | verbs:
124 | - get
125 | - list
126 | - watch
127 | - apiGroups:
128 | - extensions
129 | - networking.k8s.io
130 | resources:
131 | - ingresses/status
132 | - ingresses
133 | verbs:
134 | - get
135 | - list
136 | - watch
137 | - nonResourceURLs:
138 | - /metrics
139 | verbs:
140 | - get
141 |
142 | ---
143 | apiVersion: rbac.authorization.k8s.io/v1
144 | kind: ClusterRoleBinding
145 | metadata:
146 | name: apprunner-clusterrolebinding
147 | roleRef:
148 | apiGroup: rbac.authorization.k8s.io
149 | kind: ClusterRole
150 | name: apprunner-role
151 | subjects:
152 | - kind: ServiceAccount
153 | name: apprunner
154 | namespace: applications
--------------------------------------------------------------------------------
/flux.md:
--------------------------------------------------------------------------------
1 | ```shell
2 | #
3 | # Set these environment variables
4 | #
5 | export CLUSTER_NAME=XXXX
6 | export GITHUB_TOKEN=XXXXX
7 | export GITHUB_USER=XXXX
8 |
9 | #
10 | # Bootstrapping the cluster with Flux
11 | # The bootstrap process will automatically create a GitRepository custom resource that points to the given repository
12 | # The GitRepository resource is named after the namespace where Flux GitOps ToolKit is installed. In this case, it is 'flux-system'
13 | # The bootstrap process will configure the repository with an SSH key for read-only access
14 | #
15 | kubectl create ns flux-system
16 | flux bootstrap github \
17 | --components-extra=image-reflector-controller,image-automation-controller \
18 | --owner=$GITHUB_USER \
19 | --namespace=flux-system \
20 | --repository=eks-gitops-crossplane-flux \
21 | --branch=main \
22 | --path=clusters/$CLUSTER_NAME \
23 | --personal
24 |
25 | #
26 | # In order to authenticate with the external provider API such as AWS, the Crossplane AWS provider controller need to have access to credentials.
27 | # An AWS user with Administrative privileges is needed to enable Crossplane to create the required resources
28 | # We wil have to first create a configuration file, secrets.conf, with credeantials of an AWS account in the following format.
29 | #
30 | # [default]
31 | # aws_access_key_id = XXXXXXXXXXXXXXXXXXXXXXX
32 | # aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXX
33 | #
34 | # Then using this file, a YAML file that defines a Kubernetes Secret is created as follows
35 | #
36 | kubectl -n crossplane-system create secret generic aws-credentials --from-file=credentials=./secrets.conf --dry-run=client -o yaml > aws-credentials.yaml
37 |
38 | #
39 | # Next, deploy the Bitnami's Sealed Secrets controller in the 'sealed-secrets' namespace
40 | # Then, generate a SealedSecret corresponding to the 'aws-credentials' Secret created above. This is done as shown below using the 'kubeseal' companion utility for Bitnami's Sealed Secrets.
41 | # The file 'aws-credentials-sealed.yaml' resulting from the operation below is the one to deploy to the management cluster in the GitOps workflow.
42 | # Push this file to the './deploy/crossplane-composition' directory of the GitHub repo that Flux is pointing to
43 | #
44 | kubeseal --controller-namespace sealed-secrets --format yaml < aws-credentials.yaml > aws-credentials-sealed.yaml
45 |
46 | #
47 | # Important! Extract the master sealing key from the Sealed Secrets controller into a YAML file.
48 | # After extracting the master key, the Sealed Secrets controller may be termintaed.
49 | # The controller per se will get deployed as part of the GitOps workflow.
50 | # But you must make sure that the sealing key is first deployed using this file so that all SealedSecrets that were created using this master could be unsealed
51 | #
52 | kubectl get secret -n sealed-secrets -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml > sealing-master.yaml
53 |
54 |
55 | #
56 | # Now, you are ready to initiate the GitOps worflow.
57 | # Create a Kustomization resource under 'cluster/$CLUSTER_NAME' that points to the 'crossplane' directory in the config repo.
58 | # Pushing this file to the Git repository will trigger a Flux reconcilliation loop which will install the following:
59 | # 1. Crossplane core components
60 | # 2. Crossplane AWS provider-specific components
61 | # 3. Crossplane Configuration package for creating EKS cluster and other AWS resources
62 | # 4. Composite resource to create an EKS cluster
63 | # When this reconcilliation loop is completed, Crossplane will start provisioning the EKS cluster.
64 | # It will take about 10 minutes for the cluster to be ready and operational
65 | #
66 | mkdir -p ./clusters/${CLUSTER_NAME}
67 | flux create kustomization crossplane \
68 | --source=flux-system \
69 | --namespace=flux-system \
70 | --path=./crossplane \
71 | --prune=true \
72 | --validation=client \
73 | --interval=30s \
74 | --export > ./clusters/$CLUSTER_NAME/crossplane.yaml
75 |
76 | #
77 | # To deploy workloads to the remote cluster using the credentials of the cluster creator, continue with the following step.
78 | # To deploy using the credentials of a service account with appropriate set of RBAC permissions, refer to ./remote/remote-cluster-setup.sh before proceeding further.
79 | # Create a Kustomization resource under 'cluster/$CLUSTER_NAME' that points to the 'applications' directory
80 | # Pushing this file to the Git repository will trigger a Flux reconcilliation loop which will install the following:
81 | # 1. Sample web application that exposes Prometheus metrics
82 | # 2. Prometheus server which scrapes the metrics from the sample application and sends it to an AMP workspace
83 | #
84 | mkdir -p ./clusters/${CLUSTER_NAME}
85 | flux create kustomization applications \
86 | --source=flux-system \
87 | --namespace=flux-system \
88 | --path=./applications \
89 | --prune=true \
90 | --validation=client \
91 | --interval=30s \
92 | --export > ./clusters/$CLUSTER_NAME/applications.yaml
93 |
94 |
95 | ```
96 |
--------------------------------------------------------------------------------
/crossplane-imperative/eks-configuration/compositeresourcedefinition.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apiextensions.crossplane.io/v1
3 | kind: CompositeResourceDefinition
4 | metadata:
5 | name: eksclusters.eks.sarathy.io
6 | spec:
7 | group: eks.sarathy.io
8 | names:
9 | kind: EKSCluster
10 | plural: eksclusters
11 | connectionSecretKeys:
12 | - cluster-ca
13 | - apiserver-endpoint
14 | - value
15 | versions:
16 | - name: v1beta1
17 | served: true
18 | referenceable: true
19 | schema:
20 | openAPIV3Schema:
21 | type: object
22 | properties:
23 | spec:
24 | type: object
25 | properties:
26 | parameters:
27 | type: object
28 | properties:
29 | region:
30 | description: Geographic location of this VPC
31 | type: string
32 | enum: ["us-east-1", "us-west-2"]
33 |
34 | vpc-cidrBlock:
35 | description: CIDR block for VPC
36 | type: string
37 | vpc-name:
38 | description: Name for VPC
39 | type: string
40 |
41 | subnet1-public-name:
42 | description: Name for public subnet 1
43 | type: string
44 | subnet1-public-cidrBlock:
45 | description: CIDR block for public subnet 1
46 | type: string
47 | subnet1-public-availabilityZone:
48 | description: AZ for public subnet 1
49 | type: string
50 |
51 | subnet2-public-name:
52 | description: Name for public subnet 2
53 | type: string
54 | subnet2-public-cidrBlock:
55 | description: CIDR block for public subnet 2
56 | type: string
57 | subnet2-public-availabilityZone:
58 | description: AZ for public subnet 2
59 | type: string
60 |
61 | subnet1-private-name:
62 | description: Name for private subnet 1
63 | type: string
64 | subnet1-private-cidrBlock:
65 | description: CIDR block for private subnet 1
66 | type: string
67 | subnet1-private-availabilityZone:
68 | description: AZ for private subnet 1
69 | type: string
70 |
71 | subnet2-private-name:
72 | description: Name for private subnet 2
73 | type: string
74 | subnet2-private-cidrBlock:
75 | description: CIDR block for private subnet 2
76 | type: string
77 | subnet2-private-availabilityZone:
78 | description: AZ for private subnet 2
79 | type: string
80 |
81 | cluster-role:
82 | description: EKS cluster role
83 | type: string
84 | workernode-role:
85 | description: EKS worker node role
86 | type: string
87 |
88 | k8s-version:
89 | description: Kubernetes version
90 | type: string
91 | enum: ["1.20", "1.21", "1.22"]
92 | workers-size:
93 | description: Desired number of worker nodes in the cluster
94 | type: integer
95 | workload-type:
96 | description: Type of workloads to be run on this cluster (GPU or non-GPU)"
97 | type: string
98 | enum: ["gpu", "non-gpu"]
99 |
100 | required:
101 | - region
102 | - vpc-name
103 | - vpc-cidrBlock
104 | - subnet1-public-name
105 | - subnet1-public-cidrBlock
106 | - subnet1-public-availabilityZone
107 | - subnet2-public-name
108 | - subnet2-public-cidrBlock
109 | - subnet2-public-availabilityZone
110 | - subnet1-private-name
111 | - subnet1-private-cidrBlock
112 | - subnet1-private-availabilityZone
113 | - subnet2-private-name
114 | - subnet2-private-cidrBlock
115 | - subnet2-private-availabilityZone
116 | - k8s-version
117 | - workers-size
118 | - workload-type
119 | - cluster-role
120 | - workernode-role
121 | required:
122 | - parameters
123 |
--------------------------------------------------------------------------------
/deploy/crossplane-aws-provider/sealed-secrets-controller.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: Role
4 | metadata:
5 | labels:
6 | name: sealed-secrets-service-proxier
7 | name: sealed-secrets-service-proxier
8 | namespace: sealed-secrets
9 | rules:
10 | - apiGroups:
11 | - ""
12 | resourceNames:
13 | - 'http:sealed-secrets-controller:'
14 | - sealed-secrets-controller
15 | resources:
16 | - services/proxy
17 | verbs:
18 | - create
19 | - get
20 | ---
21 | apiVersion: rbac.authorization.k8s.io/v1
22 | kind: Role
23 | metadata:
24 | labels:
25 | name: sealed-secrets-key-admin
26 | name: sealed-secrets-key-admin
27 | namespace: sealed-secrets
28 | rules:
29 | - apiGroups:
30 | - ""
31 | resources:
32 | - secrets
33 | verbs:
34 | - create
35 | - list
36 | ---
37 | apiVersion: v1
38 | kind: Service
39 | metadata:
40 | labels:
41 | name: sealed-secrets-controller
42 | name: sealed-secrets-controller
43 | namespace: sealed-secrets
44 | spec:
45 | ports:
46 | - port: 8080
47 | targetPort: 8080
48 | selector:
49 | name: sealed-secrets-controller
50 | type: ClusterIP
51 | ---
52 | apiVersion: rbac.authorization.k8s.io/v1
53 | kind: RoleBinding
54 | metadata:
55 | labels:
56 | name: sealed-secrets-service-proxier
57 | name: sealed-secrets-service-proxier
58 | namespace: sealed-secrets
59 | roleRef:
60 | apiGroup: rbac.authorization.k8s.io
61 | kind: Role
62 | name: sealed-secrets-service-proxier
63 | subjects:
64 | - apiGroup: rbac.authorization.k8s.io
65 | kind: Group
66 | name: system:authenticated
67 | ---
68 | apiVersion: apiextensions.k8s.io/v1
69 | kind: CustomResourceDefinition
70 | metadata:
71 | name: sealedsecrets.bitnami.com
72 | spec:
73 | group: bitnami.com
74 | names:
75 | kind: SealedSecret
76 | listKind: SealedSecretList
77 | plural: sealedsecrets
78 | singular: sealedsecret
79 | scope: Namespaced
80 | versions:
81 | - name: v1alpha1
82 | schema:
83 | openAPIV3Schema:
84 | properties:
85 | spec:
86 | type: object
87 | x-kubernetes-preserve-unknown-fields: true
88 | status:
89 | x-kubernetes-preserve-unknown-fields: true
90 | type: object
91 | served: true
92 | storage: true
93 | subresources:
94 | status: {}
95 | ---
96 | apiVersion: rbac.authorization.k8s.io/v1
97 | kind: RoleBinding
98 | metadata:
99 | labels:
100 | name: sealed-secrets-controller
101 | name: sealed-secrets-controller
102 | namespace: sealed-secrets
103 | roleRef:
104 | apiGroup: rbac.authorization.k8s.io
105 | kind: Role
106 | name: sealed-secrets-key-admin
107 | subjects:
108 | - kind: ServiceAccount
109 | name: sealed-secrets-controller
110 | namespace: sealed-secrets
111 | ---
112 | apiVersion: rbac.authorization.k8s.io/v1
113 | kind: ClusterRoleBinding
114 | metadata:
115 | labels:
116 | name: sealed-secrets-controller
117 | name: sealed-secrets-controller
118 | roleRef:
119 | apiGroup: rbac.authorization.k8s.io
120 | kind: ClusterRole
121 | name: secrets-unsealer
122 | subjects:
123 | - kind: ServiceAccount
124 | name: sealed-secrets-controller
125 | namespace: sealed-secrets
126 | ---
127 | apiVersion: rbac.authorization.k8s.io/v1
128 | kind: ClusterRole
129 | metadata:
130 | labels:
131 | name: secrets-unsealer
132 | name: secrets-unsealer
133 | rules:
134 | - apiGroups:
135 | - bitnami.com
136 | resources:
137 | - sealedsecrets
138 | verbs:
139 | - get
140 | - list
141 | - watch
142 | - apiGroups:
143 | - bitnami.com
144 | resources:
145 | - sealedsecrets/status
146 | verbs:
147 | - update
148 | - apiGroups:
149 | - ""
150 | resources:
151 | - secrets
152 | verbs:
153 | - get
154 | - create
155 | - update
156 | - delete
157 | - apiGroups:
158 | - ""
159 | resources:
160 | - events
161 | verbs:
162 | - create
163 | - patch
164 | ---
165 | apiVersion: v1
166 | kind: ServiceAccount
167 | metadata:
168 | labels:
169 | name: sealed-secrets-controller
170 | name: sealed-secrets-controller
171 | namespace: sealed-secrets
172 | ---
173 | apiVersion: apps/v1
174 | kind: Deployment
175 | metadata:
176 | labels:
177 | name: sealed-secrets-controller
178 | name: sealed-secrets-controller
179 | namespace: sealed-secrets
180 | spec:
181 | minReadySeconds: 30
182 | replicas: 1
183 | revisionHistoryLimit: 10
184 | selector:
185 | matchLabels:
186 | name: sealed-secrets-controller
187 | strategy:
188 | rollingUpdate:
189 | maxSurge: 25%
190 | maxUnavailable: 25%
191 | type: RollingUpdate
192 | template:
193 | metadata:
194 | annotations: {}
195 | labels:
196 | name: sealed-secrets-controller
197 | spec:
198 | containers:
199 | - args: []
200 | command:
201 | - controller
202 | env: []
203 | image: quay.io/bitnami/sealed-secrets-controller:v0.16.0
204 | imagePullPolicy: Always
205 | livenessProbe:
206 | httpGet:
207 | path: /healthz
208 | port: http
209 | name: sealed-secrets-controller
210 | ports:
211 | - containerPort: 8080
212 | name: http
213 | readinessProbe:
214 | httpGet:
215 | path: /healthz
216 | port: http
217 | securityContext:
218 | readOnlyRootFilesystem: true
219 | runAsNonRoot: true
220 | runAsUser: 1001
221 | stdin: false
222 | tty: false
223 | volumeMounts:
224 | - mountPath: /tmp
225 | name: tmp
226 | imagePullSecrets: []
227 | initContainers: []
228 | securityContext:
229 | fsGroup: 65534
230 | serviceAccountName: sealed-secrets-controller
231 | terminationGracePeriodSeconds: 30
232 | volumes:
233 | - emptyDir: {}
234 | name: tmp
235 |
--------------------------------------------------------------------------------
/crossplane.sh:
--------------------------------------------------------------------------------
1 | ##!/bin/bash
2 |
3 | #
4 | # The Crossplane CLI extends kubectl with functionality to build, push, and install Crossplane packages
5 | #
6 | curl -sL https://raw.githubusercontent.com/crossplane/crossplane/release-1.0/install.sh | sh
7 | sudo mv kubectl-crossplane /usr/local/bin
8 |
9 | #
10 | # Install Crossplane on your "management" cluster
11 | #
12 | kubectl create namespace crossplane-system
13 | helm repo add crossplane-stable https://charts.crossplane.io/stable
14 | helm repo update
15 |
16 | #
17 | # Install Crossplane core components using Helm chart
18 | #
19 | helm install crossplane --namespace crossplane-system crossplane-stable/crossplane --version 1.4.1
20 |
21 | #
22 | # Providers extend Crossplane with custom resources that can be used to declaratively configure a system.
23 | # In order to provision a resource, a CRD needs to be registered in your Kubernetes cluster and its controller should be watching the Custom Resources those CRDs define.
24 | # Crossplane provider packages contain many CRDs and their controllers.
25 | # The 'provider-aws' package is the Crossplane infrastructure provider for AWS. This package contains the followig:
26 | # 1. Custom Resource Definitions (CRDs) that model AWS infrastructure and services (e.g. RDS, S3, EKS clusters, etc.) These are called 'managed resources'
27 | # 2. Controllers to provision these resources in AWS based on the users desired state captured in CRDs they create
28 | # 3. Implementations of Crossplane's portable resource abstractions, enabling AWS resources to fulfill a user's general need for cloud services
29 | #
30 | # The core Crossplane controller can install provider controllers and CRDs for you through its own provider packaging mechanism, which is triggered by the application of a 'Provider' resource.
31 | # In order to request installation of the provider-aws package, apply the 'aws-provider.yaml' resource to the cluster where Crossplane is running.
32 | # Providers can be installed using the 'kubectl crossplane install provider' command as well.
33 | # Check out documentation on installing providers: https://crossplane.io/docs/v1.3/concepts/providers.html
34 | #
35 | cd crossplane-imperative
36 | kubectl apply -f aws-provider.yaml
37 |
38 | #
39 | # In order to authenticate with the external provider API such as AWS, the provider controllers need to have access to credentials.
40 | # It could be an IAM User for AWS
41 | # An AWS user with Administrative privileges is needed to enable Crossplane to create the required resources
42 | # We wil have to first create a configuration file, secrets.conf, with credeantials of an AWS account in the following format.
43 | #
44 | # [default]
45 | # aws_access_key_id = XXXXXXXXXXXXXX
46 | # aws_secret_access_key = XXXXXXXXXXXXXX
47 | #
48 | # Then using that file, a Kubernetes Secret is created as follows
49 | #
50 | kubectl -n crossplane-system create secret generic aws-credentials --from-file=credentials=./secrets.conf
51 |
52 | #
53 | # Create a ProviderConfig resource, referencing the above Secret
54 | #
55 | kubectl apply -f aws-providerconfig.yaml
56 |
57 |
58 | #
59 | # Crossplane goes beyond simply modelling infrastructure primitives as ‘managed resources’.
60 | # Composition is a concept that allows platform builders to define new custom resources that are composed of managed resources, like an RDS instance
61 | # Crossplane calls these “composite resources” (XRs).
62 | # Composition can be used to build a catalogue of custom resources and classes of configuration that fit the needs and opinions of your organisation.
63 | # Crossplane uses two special resources to define and configure these new composite resources:
64 | # A CompositeResourceDefinition (XRD) defines a new kind of composite resource, including its schema. An XRD may optionally offer a claim (XRC).
65 | # A Composition specifies which managed resources a composite resource will be composed of, and how they should be configured.
66 | # You can create multiple Composition options for each composite resource.
67 | # Check out the composition documentation: https://crossplane.io/docs/v1.3/concepts/composition.html
68 | #
69 | # CompositeResourceDefinitions (XRDs) and Compositions may be packaged and installed as a configuration.
70 | # A configuration is a package of composition configuration that can easily be installed to Crossplane by creating a declarative 'Configuration' resource, or by using 'kubectl crossplane install configuration'.
71 | # Check out the documentation on creating configuration: https://crossplane.io/docs/v1.3/getting-started/create-configuration.html
72 | #
73 |
74 | #
75 | # Create a package for EKS cluster creation
76 | # This package will help create a new VPC with 2 private/public subnets, IGW, NATGW and the EKS cluster with managed node group
77 | # Push this package to a repository in an image registry
78 | #
79 | cd eks-configuration
80 | kubectl crossplane build configuration
81 | kubectl crossplane push configuration public.ecr.aws/awsvijisarathy/crossplane-eks-composition:6.0.0
82 |
83 |
84 | #
85 | # Install the package to a cluster
86 | #
87 | kubectl crossplane install configuration public.ecr.aws/awsvijisarathy/crossplane-eks-composition:2.0.0
88 |
89 | #
90 | # Check if the package and the XRDs defined in it were installed properly
91 | #
92 | kubectl get Configuration crossplane-eks-composition
93 | kubectl get CompositeResourceDefinition eksclusters.eks.sarathy.io
94 |
95 | #
96 | # Create an EKS cluster and a nodegroup using an XR
97 | #
98 | kubectl apply -f eks-cluster-xr.yaml
99 |
100 | #
101 | # Here are a set of CLI commands to look at various resources
102 | #
103 | kubectl get crossplane # get all resources related to Crossplane.
104 | kubectl get managed # get all resources that represent a unit of external infrastructure such as RDSInstance.
105 | kubectl get composite # get all resources that represent an XR
106 |
107 |
108 | #
109 | # Cleanup
110 | #
111 | kubectl delete -f eks-cluster-xr.yaml
112 | kubectl delete -f aws-providerconfig.yaml
113 | kubectl delete -f aws-provider.yaml
114 | helm uninstall crossplane --namespace crossplane-system
115 |
116 |
--------------------------------------------------------------------------------
/Grafana-Metrics-Dashboard.json:
--------------------------------------------------------------------------------
1 | {
2 | "annotations": {
3 | "list": [
4 | {
5 | "builtIn": 1,
6 | "datasource": "-- Grafana --",
7 | "enable": true,
8 | "hide": true,
9 | "iconColor": "rgba(0, 211, 255, 1)",
10 | "name": "Annotations & Alerts",
11 | "target": {
12 | "limit": 100,
13 | "matchAny": false,
14 | "tags": [],
15 | "type": "dashboard"
16 | },
17 | "type": "dashboard"
18 | }
19 | ]
20 | },
21 | "editable": true,
22 | "fiscalYearStartMonth": 0,
23 | "gnetId": null,
24 | "graphTooltip": 0,
25 | "id": 34,
26 | "links": [],
27 | "liveNow": false,
28 | "panels": [
29 | {
30 | "aliasColors": {},
31 | "bars": false,
32 | "dashLength": 10,
33 | "dashes": false,
34 | "datasource": "Prometheus-West",
35 | "fill": 1,
36 | "fillGradient": 0,
37 | "gridPos": {
38 | "h": 9,
39 | "w": 12,
40 | "x": 0,
41 | "y": 0
42 | },
43 | "hiddenSeries": false,
44 | "id": 2,
45 | "legend": {
46 | "alignAsTable": true,
47 | "avg": false,
48 | "current": false,
49 | "max": false,
50 | "min": false,
51 | "show": true,
52 | "total": false,
53 | "values": false
54 | },
55 | "lines": true,
56 | "linewidth": 1,
57 | "nullPointMode": "null",
58 | "options": {
59 | "alertThreshold": true
60 | },
61 | "percentage": false,
62 | "pluginVersion": "8.2.5",
63 | "pointradius": 2,
64 | "points": false,
65 | "renderer": "flot",
66 | "seriesOverrides": [],
67 | "spaceLength": 10,
68 | "stack": false,
69 | "steppedLine": false,
70 | "targets": [
71 | {
72 | "exemplar": true,
73 | "expr": "sum(rate(http_requests_total[5m]))",
74 | "interval": "",
75 | "legendFormat": "Requests per Second",
76 | "refId": "A"
77 | }
78 | ],
79 | "thresholds": [],
80 | "timeFrom": null,
81 | "timeRegions": [],
82 | "timeShift": null,
83 | "title": "HTTP Request Rate",
84 | "tooltip": {
85 | "shared": true,
86 | "sort": 0,
87 | "value_type": "individual"
88 | },
89 | "type": "graph",
90 | "xaxis": {
91 | "buckets": null,
92 | "mode": "time",
93 | "name": null,
94 | "show": true,
95 | "values": []
96 | },
97 | "yaxes": [
98 | {
99 | "$$hashKey": "object:753",
100 | "format": "short",
101 | "label": null,
102 | "logBase": 1,
103 | "max": null,
104 | "min": null,
105 | "show": true
106 | },
107 | {
108 | "$$hashKey": "object:754",
109 | "format": "short",
110 | "label": null,
111 | "logBase": 1,
112 | "max": null,
113 | "min": null,
114 | "show": true
115 | }
116 | ],
117 | "yaxis": {
118 | "align": false,
119 | "alignLevel": null
120 | }
121 | },
122 | {
123 | "aliasColors": {},
124 | "bars": false,
125 | "dashLength": 10,
126 | "dashes": false,
127 | "datasource": "Prometheus-West",
128 | "fill": 1,
129 | "fillGradient": 0,
130 | "gridPos": {
131 | "h": 8,
132 | "w": 12,
133 | "x": 0,
134 | "y": 9
135 | },
136 | "hiddenSeries": false,
137 | "id": 6,
138 | "legend": {
139 | "avg": false,
140 | "current": false,
141 | "max": false,
142 | "min": false,
143 | "show": true,
144 | "total": false,
145 | "values": false
146 | },
147 | "lines": true,
148 | "linewidth": 1,
149 | "nullPointMode": "null",
150 | "options": {
151 | "alertThreshold": true
152 | },
153 | "percentage": false,
154 | "pluginVersion": "8.2.5",
155 | "pointradius": 2,
156 | "points": false,
157 | "renderer": "flot",
158 | "seriesOverrides": [],
159 | "spaceLength": 10,
160 | "stack": false,
161 | "steppedLine": false,
162 | "targets": [
163 | {
164 | "exemplar": true,
165 | "expr": "sum(rate(request_duration_milliseconds_sum[5m]))/sum(rate(request_duration_milliseconds_count[5m]))",
166 | "hide": false,
167 | "interval": "",
168 | "legendFormat": "Average Response Latency",
169 | "refId": "B"
170 | }
171 | ],
172 | "thresholds": [],
173 | "timeFrom": null,
174 | "timeRegions": [],
175 | "timeShift": null,
176 | "title": "Response Latency",
177 | "tooltip": {
178 | "shared": true,
179 | "sort": 0,
180 | "value_type": "individual"
181 | },
182 | "type": "graph",
183 | "xaxis": {
184 | "buckets": null,
185 | "mode": "time",
186 | "name": null,
187 | "show": true,
188 | "values": []
189 | },
190 | "yaxes": [
191 | {
192 | "$$hashKey": "object:335",
193 | "format": "short",
194 | "label": null,
195 | "logBase": 1,
196 | "max": null,
197 | "min": null,
198 | "show": true
199 | },
200 | {
201 | "$$hashKey": "object:336",
202 | "format": "short",
203 | "label": null,
204 | "logBase": 1,
205 | "max": null,
206 | "min": null,
207 | "show": true
208 | }
209 | ],
210 | "yaxis": {
211 | "align": false,
212 | "alignLevel": null
213 | }
214 | }
215 | ],
216 | "refresh": false,
217 | "schemaVersion": 32,
218 | "style": "dark",
219 | "tags": [],
220 | "templating": {
221 | "list": []
222 | },
223 | "time": {
224 | "from": "now-15m",
225 | "to": "now"
226 | },
227 | "timepicker": {},
228 | "timezone": "",
229 | "title": "Grafana Metrics Dashboard",
230 | "uid": "5wqWkSR7k",
231 | "version": 4
232 | }
--------------------------------------------------------------------------------
/crossplane-imperative/eks-configuration/composition.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apiextensions.crossplane.io/v1
3 | kind: Composition
4 | metadata:
5 | name: amazon-eks-cluster
6 | labels:
7 | provider: aws
8 | service: eks
9 | compute: managed
10 | spec:
11 | writeConnectionSecretsToNamespace: crossplane-system
12 | compositeTypeRef:
13 | apiVersion: eks.sarathy.io/v1beta1
14 | kind: EKSCluster
15 |
16 | patchSets:
17 | - name: common-parameters
18 | patches:
19 | - fromFieldPath: "spec.parameters.region"
20 | toFieldPath: "spec.forProvider.region"
21 |
22 | resources:
23 | - name: vpc
24 | base:
25 | apiVersion: ec2.aws.crossplane.io/v1beta1
26 | kind: VPC
27 | spec:
28 | forProvider:
29 | enableDnsSupport: true
30 | enableDnsHostNames: true
31 | tags:
32 | - key: Name
33 | patches:
34 | - type: PatchSet
35 | patchSetName: common-parameters
36 | - fromFieldPath: spec.parameters.vpc-cidrBlock
37 | toFieldPath: spec.forProvider.cidrBlock
38 | - fromFieldPath: spec.parameters.vpc-name
39 | toFieldPath: spec.forProvider.tags[0].value
40 |
41 | - name: internetgateway
42 | base:
43 | apiVersion: ec2.aws.crossplane.io/v1beta1
44 | kind: InternetGateway
45 | metadata:
46 | labels:
47 | type: igw
48 | spec:
49 | forProvider:
50 | vpcIdSelector:
51 | matchControllerRef: true
52 | tags:
53 | - key: Name
54 | patches:
55 | - type: PatchSet
56 | patchSetName: common-parameters
57 | - type: CombineFromComposite
58 | combine:
59 | variables:
60 | - fromFieldPath: spec.parameters.vpc-name
61 | strategy: string
62 | string:
63 | fmt: "%s-igw"
64 | toFieldPath: spec.forProvider.tags[0].value
65 | policy:
66 | fromFieldPath: Required
67 |
68 | - name: subnet-public-1
69 | base:
70 | apiVersion: ec2.aws.crossplane.io/v1beta1
71 | kind: Subnet
72 | metadata:
73 | labels:
74 | type: subnet
75 | visibility: public
76 | spec:
77 | forProvider:
78 | mapPublicIpOnLaunch: true
79 | vpcIdSelector:
80 | matchControllerRef: true
81 | tags:
82 | - key: Name
83 | - key: kubernetes.io/role/elb
84 | value: "1"
85 | patches:
86 | - type: CombineFromComposite
87 | combine:
88 | variables:
89 | - fromFieldPath: spec.parameters.vpc-name
90 | - fromFieldPath: spec.parameters.subnet1-public-name
91 | strategy: string
92 | string:
93 | fmt: "%s-%s"
94 | toFieldPath: spec.forProvider.tags[0].value
95 | policy:
96 | fromFieldPath: Required
97 | - type: PatchSet
98 | patchSetName: common-parameters
99 | - fromFieldPath: spec.parameters.subnet1-public-cidrBlock
100 | toFieldPath: spec.forProvider.cidrBlock
101 | - fromFieldPath: spec.parameters.subnet1-public-availabilityZone
102 | toFieldPath: spec.forProvider.availabilityZone
103 | - fromFieldPath: spec.parameters.subnet1-public-availabilityZone
104 | toFieldPath: metadata.labels.zone
105 |
106 | - name: subnet-public-2
107 | base:
108 | apiVersion: ec2.aws.crossplane.io/v1beta1
109 | kind: Subnet
110 | metadata:
111 | labels:
112 | type: subnet
113 | visibility: public
114 | spec:
115 | forProvider:
116 | mapPublicIpOnLaunch: true
117 | vpcIdSelector:
118 | matchControllerRef: true
119 | tags:
120 | - key: Name
121 | - key: kubernetes.io/role/elb
122 | value: "1"
123 | patches:
124 | - type: CombineFromComposite
125 | combine:
126 | variables:
127 | - fromFieldPath: spec.parameters.vpc-name
128 | - fromFieldPath: spec.parameters.subnet2-public-name
129 | strategy: string
130 | string:
131 | fmt: "%s-%s"
132 | toFieldPath: spec.forProvider.tags[0].value
133 | policy:
134 | fromFieldPath: Required
135 | - type: PatchSet
136 | patchSetName: common-parameters
137 | - fromFieldPath: spec.parameters.subnet2-public-cidrBlock
138 | toFieldPath: spec.forProvider.cidrBlock
139 | - fromFieldPath: spec.parameters.subnet2-public-availabilityZone
140 | toFieldPath: spec.forProvider.availabilityZone
141 | - fromFieldPath: spec.parameters.subnet2-public-availabilityZone
142 | toFieldPath: metadata.labels.zone
143 |
144 | - name: subnet-private-1
145 | base:
146 | apiVersion: ec2.aws.crossplane.io/v1beta1
147 | kind: Subnet
148 | metadata:
149 | labels:
150 | type: subnet
151 | visibility: private
152 | spec:
153 | forProvider:
154 | mapPublicIpOnLaunch: false
155 | vpcIdSelector:
156 | matchControllerRef: true
157 | tags:
158 | - key: Name
159 | - key: kubernetes.io/role/internal-elb
160 | value: "1"
161 | patches:
162 | - type: CombineFromComposite
163 | combine:
164 | variables:
165 | - fromFieldPath: spec.parameters.vpc-name
166 | - fromFieldPath: spec.parameters.subnet1-private-name
167 | strategy: string
168 | string:
169 | fmt: "%s-%s"
170 | toFieldPath: spec.forProvider.tags[0].value
171 | policy:
172 | fromFieldPath: Required
173 | - type: PatchSet
174 | patchSetName: common-parameters
175 | - fromFieldPath: spec.parameters.subnet1-private-cidrBlock
176 | toFieldPath: spec.forProvider.cidrBlock
177 | - fromFieldPath: spec.parameters.subnet1-private-availabilityZone
178 | toFieldPath: spec.forProvider.availabilityZone
179 | - fromFieldPath: spec.parameters.subnet1-private-availabilityZone
180 | toFieldPath: metadata.labels.zone
181 |
182 | - name: subnet-private-2
183 | base:
184 | apiVersion: ec2.aws.crossplane.io/v1beta1
185 | kind: Subnet
186 | metadata:
187 | labels:
188 | type: subnet
189 | visibility: private
190 | spec:
191 | forProvider:
192 | mapPublicIpOnLaunch: false
193 | vpcIdSelector:
194 | matchControllerRef: true
195 | tags:
196 | - key: Name
197 | - key: kubernetes.io/role/internal-elb
198 | value: "1"
199 | patches:
200 | - type: CombineFromComposite
201 | combine:
202 | variables:
203 | - fromFieldPath: spec.parameters.vpc-name
204 | - fromFieldPath: spec.parameters.subnet2-private-name
205 | strategy: string
206 | string:
207 | fmt: "%s-%s"
208 | toFieldPath: spec.forProvider.tags[0].value
209 | policy:
210 | fromFieldPath: Required
211 | - type: PatchSet
212 | patchSetName: common-parameters
213 | - fromFieldPath: spec.parameters.subnet2-private-cidrBlock
214 | toFieldPath: spec.forProvider.cidrBlock
215 | - fromFieldPath: spec.parameters.subnet2-private-availabilityZone
216 | toFieldPath: spec.forProvider.availabilityZone
217 | - fromFieldPath: spec.parameters.subnet2-private-availabilityZone
218 | toFieldPath: metadata.labels.zone
219 |
220 | - name: elastic-ip-1
221 | base:
222 | apiVersion: ec2.aws.crossplane.io/v1beta1
223 | kind: Address
224 | metadata:
225 | labels:
226 | type: eip-1
227 | spec:
228 | forProvider:
229 | domain: vpc
230 | patches:
231 | - type: PatchSet
232 | patchSetName: common-parameters
233 |
234 | - name: elastic-ip-2
235 | base:
236 | apiVersion: ec2.aws.crossplane.io/v1beta1
237 | kind: Address
238 | metadata:
239 | labels:
240 | type: eip-2
241 | spec:
242 | forProvider:
243 | domain: vpc
244 | patches:
245 | - type: PatchSet
246 | patchSetName: common-parameters
247 |
248 | - name: natgateway-1
249 | base:
250 | apiVersion: ec2.aws.crossplane.io/v1beta1
251 | kind: NATGateway
252 | metadata:
253 | labels:
254 | type: natgw-1
255 | spec:
256 | forProvider:
257 | allocationIdSelector:
258 | matchLabels:
259 | type: eip-1
260 | vpcIdSelector:
261 | matchControllerRef: true
262 | subnetIdSelector:
263 | matchLabels:
264 | type: subnet
265 | visibility: public
266 | tags:
267 | - key: Name
268 | patches:
269 | - type: CombineFromComposite
270 | combine:
271 | variables:
272 | - fromFieldPath: spec.parameters.vpc-name
273 | strategy: string
274 | string:
275 | fmt: "%s-nat-gateway-1"
276 | toFieldPath: spec.forProvider.tags[0].value
277 | policy:
278 | fromFieldPath: Required
279 | - type: PatchSet
280 | patchSetName: common-parameters
281 | - fromFieldPath: spec.parameters.subnet1-public-availabilityZone
282 | toFieldPath: spec.forProvider.subnetIdSelector.matchLabels.zone
283 |
284 | - name: natgateway-2
285 | base:
286 | apiVersion: ec2.aws.crossplane.io/v1beta1
287 | kind: NATGateway
288 | metadata:
289 | labels:
290 | type: natgw-2
291 | spec:
292 | forProvider:
293 | allocationIdSelector:
294 | matchLabels:
295 | type: eip-2
296 | vpcIdSelector:
297 | matchControllerRef: true
298 | subnetIdSelector:
299 | matchLabels:
300 | type: subnet
301 | visibility: public
302 | tags:
303 | - key: Name
304 | patches:
305 | - type: CombineFromComposite
306 | combine:
307 | variables:
308 | - fromFieldPath: spec.parameters.vpc-name
309 | strategy: string
310 | string:
311 | fmt: "%s-nat-gateway-2"
312 | toFieldPath: spec.forProvider.tags[0].value
313 | policy:
314 | fromFieldPath: Required
315 | - type: PatchSet
316 | patchSetName: common-parameters
317 | - fromFieldPath: spec.parameters.subnet2-public-availabilityZone
318 | toFieldPath: spec.forProvider.subnetIdSelector.matchLabels.zone
319 |
320 | - name: routetable-public
321 | base:
322 | apiVersion: ec2.aws.crossplane.io/v1beta1
323 | kind: RouteTable
324 | spec:
325 | forProvider:
326 | vpcIdSelector:
327 | matchControllerRef: true
328 | routes:
329 | - destinationCidrBlock: 0.0.0.0/0
330 | gatewayIdSelector:
331 | matchLabels:
332 | type: igw
333 | associations:
334 | - subnetIdSelector:
335 | matchLabels:
336 | type: subnet
337 | visibility: public
338 | - subnetIdSelector:
339 | matchLabels:
340 | type: subnet
341 | visibility: public
342 | tags:
343 | - key: Name
344 | patches:
345 | - type: CombineFromComposite
346 | combine:
347 | variables:
348 | - fromFieldPath: spec.parameters.vpc-name
349 | strategy: string
350 | string:
351 | fmt: "%s-public-route-table"
352 | toFieldPath: spec.forProvider.tags[0].value
353 | policy:
354 | fromFieldPath: Required
355 | - type: PatchSet
356 | patchSetName: common-parameters
357 | - fromFieldPath: spec.parameters.subnet1-public-availabilityZone
358 | toFieldPath: spec.forProvider.associations[0].subnetIdSelector.matchLabels.zone
359 | - fromFieldPath: spec.parameters.subnet2-public-availabilityZone
360 | toFieldPath: spec.forProvider.associations[1].subnetIdSelector.matchLabels.zone
361 |
362 | - name: routetable-private-1
363 | base:
364 | apiVersion: ec2.aws.crossplane.io/v1beta1
365 | kind: RouteTable
366 | spec:
367 | forProvider:
368 | vpcIdSelector:
369 | matchControllerRef: true
370 | routes:
371 | - destinationCidrBlock: 0.0.0.0/0
372 | natGatewayIdSelector:
373 | matchLabels:
374 | type: natgw-1
375 | associations:
376 | - subnetIdSelector:
377 | matchLabels:
378 | type: subnet
379 | visibility: private
380 | tags:
381 | - key: Name
382 | patches:
383 | - type: CombineFromComposite
384 | combine:
385 | variables:
386 | - fromFieldPath: spec.parameters.vpc-name
387 | strategy: string
388 | string:
389 | fmt: "%s-private-route-table-1"
390 | toFieldPath: spec.forProvider.tags[0].value
391 | policy:
392 | fromFieldPath: Required
393 | - type: PatchSet
394 | patchSetName: common-parameters
395 | - fromFieldPath: spec.parameters.subnet1-public-availabilityZone
396 | toFieldPath: spec.forProvider.associations[0].subnetIdSelector.matchLabels.zone
397 |
398 | - name: routetable-private-2
399 | base:
400 | apiVersion: ec2.aws.crossplane.io/v1beta1
401 | kind: RouteTable
402 | spec:
403 | forProvider:
404 | vpcIdSelector:
405 | matchControllerRef: true
406 | routes:
407 | - destinationCidrBlock: 0.0.0.0/0
408 | natGatewayIdSelector:
409 | matchLabels:
410 | type: natgw-2
411 | associations:
412 | - subnetIdSelector:
413 | matchLabels:
414 | type: subnet
415 | visibility: private
416 | tags:
417 | - key: Name
418 | patches:
419 | - type: CombineFromComposite
420 | combine:
421 | variables:
422 | - fromFieldPath: spec.parameters.vpc-name
423 | strategy: string
424 | string:
425 | fmt: "%s-private-route-table-2"
426 | toFieldPath: spec.forProvider.tags[0].value
427 | policy:
428 | fromFieldPath: Required
429 | - type: PatchSet
430 | patchSetName: common-parameters
431 | - fromFieldPath: spec.parameters.subnet2-public-availabilityZone
432 | toFieldPath: spec.forProvider.associations[0].subnetIdSelector.matchLabels.zone
433 |
434 | - name: eks-cluster
435 | base:
436 | apiVersion: eks.aws.crossplane.io/v1beta1
437 | kind: Cluster
438 | spec:
439 | forProvider:
440 | resourcesVpcConfig:
441 | endpointPrivateAccess: false
442 | endpointPublicAccess: true
443 | subnetIdSelector:
444 | matchLabels:
445 | type: subnet
446 | writeConnectionSecretToRef:
447 | namespace: crossplane-system
448 | patches:
449 | - type: PatchSet
450 | patchSetName: common-parameters
451 | - fromFieldPath: "spec.parameters.k8s-version"
452 | toFieldPath: "spec.forProvider.version"
453 | - fromFieldPath: "metadata.uid"
454 | toFieldPath: "spec.writeConnectionSecretToRef.name"
455 | transforms:
456 | - type: string
457 | string:
458 | fmt: "%s-ekscluster-connection"
459 | - fromFieldPath: "spec.parameters.cluster-role"
460 | toFieldPath: "spec.forProvider.roleArn"
461 | connectionDetails:
462 | - name: cluster-ca
463 | fromConnectionSecretKey: clusterCA
464 | - name: apiserver-endpoint
465 | fromConnectionSecretKey: endpoint
466 | - name: value
467 | fromConnectionSecretKey: kubeconfig
468 |
469 | - name: eks-nodegroup
470 | base:
471 | apiVersion: eks.aws.crossplane.io/v1alpha1
472 | kind: NodeGroup
473 | spec:
474 | forProvider:
475 | instanceTypes:
476 | - m5.large
477 | scalingConfig:
478 | minSize: 1
479 | subnetSelector:
480 | matchLabels:
481 | type: subnet
482 | visibility: private
483 | clusterNameSelector:
484 | matchControllerRef: true
485 | patches:
486 | - type: PatchSet
487 | patchSetName: common-parameters
488 | - fromFieldPath: "spec.parameters.workers-size"
489 | toFieldPath: "spec.forProvider.scalingConfig.desiredSize"
490 | - fromFieldPath: "spec.parameters.workers-size"
491 | toFieldPath: "spec.forProvider.scalingConfig.maxSize"
492 | - fromFieldPath: "spec.parameters.workload-type"
493 | toFieldPath: "spec.forProvider.amiType"
494 | transforms:
495 | - type: map
496 | map:
497 | gpu: AL2_x86_64_GPU
498 | non-gpu: AL2_x86_64
499 | - fromFieldPath: "spec.parameters.workernode-role"
500 | toFieldPath: "spec.forProvider.nodeRole"
--------------------------------------------------------------------------------