diff --git a/README.md b/README.md index f057d1da..1d9146e5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,11 @@ Run Terraform: cd terraform terraform init -upgrade # the gitops_addons_org needs to be in the git format to use the SSH key until the repo is private -terraform apply -var gitops_addons_org=git@github.com:Azure-Samples +terraform apply -var infrastructure_provider=crossplane \ + -var gitops_addons_org=git@github.com:Azure-Samples \ + -var gitops_workload_org=git@github.com:Azure-Samples \ + -var service_principal_client_id=xxxxxxxx \ + -var service_principal_client_secret=xxxxxxxxxx ``` Get the initial admin password and the IP address of the ArgoCD web interface. diff --git a/gitops/bootstrap/workloads/workload-clusters-app.yaml b/gitops/bootstrap/workloads/workload-clusters-app.yaml new file mode 100644 index 00000000..1b5d737f --- /dev/null +++ b/gitops/bootstrap/workloads/workload-clusters-app.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: ApplicationSet +metadata: + name: clusters + namespace: argocd +spec: + syncPolicy: + preserveResourcesOnDeletion: true + generators: + - clusters: + selector: + matchLabels: + environment: control-plane + template: + metadata: + name: clusters + spec: + project: default + source: + repoURL: '{{metadata.annotations.workload_repo_url}}' + targetRevision: '{{metadata.annotations.workload_repo_revision}}' + path: 'gitops/clusters/{{metadata.annotations.infrastructure_provider}}' + destination: + name: '{{name}}' + namespace: workload + syncPolicy: + retry: + limit: 10 + automated: {} + syncOptions: + - CreateNamespace=true \ No newline at end of file diff --git a/gitops/clusters/capz/.keep b/gitops/clusters/capz/.keep new file mode 100644 index 00000000..e69de29b diff --git a/gitops/clusters/crossplane/base/cluster/aks-composite-resource-definition.yaml b/gitops/clusters/crossplane/base/cluster/aks-composite-resource-definition.yaml new file mode 100644 index 00000000..74e77de7 --- /dev/null +++ b/gitops/clusters/crossplane/base/cluster/aks-composite-resource-definition.yaml @@ -0,0 +1,346 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: CompositeResourceDefinition +metadata: + name: xaksclusters.kubernetes.example.com + annotations: + argocd.argoproj.io/sync-wave: "1" + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + connectionSecretKeys: + - kubeconfig + group: kubernetes.example.com + names: + kind: XAksCluster + plural: xaksclusters + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + location: + type: string + description: specifies the location of the Azure resources + aks: + type: object + properties: + defaultNodePool: + type: object + properties: + name: + type: string + description: specifies the name of the node pool + default: default + maxCount: + type: integer + description: specifies the maximum number of nodes in the node pool + default: 20 + minCount: + type: integer + description: specifies the minimum number of nodes in the node pool + default: 3 + nodeCount: + type: integer + description: specifies the number of nodes in the node pool + default: 3 + vmSize: + type: string + description: specifies the size of the Virtual Machines making up the node pool + default: Standard_F8s_v2 + enableAutoScaling: + type: boolean + description: specifies whether the node pool should automatically adjust the number of nodes + default: true + maxPods: + type: integer + description: specifies the maximum number of pods that can run on a node in the node pool + default: 30 + nodeLabels: + type: object + description: specifies the labels for the nodes in the node pool + additionalProperties: + type: string + nodeTaints: + type: array + description: specifies the taints for the nodes in the node pool + items: + type: string + osDiskSizeGb: + type: integer + description: specifies the size of the OS Disk in GB + default: 128 + osDiskType: + type: string + description: specifies the type of the OS Disk + enum: + - Ephemeral + - Managed + onlyCriticalAddonsEnabled: + type: boolean + description: specifies whether only critical add-ons are enabled + osSku: + type: string + description: specifies the SKU of the OS + enum: + - Ubuntu + - Windows2019 + - Windows2022 + - AzureLinux + type: + type: string + description: specifies the type of the node pool + default: VirtualMachineScaleSets + kubernetesVersion: + type: string + description: specifies the version of Kubernetes + default: 1.28.3 + dnsPrefix: + type: string + description: specifies the DNS prefix to use with the hosted Kubernetes API server FQDN + roleBasedAccessControlEnabled: + type: boolean + description: specifies whether Azure Active Directory Role-Based Access Control is enabled + default: true + azureActiveDirectoryRoleBasedAccessControl: + type: array + description: specifies the Azure Active Directory Role-Based Access Control settings + items: + type: object + properties: + adminGroupObjectIds: + type: array + description: specifies the object IDs of the Azure Active Directory admin groups + items: + type: string + azureRbacEnabled: + type: boolean + description: specifies whether Azure Active Directory Role-Based Access Control is enabled + managed: + type: boolean + description: specifies whether the Azure Active Directory Role-Based Access Control is managed + azurePolicyEnabled: + type: boolean + networkProfile: + type: array + items: + type: object + properties: + dnsServiceIp: + type: string + description: specifies the IP address of the Kubernetes DNS service + default: 172.16.0.10 + serviceCidr: + type: string + description: specifies the IP address range for the services in the Kubernetes cluster + default: 172.16.0.0/16 + networkMode: + type: string + description: specifies the network mode for the Kubernetes cluster + enum: + - transparent + - bridge + networkPlugin: + type: string + description: specifies the network plugin used for the Kubernetes cluster + default: azure + enum: + - azure + - kubenet + - none + networkPluginMode: + type: string + description: specifies the network plugin mode for the Kubernetes cluster + networkPolicy: + type: string + description: specifies the network policy for the Kubernetes cluster + enum: + - azure + - calico + - cilium + outboundType: + type: string + description: specifies the outbound type for the Kubernetes cluster + enum: + - loadBalancer + - managedNATGateway + - userAssignedNATGateway + - userDefinedRouting + identity: + type: array + description: specifies the identity settings for the Kubernetes cluster + items: + type: object + properties: + type: + type: string + description: specifies the type of the identity + enum: + - SystemAssigned + - UserAssigned + identityIds: + type: array + description: specifies the user-assigned identities + items: + type: string + default: + - type: SystemAssigned + localAccountDisabled: + type: boolean + description: specifies whether the local account is disabled + oidcIssuerEnabled: + type: boolean + description: specifies whether the OpenID Connect issuer is enabled + workloadIdentityEnabled: + type: boolean + description: specifies whether the workload identity is enabled + privateClusterEnabled: + type: boolean + description: specifies whether the private cluster is enabled + privateClusterPublicFqdnEnabled: + type: boolean + description: specifies whether the private cluster public FQDN is enabled + workloadAutoscalerProfile: + type: array + items: + type: object + properties: + kedaEnabled: + type: boolean + description: specifies whether the Kubernetes Event-Driven Autoscaler is enabled + verticalPodAutoscalerEnabled: + type: boolean + description: specifies whether the Vertical Pod Autoscaler is enabled + tags: + type: object + description: specifies the tags for the Kubernetes cluster + additionalProperties: + type: string + required: + - defaultNodePool + - networkProfile + userNodePool: + type: object + properties: + name: + type: string + description: specifies the name of the node pool + mode: + type: string + description: specifies the mode of the node pool + enum: + - system + - user + default: user + maxCount: + type: integer + description: specifies the maximum number of nodes in the node pool + default: 20 + minCount: + type: integer + description: specifies the minimum number of nodes in the node pool + default: 3 + nodeCount: + type: integer + description: specifies the number of nodes in the node pool + default: 3 + vmSize: + type: string + description: specifies the size of the Virtual Machines making up the node pool + default: Standard_F8s_v2 + enableAutoScaling: + type: boolean + description: specifies whether the node pool should automatically adjust the number of nodes + default: true + maxPods: + type: integer + description: specifies the maximum number of pods that can run on a node in the node pool + default: 30 + nodeLabels: + type: object + description: specifies the labels for the nodes in the node pool + additionalProperties: + type: string + nodeTaints: + type: array + description: specifies the taints for the nodes in the node pool + items: + type: string + osDiskSizeGb: + type: integer + description: specifies the size of the OS Disk in GB + default: 128 + osDiskType: + type: string + description: specifies the type of the OS Disk + enum: + - Ephemeral + - Managed + osSku: + type: string + description: specifies the SKU of the OS + enum: + - Ubuntu + - Windows2019 + - Windows2022 + - AzureLinux + osType: + type: string + description: specifies the type of the OS + enum: + - Linux + - Windows + required: + - name + subnet: + type: object + properties: + name: + type: string + description: specifies the name of the subnet + privateEndpointNetworkPoliciesEnabled: + type: boolean + description: specifies whether private endpoint network policies are enabled + privateLinkServiceNetworkPoliciesEnabled: + type: boolean + description: specifies whether private link service network policies are enabled + addressPrefixes: + type: array + description: specifies the address prefixes for the subnet + items: + type: string + description: specifies the address prefix for the subnet + required: + - name + - addressPrefixes + virtualNetwork: + type: object + properties: + addressSpace: + type: array + description: specifies the address prefixes for the virtual network + items: + type: string + description: specifies the address prefix for the virtual network + tags: + type: object + description: specifies the tags for the virtual network + additionalProperties: + type: string + required: + - addressSpace + resourceGroup: + type: object + properties: + tags: + type: object + description: specifies the tags for the virtual network + required: + - location + served: true + referenceable: true + claimNames: + kind: AksClusterClaim + plural: aksclusterclaims diff --git a/gitops/clusters/crossplane/base/cluster/aks-composition.yaml b/gitops/clusters/crossplane/base/cluster/aks-composition.yaml new file mode 100644 index 00000000..79a36b5b --- /dev/null +++ b/gitops/clusters/crossplane/base/cluster/aks-composition.yaml @@ -0,0 +1,276 @@ + +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: aks-with-virtual-network + annotations: + argocd.argoproj.io/sync-wave: "2" + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + writeConnectionSecretsToNamespace: crossplane-system + patchSets: + - name: location-patch + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.location + toFieldPath: spec.forProvider.location + - name: metadata-patch + patches: + - type: FromCompositeFieldPath + fromFieldPath: metadata.annotations + toFieldPath: metadata.annotations + resources: + - name: aks-cluster + connectionDetails: + - fromConnectionSecretKey: kubeconfig + base: + apiVersion: containerservice.azure.upbound.io/v1beta1 + kind: KubernetesCluster + spec: + writeConnectionSecretToRef: + name: example-kubeconfig + namespace: crossplane-system + forProvider: + defaultNodePool: + - type: VirtualMachineScaleSets + vnetSubnetIdSelector: + matchControllerRef: true + resourceGroupNameSelector: + matchControllerRef: true + patches: + - type: FromCompositeFieldPath + fromFieldPath: "metadata.uid" + toFieldPath: "spec.writeConnectionSecretToRef.name" + transforms: + - type: string + string: + fmt: "%s-secret" + - type: PatchSet + patchSetName: location-patch + - type: PatchSet + patchSetName: metadata-patch + - type: FromCompositeFieldPath + fromFieldPath: metadata.annotations[crossplane.io/external-name] + toFieldPath: metadata.annotations[crossplane.io/external-name] + transforms: + - type: string + string: + fmt: "%s-aks" + - type: FromCompositeFieldPath + fromFieldPath: metadata.annotations[crossplane.io/external-name] + toFieldPath: spec.forProvider.dnsPrefix + transforms: + - type: string + string: + type: Convert + convert: "ToLower" + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.name + toFieldPath: spec.forProvider.defaultNodePool[0].name + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.maxCount + toFieldPath: spec.forProvider.defaultNodePool[0].maxCount + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.minCount + toFieldPath: spec.forProvider.defaultNodePool[0].minCount + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.nodeCount + toFieldPath: spec.forProvider.defaultNodePool[0].nodeCount + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.vmSize + toFieldPath: spec.forProvider.defaultNodePool[0].vmSize + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.enableAutoScaling + toFieldPath: spec.forProvider.defaultNodePool[0].enableAutoScaling + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.maxPods + toFieldPath: spec.forProvider.defaultNodePool[0].maxPods + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.nodeLabels + toFieldPath: spec.forProvider.defaultNodePool[0].nodeLabels + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.nodeTaints + toFieldPath: spec.forProvider.defaultNodePool[0].nodeTaints + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.osDiskType + toFieldPath: spec.forProvider.defaultNodePool[0].osDiskType + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.onlyCriticalAddonsEnabled + toFieldPath: spec.forProvider.defaultNodePool[0].onlyCriticalAddonsEnabled + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.osSku + toFieldPath: spec.forProvider.defaultNodePool[0].osSku + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.osDiskSizeGb + toFieldPath: spec.forProvider.defaultNodePool[0].osDiskSizeGb + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.defaultNodePool.type + toFieldPath: spec.forProvider.defaultNodePool[0].type + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.kubernetesVersion + toFieldPath: spec.forProvider.kubernetesVersion + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.dnsPrefix + toFieldPath: spec.forProvider.dnsPrefix + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.roleBasedAccessControlEnabled + toFieldPath: spec.forProvider.roleBasedAccessControlEnabled + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.azureActiveDirectoryRoleBasedAccessControl + toFieldPath: spec.forProvider.azureActiveDirectoryRoleBasedAccessControl + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.azurePolicyEnabled + toFieldPath: spec.forProvider.azurePolicyEnabled + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.networkProfile + toFieldPath: spec.forProvider.networkProfile + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.identity + toFieldPath: spec.forProvider.identity + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.localAccountDisabled + toFieldPath: spec.forProvider.localAccountDisabled + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.oidcIssuerEnabled + toFieldPath: spec.forProvider.oidcIssuerEnabled + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.workloadIdentityEnabled + toFieldPath: spec.forProvider.workloadIdentityEnabled + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.privateClusterEnabled + toFieldPath: spec.forProvider.privateClusterEnabled + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.privateClusterPublicFqdnEnabled + toFieldPath: spec.forProvider.privateClusterPublicFqdnEnabled + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.workloadAutoscalerProfile + toFieldPath: spec.forProvider.workloadAutoscalerProfile + - type: FromCompositeFieldPath + fromFieldPath: spec.aks.tags + toFieldPath: spec.forProvider.tags + - name: user-node-pool + base: + apiVersion: containerservice.azure.upbound.io/v1beta1 + kind: KubernetesClusterNodePool + spec: + forProvider: + vnetSubnetIdSelector: + matchControllerRef: true + kubernetesClusterIdSelector: + matchControllerRef: true + patches: + - type: PatchSet + patchSetName: metadata-patch + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.name + toFieldPath: metadata.annotations[crossplane.io/external-name] + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.maxCount + toFieldPath: spec.forProvider.maxCount + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.minCount + toFieldPath: spec.forProvider.minCount + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.nodeCount + toFieldPath: spec.forProvider.nodeCount + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.vmSize + toFieldPath: spec.forProvider.vmSize + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.enableAutoScaling + toFieldPath: spec.forProvider.enableAutoScaling + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.maxPods + toFieldPath: spec.forProvider.maxPods + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.nodeLabels + toFieldPath: spec.forProvider.nodeLabels + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.nodeTaints + toFieldPath: spec.forProvider.nodeTaints + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.osDiskType + toFieldPath: spec.forProvider.osDiskType + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.osSku + toFieldPath: spec.forProvider.osSku + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.osDiskSizeGb + toFieldPath: spec.forProvider.osDiskSizeGb + - type: FromCompositeFieldPath + fromFieldPath: spec.userNodePool.osType + toFieldPath: spec.forProvider.osType + - name: default-subnet + base: + apiVersion: network.azure.upbound.io/v1beta1 + kind: Subnet + spec: + forProvider: + virtualNetworkNameSelector: + matchControllerRef: true + resourceGroupNameSelector: + matchControllerRef: true + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.subnet.name + toFieldPath: metadata.annotations[crossplane.io/external-name] + - type: FromCompositeFieldPath + fromFieldPath: spec.subnet.addressPrefixes + toFieldPath: spec.forProvider.addressPrefixes + - type: FromCompositeFieldPath + fromFieldPath: spec.subnet.privateEndpointNetworkPoliciesEnabled + toFieldPath: spec.forProvider.privateEndpointNetworkPoliciesEnabled + - type: FromCompositeFieldPath + fromFieldPath: spec.subnet.privateLinkServiceNetworkPoliciesEnabled + toFieldPath: spec.forProvider.privateLinkServiceNetworkPoliciesEnabled + - name: virtual-network + base: + apiVersion: network.azure.upbound.io/v1beta1 + kind: VirtualNetwork + spec: + forProvider: + resourceGroupNameSelector: + matchControllerRef: true + patches: + - type: PatchSet + patchSetName: location-patch + - type: PatchSet + patchSetName: metadata-patch + - type: FromCompositeFieldPath + fromFieldPath: metadata.annotations[crossplane.io/external-name] + toFieldPath: metadata.annotations[crossplane.io/external-name] + transforms: + - type: string + string: + fmt: "%s-vnet" + - type: FromCompositeFieldPath + fromFieldPath: spec.virtualNetwork.addressSpace + toFieldPath: spec.forProvider.addressSpace + - type: FromCompositeFieldPath + fromFieldPath: spec.virtualNetwork.tags + toFieldPath: spec.forProvider.tags + - name: aks-resourcegroup + base: + apiVersion: azure.upbound.io/v1beta1 + kind: ResourceGroup + spec: + forProvider: + name: temp + patches: + - type: PatchSet + patchSetName: location-patch + - type: PatchSet + patchSetName: metadata-patch + - type: FromCompositeFieldPath + fromFieldPath: metadata.annotations[crossplane.io/external-name] + toFieldPath: metadata.annotations[crossplane.io/external-name] + transforms: + - type: string + string: + fmt: "%s-rg" + - type: FromCompositeFieldPath + fromFieldPath: spec.resourceGroup.tags + toFieldPath: spec.forProvider.tags + compositeTypeRef: + apiVersion: kubernetes.example.com/v1alpha1 + kind: XAksCluster diff --git a/gitops/clusters/crossplane/base/cluster/kustomization.yaml b/gitops/clusters/crossplane/base/cluster/kustomization.yaml new file mode 100644 index 00000000..5e6b965d --- /dev/null +++ b/gitops/clusters/crossplane/base/cluster/kustomization.yaml @@ -0,0 +1,4 @@ +--- +resources: + - aks-composite-resource-definition.yaml + - aks-composition.yaml \ No newline at end of file diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/base/cluster-claim.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/base/cluster-claim.yaml new file mode 100644 index 00000000..c8b3c0e4 --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/base/cluster-claim.yaml @@ -0,0 +1,73 @@ +apiVersion: kubernetes.example.com/v1alpha1 +kind: AksClusterClaim +metadata: + name: my-app-cluster + annotations: + crossplane.io/external-name: my-app-cluster + argocd.argoproj.io/sync-wave: "3" + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + location: "North Europe" + aks: + defaultNodePool: + name: system + vmSize: Standard_B2s + enableAutoScaling: true + nodeCount: 1 + minCount: 1 + maxCount: 20 + maxPods: 30 + nodeLabels: + mode: system + onlyCriticalAddonsEnabled: false + osDiskSizeGb: 128 + osDiskType: Ephemeral + kubernetesVersion: "1.28.3" + roleBasedAccessControlEnabled: true + oidcIssuerEnabled: true + workloadIdentityEnabled: true + privateClusterEnabled: false + azureActiveDirectoryRoleBasedAccessControl: + - adminGroupObjectIds: + - 4e4d0501-e693-4f3e-965b-5bec6c410c03 + azureRbacEnabled: true + managed: true + azurePolicyEnabled: true + networkProfile: + - networkPlugin: azure + networkPolicy: azure + outboundType: loadBalancer + dnsServiceIp: 172.16.0.10 + serviceCidr: 172.16.0.0/16 + workloadAutoscalerProfile: + - kedaEnabled: true + verticalPodAutoscalerEnabled: true + tags: + environment: Test + provisionedBy: Crossplane + userNodePool: + name: user + vmSize: Standard_B2s + enableAutoScaling: true + nodeCount: 1 + minCount: 1 + maxCount: 20 + maxPods: 30 + nodeLabels: + mode: user + osDiskSizeGb: 128 + osDiskType: Ephemeral + osSku: AzureLinux + osType: Linux + subnet: + name: MainSubnet + privateEndpointNetworkPoliciesEnabled: true + privateLinkServiceNetworkPoliciesEnabled: false + addressPrefixes: + - 10.0.0.0/16 + virtualNetwork: + addressSpace: + - 10.0.0.0/8 + tags: + environment: Test + provisionedBy: Crossplane \ No newline at end of file diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/base/kustomization.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/base/kustomization.yaml new file mode 100644 index 00000000..60172c92 --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/base/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - cluster-claim.yaml \ No newline at end of file diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/dev/cluster-claim.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/dev/cluster-claim.yaml new file mode 100644 index 00000000..785543c7 --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/dev/cluster-claim.yaml @@ -0,0 +1,17 @@ + +apiVersion: kubernetes.example.com/v1alpha1 +kind: AksClusterClaim +metadata: + name: my-app-cluster + annotations: + crossplane.io/external-name: my-app-cluster-dev +spec: + location: "North Europe" + aks: + tags: + environment: dev + virtualNetwork: + tags: + environment: dev + writeConnectionSecretToRef: + name: my-app-cluster-dev-secret \ No newline at end of file diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/dev/kustomization.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/dev/kustomization.yaml new file mode 100644 index 00000000..b302ef55 --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/dev/kustomization.yaml @@ -0,0 +1,19 @@ +namespace: my-app-cluster-dev + +resources: + - ../base + - namespace.yaml + +patches: +- path: cluster-claim.yaml + target: + group: kubernetes.example.com + version: v1alpha1 + kind: AksClusterClaim + name: my-app-cluster +- patch: |- + - op: replace + path: /metadata/name + value: my-app-cluster-dev + target: + kind: AksClusterClaim \ No newline at end of file diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/dev/namespace.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/dev/namespace.yaml new file mode 100644 index 00000000..d8805f7c --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/dev/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: my-app-cluster-dev diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/kustomization.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/kustomization.yaml new file mode 100644 index 00000000..9ff16ef0 --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/kustomization.yaml @@ -0,0 +1,3 @@ +resources: + - dev + - stage \ No newline at end of file diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/stage/cluster-claim.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/stage/cluster-claim.yaml new file mode 100644 index 00000000..6d491c5c --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/stage/cluster-claim.yaml @@ -0,0 +1,17 @@ + +apiVersion: kubernetes.example.com/v1alpha1 +kind: AksClusterClaim +metadata: + name: my-app-cluster + annotations: + crossplane.io/external-name: my-app-cluster-stage +spec: + location: "EastUs" + aks: + tags: + environment: stage + virtualNetwork: + tags: + environment: stage + writeConnectionSecretToRef: + name: my-app-cluster-stage-secret \ No newline at end of file diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/stage/kustomization.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/stage/kustomization.yaml new file mode 100644 index 00000000..ecb2bacd --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/stage/kustomization.yaml @@ -0,0 +1,19 @@ +namespace: my-app-cluster-stage + +resources: + - ../base + - namespace.yaml + +patches: +- path: cluster-claim.yaml + target: + group: kubernetes.example.com + version: v1alpha1 + kind: AksClusterClaim + name: my-app-cluster +- patch: |- + - op: replace + path: /metadata/name + value: my-app-cluster-stage + target: + kind: AksClusterClaim \ No newline at end of file diff --git a/gitops/clusters/crossplane/clusters/my-app-cluster/stage/namespace.yaml b/gitops/clusters/crossplane/clusters/my-app-cluster/stage/namespace.yaml new file mode 100644 index 00000000..6685a5d9 --- /dev/null +++ b/gitops/clusters/crossplane/clusters/my-app-cluster/stage/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: my-app-cluster-stage diff --git a/gitops/clusters/crossplane/kustomization.yaml b/gitops/clusters/crossplane/kustomization.yaml new file mode 100644 index 00000000..2244be31 --- /dev/null +++ b/gitops/clusters/crossplane/kustomization.yaml @@ -0,0 +1,3 @@ +resources: + - base/cluster + - clusters/my-app-cluster \ No newline at end of file diff --git a/terraform/bootstrap/workloads.yaml b/terraform/bootstrap/workloads.yaml index c3990393..c07e8bfb 100644 --- a/terraform/bootstrap/workloads.yaml +++ b/terraform/bootstrap/workloads.yaml @@ -13,9 +13,6 @@ spec: - key: akuity.io/argo-cd-cluster-name operator: NotIn values: [in-cluster] - - key: environment - operator: NotIn - values: [control-plane] template: metadata: name: 'workload-{{metadata.labels.environment}}' @@ -25,6 +22,9 @@ spec: repoURL: '{{metadata.annotations.workload_repo_url}}' path: '{{metadata.annotations.workload_repo_basepath}}{{metadata.annotations.workload_repo_path}}' targetRevision: '{{metadata.annotations.workload_repo_revision}}' + directory: + recurse: true + exclude: exclude/* destination: namespace: 'workload' name: '{{name}}' diff --git a/terraform/main.tf b/terraform/main.tf index c8ef66c1..92ed8a2b 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -13,11 +13,13 @@ locals { argocd_namespace = "argocd" azure_addons = { - enable_azure_crossplane_upbound_provider = try(var.addons.enable_azure_crossplane_upbound_provider, false) + enable_azure_crossplane_provider = var.infrastructure_provider == "crossplane" ? true : false + enable_azure_crossplane_upbound_provider = var.infrastructure_provider == "crossplane" ? true : false enable_cluster_api_operator = try(var.addons.enable_cluster_api_operator, false) } + oss_addons = { - enable_argocd = try(var.addons.enable_argocd, false) + enable_argocd = try(var.addons.enable_argocd, false) # installed by default enable_argo_rollouts = try(var.addons.enable_argo_rollouts, false) enable_argo_events = try(var.addons.enable_argo_events, false) enable_argo_workflows = try(var.addons.enable_argo_workflows, false) @@ -32,11 +34,15 @@ locals { enable_prometheus_adapter = try(var.addons.enable_prometheus_adapter, false) enable_secrets_store_csi_driver = try(var.addons.enable_secrets_store_csi_driver, false) enable_vpa = try(var.addons.enable_vpa, false) - enable_crossplane = try(var.addons.enable_crossplane, false) + enable_crossplane = var.infrastructure_provider == "crossplane" ? true : false } addons = merge(local.azure_addons, local.oss_addons) - cluster_metadata = merge(local.addons_metadata, local.workloads_metadata) + cluster_metadata = merge(local.environment_metadata, local.addons_metadata, local.workloads_metadata) + + environment_metadata = { + infrastructure_provider = var.infrastructure_provider + } addons_metadata = { addons_repo_url = local.gitops_addons_url diff --git a/terraform/variables.tf b/terraform/variables.tf index 7e0ad5b6..1b96f4a6 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -22,8 +22,14 @@ variable "kubernetes_version" { default = null } +variable "infrastructure_provider" { + description = "Specific the choice of infrastructure provider. crossplane or capz" + type = string + default = "crossplane" +} + variable "addons" { - description = "Specifies the Kubernetes addons to install." + description = "Specifies the Kubernetes addons to install on the hub cluster." type = any default = { enable_argocd = true # installs argocd @@ -91,7 +97,7 @@ variable "gitops_workload_basepath" { variable "gitops_workload_path" { description = "Specifies the Git repository path for workload." type = string - default = "apps" + default = "bootstrap/workloads" } variable "tags" {