├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app.py ├── cdk.context.json ├── cdk.json ├── cluster ├── __init__.py └── cluster_construct.py ├── dockerpipeline └── docker_pipeline.py ├── fluxcd ├── __init__.py ├── fluxcd_cluster.py └── fluxcd_construct.py ├── images ├── diagram.png └── pipeline.png ├── repos ├── app_example │ ├── Dockerfile │ ├── buildspec.yml │ └── code │ │ ├── app.py │ │ └── requirements.txt └── infra_example │ └── podinfo-dep.yaml ├── requirements.txt ├── setup.py └── source.bat /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## CI/CD on EKS using AWS Codecommit, AWS Codepipeline, AWS Codebuild and FluxCD written in python using CDK! 2 | The purpose of this repository is to demo how can we work with the GitOps philosophy using FluxCD on EKS. This implementation has been developed using CDK. 3 | 4 | #### Requirements 5 | - CDK installed: [Getting started with the AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html) 6 | - AWS Account 7 | - IAM user with Git Credentials for Codecommit: [IAM Git Credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_ssh-keys.html) 8 | 9 | 10 | ### Architecture 11 | ![awsome-flux-example](images/diagram.png) 12 | 13 | ### Steps to reproduce 14 | 15 | Export your Git credentials: 16 | ``` 17 | export GIT_AUTH_USER=git_username 18 | export GIT_AUTH_KEY=git_credentials 19 | ``` 20 | Specify the stack name, and region on the [cdk.json](cdk.json), for example: 21 | 22 | ``` 23 | { 24 | "app": "python3 app.py", 25 | "context": { 26 | "@aws-cdk/core:enableStackNameDuplicates": "true", 27 | "aws-cdk:enableDiffNoFail": "true", 28 | "@aws-cdk/core:stackRelativeExports": "true", 29 | "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, 30 | "name": "awsome-flux-example", 31 | "region": "us-east-1" 32 | } 33 | } 34 | 35 | ``` 36 | 37 | Deploy the infrastructure using the CDK cli: 38 | 39 | ``` 40 | cdk bootstrap aws://account_id/us-east-1 41 | cdk deploy 42 | ``` 43 | The infrastructure creation takes around 15/20 min due the EKS cluster creation. During the meantime, you can clone the two new repos that have been already created and push the example code. First one for the kubernetes [infrastructure](repos/infra_example) and later, for your [application](repos/app_example). Don't forget to change the account ID of the Amazon Registry on the [infrastructure](repos/infra_example) in the line 21. 44 | 45 | Like this: 46 | ``` 47 | git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/kubernetes-infra-awsome-flux-example 48 | cp repos/infra_example/* kubernetes-infra-awsome-flux-example/ 49 | git add . 50 | git commit -am "First commit" 51 | git push 52 | 53 | git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/awsome-flux-example 54 | cp repos/app_example/* awsome-flux-example/ 55 | git add . 56 | git commit -am "First commit" 57 | git push 58 | ``` 59 | 60 | After push your code the pipeline is triggered: 61 | 62 | ![awsome-pipeline](images/pipeline.png) 63 | 64 | 65 | Once the stack is completed, you will get the following outputs: 66 | ``` 67 | Outputs: 68 | awsome-flux-example-stack.awsomefluxexampleclusterConfigCommandC5ACCB2F = aws eks update-kubeconfig --name awsomefluxexamplecluster7E1AB52B-8636fb0994a64eaf835a8568e4f1dd6d --region us-east-1 --role-arn arn:aws:iam::account_id:role/awsome-flux-example-stack-awsomefluxexamplecluster-4WYAIKEQONYC 69 | awsome-flux-example-stack.awsomefluxexampleclusterGetTokenCommand58A55459 = aws eks get-token --cluster-name awsomefluxexamplecluster7E1AB52B-8636fb0994a64eaf835a8568e4f1dd6d --region us-east-1 --role-arn arn:aws:iam::account_id:role/awsome-flux-example-stack-awsomefluxexamplecluster-4WYAIKEQONYC 70 | awsome-flux-example-stack.awsomefluxexamplefluxcdk8sinfrastructurerepository051BF5A3 = https://git-codecommit.us-east-1.amazonaws.com/v1/repos/kubernetes-infra-awsome-flux-example 71 | ``` 72 | 73 | ### Check your cluster 74 | 75 | Connect to the EKS cluster using the previous output and check your application. You can also follow [Update Kubeconfig](https://docs.aws.amazon.com/cli/latest/reference/eks/update-kubeconfig.html) 76 | 77 | ``` 78 | # kubectl get pod 79 | NAME READY STATUS RESTARTS AGE 80 | awsome-app-flux-67b6457b5b-fhz7m 1/1 Running 0 5m12s 81 | awsome-app-flux-67b6457b5b-ngxhb 1/1 Running 0 5m33s 82 | flux-f8c9c99f9-k9wd4 1/1 Running 0 15m 83 | memcached-5bd7849b84-26xrv 1/1 Running 0 15m 84 | ``` 85 | 86 | 87 | ### Clean up 88 | After completing your demo, delete your stack using the CDK cli: 89 | ``` 90 | cdk destroy 91 | ``` 92 | 93 | ## Security 94 | 95 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 96 | 97 | ## License 98 | 99 | This library is licensed under the MIT-0 License. See the LICENSE file. -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from aws_cdk import core 4 | from dockerpipeline.docker_pipeline import DockerPipelineConstruct 5 | from fluxcd.fluxcd_construct import FluxcdConstruct 6 | from cluster.cluster_construct import ClusterConstruct 7 | import os 8 | git_auth_user = os.environ["GIT_AUTH_USER"] 9 | git_auth_key = os.environ["GIT_AUTH_KEY"] 10 | 11 | app = core.App() 12 | 13 | 14 | name = app.node.try_get_context("name") 15 | region = app.node.try_get_context("region") 16 | 17 | aws_env = core.Environment(region=region) 18 | stack = core.Stack(scope=app,id=f"{name}-stack",env=aws_env) 19 | 20 | cluster_construct = ClusterConstruct( 21 | scope=stack, 22 | id=f"{name}-cluster", 23 | cluster_name=f"{name}-cluster" 24 | ) 25 | fluxcd_docker_pipeline = DockerPipelineConstruct( 26 | scope=stack, 27 | id=f"{name}-docker-pipeline" 28 | ) 29 | fluxcd_construct = FluxcdConstruct( 30 | scope=stack, 31 | id=f"{name}-fluxcd", 32 | git_user=git_auth_user, 33 | git_password=git_auth_key, 34 | eks_base_cluster=cluster_construct.cluster 35 | ) 36 | 37 | app.synth() -------------------------------------------------------------------------------- /cdk.context.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "python3 app.py", 3 | "context": { 4 | "@aws-cdk/core:enableStackNameDuplicates": "true", 5 | "aws-cdk:enableDiffNoFail": "true", 6 | "@aws-cdk/core:stackRelativeExports": "true", 7 | "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, 8 | "name": "awsome-flux-example", 9 | "region": "us-east-1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /cluster/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cdk-eks-flux/22285365f277542abf12cbeb7341a62283d134eb/cluster/__init__.py -------------------------------------------------------------------------------- /cluster/cluster_construct.py: -------------------------------------------------------------------------------- 1 | from aws_cdk import ( 2 | aws_eks as eks, 3 | core as cdk 4 | ) 5 | 6 | class ClusterConstruct(cdk.Construct): 7 | def __init__(self,scope,id,cluster_name): 8 | super().__init__(scope,id) 9 | self._cluster_name = cluster_name 10 | self._create_resource() 11 | 12 | def _create_resource(self): 13 | self.cluster = eks.Cluster( 14 | scope=self, 15 | id=self._cluster_name, 16 | version=eks.KubernetesVersion.V1_18 17 | ) 18 | -------------------------------------------------------------------------------- /dockerpipeline/docker_pipeline.py: -------------------------------------------------------------------------------- 1 | from aws_cdk import ( 2 | aws_codecommit as codecommit, 3 | aws_codepipeline as codepipeline, 4 | aws_codebuild as codebuild, 5 | aws_codepipeline_actions as codepipeline_actions, 6 | aws_ecr as ecr, 7 | aws_iam as iam, 8 | core 9 | ) 10 | 11 | 12 | class DockerPipelineConstruct(core.Construct): 13 | 14 | def __init__( 15 | self, 16 | scope: core.Construct, 17 | id: str, 18 | ) -> None: 19 | super().__init__(scope=scope, id=id) 20 | 21 | name = scope.node.try_get_context("name") 22 | # ECR repositories 23 | container_repository = ecr.Repository( 24 | scope=self, 25 | id=f"{name}-container", 26 | repository_name=f"{name}" 27 | ) 28 | # Repo for Application 29 | codecommit_repo = codecommit.Repository( 30 | scope=self, 31 | id=f"{name}-container-git", 32 | repository_name=f"{name}", 33 | description=f"Application code" 34 | ) 35 | 36 | pipeline = codepipeline.Pipeline( 37 | scope=self, 38 | id=f"{name}-container--pipeline", 39 | pipeline_name=f"{name}" 40 | ) 41 | 42 | 43 | # Outputs 44 | core.CfnOutput( 45 | scope=self, 46 | id="application_repository", 47 | value=codecommit_repo.repository_clone_url_http 48 | ) 49 | source_output = codepipeline.Artifact() 50 | docker_output = codepipeline.Artifact(artifact_name="Docker") 51 | 52 | buildspec_docker = codebuild.BuildSpec.from_source_filename("buildspec.yml") 53 | 54 | docker_build = codebuild.PipelineProject( 55 | scope=self, 56 | id=f"DockerBuild", 57 | environment=dict( 58 | build_image=codebuild.LinuxBuildImage.AMAZON_LINUX_2_3, 59 | privileged=True), 60 | environment_variables={ 61 | 'REPO_ECR': codebuild.BuildEnvironmentVariable( 62 | value=container_repository.repository_uri), 63 | }, 64 | build_spec=buildspec_docker 65 | ) 66 | 67 | container_repository.grant_pull_push(docker_build) 68 | docker_build.add_to_role_policy(iam.PolicyStatement( 69 | effect=iam.Effect.ALLOW, 70 | actions=["ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"], 71 | resources=[f"arn:{core.Stack.of(self).partition}:ecr:{core.Stack.of(self).region}:{core.Stack.of(self).account}:repository/*"],)) 72 | 73 | source_action = codepipeline_actions.CodeCommitSourceAction( 74 | action_name="CodeCommit_Source", 75 | repository=codecommit_repo, 76 | output=source_output, 77 | branch="master" 78 | ) 79 | 80 | pipeline.add_stage( 81 | stage_name="Source", 82 | actions=[source_action] 83 | ) 84 | 85 | # Stages in CodePipeline 86 | pipeline.add_stage( 87 | stage_name="DockerBuild", 88 | actions=[ 89 | codepipeline_actions.CodeBuildAction( 90 | action_name=f"DockerBuild_and_Push_ECR", 91 | project=docker_build, 92 | input=source_output, 93 | outputs=[docker_output]) 94 | ] 95 | ) 96 | -------------------------------------------------------------------------------- /fluxcd/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cdk-eks-flux/22285365f277542abf12cbeb7341a62283d134eb/fluxcd/__init__.py -------------------------------------------------------------------------------- /fluxcd/fluxcd_cluster.py: -------------------------------------------------------------------------------- 1 | import base64 2 | from aws_cdk import aws_eks as eks 3 | 4 | class FluxcdCluster(): 5 | def __init__( 6 | self, 7 | scope, 8 | eks_base_cluster, 9 | git_user, 10 | git_password, 11 | git_repository, 12 | git_branch="master" 13 | ): 14 | main_manifest = self._base_manifest(git_repository) 15 | main_manifest.append(self._secret_manifest(git_user,git_password)) 16 | eks_manifest = eks.KubernetesManifest( 17 | scope=scope, 18 | id="fluxcd-main-manifest-new", 19 | cluster=eks_base_cluster, 20 | manifest=main_manifest 21 | ) 22 | 23 | def _base64encode(self,string): 24 | return base64.b64encode(string.encode('ascii')).decode('ascii') 25 | 26 | 27 | def _secret_manifest(self,git_user,git_password): 28 | return { 29 | 'apiVersion': 'v1', 30 | 'kind': 'Secret', 31 | 'metadata': { 32 | 'name': 'flux-git-auth', 33 | 'namespace': 'default' 34 | }, 35 | 'data': { 36 | 'GIT_AUTHKEY' : self._base64encode(git_password), 37 | 'GIT_AUTHUSER' : self._base64encode(git_user) 38 | }, 39 | 'type': 'Opaque' 40 | } 41 | 42 | def _base_manifest(self,git_repository): 43 | return [{ 44 | 'apiVersion': 'apps/v1', 45 | 'kind': 'Deployment', 46 | 'metadata': { 47 | 'name': 'memcached', 48 | 'namespace': 'default'}, 49 | 'spec': { 50 | 'replicas': 1, 51 | 'selector': { 52 | 'matchLabels': { 53 | 'name': 'memcached' 54 | } 55 | }, 56 | 'template': { 57 | 'metadata': { 58 | 'labels': { 59 | 'name': 'memcached' 60 | } 61 | }, 62 | 'spec': { 63 | 'nodeSelector': { 64 | 'beta.kubernetes.io/os': 'linux' 65 | }, 'containers': [{ 66 | 'name': 'memcached', 67 | 'image': 'memcached:1.5.20', 68 | 'imagePullPolicy': 'IfNotPresent', 69 | 'args': ['-m 512', '-I 5m', '-p 11211'], 70 | 'ports': [{ 71 | 'name': 'clients', 72 | 'containerPort': 11211 73 | }], 74 | 'securityContext': { 75 | 'runAsUser': 11211, 76 | 'runAsGroup': 11211, 77 | 'allowPrivilegeEscalation': False 78 | } 79 | }] 80 | } 81 | } 82 | } 83 | }, 84 | { 85 | 'apiVersion': 'v1', 86 | 'kind': 'Service', 87 | 'metadata': { 88 | 'name': 'memcached', 89 | 'namespace': 'default' 90 | }, 91 | 'spec': { 92 | 'ports': [{ 93 | 'name': 'memcached', 94 | 'port': 11211 95 | }], 96 | 'selector': { 97 | 'name': 'memcached' 98 | } 99 | } 100 | }, 101 | { 102 | 'apiVersion': 'v1', 103 | 'kind': 'ServiceAccount', 104 | 'metadata': { 105 | 'labels': { 106 | 'name': 'flux' 107 | }, 108 | 'name': 'flux', 109 | 'namespace': 'default' 110 | } 111 | }, 112 | { 113 | 'apiVersion': 'rbac.authorization.k8s.io/v1beta1', 114 | 'kind': 'ClusterRole', 115 | 'metadata': { 116 | 'labels': { 117 | 'name': 'flux' 118 | }, 119 | 'name': 'flux' 120 | }, 121 | 'rules': [{ 122 | 'apiGroups': ['*'], 123 | 'resources': ['*'], 124 | 'verbs': ['*'] 125 | }, 126 | {'nonResourceURLs': ['*'], 127 | 'verbs': ['*'] 128 | }] 129 | }, 130 | { 131 | 'apiVersion': 'rbac.authorization.k8s.io/v1beta1', 132 | 'kind': 'ClusterRoleBinding', 133 | 'metadata': { 134 | 'labels': { 135 | 'name': 'flux' 136 | }, 137 | 'name': 'flux' 138 | }, 139 | 'roleRef': { 140 | 'apiGroup': 'rbac.authorization.k8s.io', 141 | 'kind': 'ClusterRole', 142 | 'name': 'flux' 143 | }, 144 | 'subjects': [{ 145 | 'kind': 'ServiceAccount', 146 | 'name': 'flux', 147 | 'namespace': 'default' 148 | }] 149 | }, 150 | { 151 | 'apiVersion': 'apps/v1', 152 | 'kind': 'Deployment', 153 | 'metadata': { 154 | 'name': 'flux', 155 | 'namespace': 'default' 156 | }, 157 | 'spec': { 158 | 'replicas': 1, 159 | 'selector': { 160 | 'matchLabels': { 161 | 'name': 'flux' 162 | } 163 | }, 164 | 'strategy': { 165 | 'type': 'Recreate' 166 | }, 167 | 'template': { 168 | 'metadata': { 169 | 'annotations': { 170 | 'prometheus.io/port': '3031' 171 | }, 172 | 'labels': { 173 | 'name': 'flux' 174 | } 175 | }, 176 | 'spec': { 177 | 'nodeSelector': { 178 | 'beta.kubernetes.io/os': 'linux' 179 | }, 180 | 'serviceAccountName': 'flux', 181 | 'volumes': [{ 182 | 'name': 'git-key', 183 | 'secret': { 184 | 'secretName': 'flux-git-deploy', 185 | 'defaultMode': 256 186 | } 187 | }, 188 | {'name': 'git-keygen', 189 | 'emptyDir': { 190 | 'medium': 'Memory' 191 | } 192 | }], 193 | 'containers': [{ 194 | 'name': 'flux', 195 | 'image': 'docker.io/fluxcd/flux:1.21.0', 196 | 'imagePullPolicy': 'IfNotPresent', 197 | 'envFrom' : [{ 198 | 'secretRef' : { 199 | 'name' : 'flux-git-auth' 200 | } 201 | }], 202 | 'resources': { 203 | 'requests': { 204 | 'cpu': '50m', 205 | 'memory': '64Mi' 206 | } 207 | }, 208 | 'ports': [{ 209 | 'containerPort': 3030 210 | }], 211 | 'livenessProbe': { 212 | 'httpGet': { 213 | 'port': 3030, 214 | 'path': '/api/flux/v6/identity.pub' 215 | }, 216 | 'initialDelaySeconds': 5, 217 | 'timeoutSeconds': 5 218 | }, 219 | 'readinessProbe': { 220 | 'httpGet': { 221 | 'port': 3030, 222 | 'path': '/api/flux/v6/identity.pub' 223 | }, 224 | 'initialDelaySeconds': 5, 225 | 'timeoutSeconds': 5 226 | }, 227 | 'volumeMounts': [{ 228 | 'name': 'git-key', 229 | 'mountPath': '/etc/fluxd/ssh', 230 | 'readOnly': True 231 | }, 232 | {'name': 'git-keygen', 233 | 'mountPath': '/var/fluxd/keygen' 234 | }], 235 | 'args': ['--memcached-service=', 236 | '--ssh-keygen-dir=/var/fluxd/keygen', 237 | '--git-url=https://$(GIT_AUTHUSER):$(GIT_AUTHKEY)@' + git_repository, 238 | '--git-branch=master', 239 | '--git-label=flux', 240 | '--git-email=aws-example@users.noreply.github.com', 241 | '--listen-metrics=:3031' 242 | ] 243 | }] 244 | } 245 | } 246 | } 247 | }, 248 | { 249 | 'apiVersion': 'v1', 250 | 'kind': 'Secret', 251 | 'metadata': { 252 | 'name': 'flux-git-deploy', 253 | 'namespace': 254 | 'default' 255 | }, 256 | 'type': 'Opaque' 257 | }] 258 | -------------------------------------------------------------------------------- /fluxcd/fluxcd_construct.py: -------------------------------------------------------------------------------- 1 | from aws_cdk import ( 2 | aws_iam as iam, 3 | aws_sqs as sqs, 4 | aws_sns as sns, 5 | aws_sns_subscriptions as subs, 6 | aws_codecommit as codecommit, 7 | aws_eks as eks, 8 | core 9 | ) 10 | from . import fluxcd_cluster 11 | class FluxcdConstruct(core.Construct): 12 | 13 | def __init__( 14 | self, 15 | scope: core.Construct, 16 | id: str, 17 | eks_base_cluster: eks.Cluster, 18 | git_user, 19 | git_password 20 | ) -> None: 21 | 22 | super().__init__(scope=scope, id=id) 23 | 24 | name = scope.node.try_get_context("name") 25 | region = scope.region 26 | 27 | # Repo for Kubernetes infraestructure 28 | codecommit_repo_kubernetes = codecommit.Repository( 29 | scope=self, 30 | id=f"{name}-kubernetes-git", 31 | repository_name=f"kubernetes-infra-{name}", 32 | description=f"Kubernetes Infra Code" 33 | ) 34 | self.k8s_infra_git_host = "git-codecommit." + region + ".amazonaws.com/v1/repos/" + codecommit_repo_kubernetes.repository_name 35 | core.CfnOutput( 36 | scope=self, 37 | id="k8s_infrastructure_repository", 38 | value=codecommit_repo_kubernetes.repository_clone_url_http 39 | ) 40 | fluxcd_cluster.FluxcdCluster( 41 | scope=self, 42 | eks_base_cluster=eks_base_cluster, 43 | git_user=git_user, 44 | git_password=git_password, 45 | git_repository=self.k8s_infra_git_host 46 | ) 47 | 48 | -------------------------------------------------------------------------------- /images/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cdk-eks-flux/22285365f277542abf12cbeb7341a62283d134eb/images/diagram.png -------------------------------------------------------------------------------- /images/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cdk-eks-flux/22285365f277542abf12cbeb7341a62283d134eb/images/pipeline.png -------------------------------------------------------------------------------- /repos/app_example/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3 2 | ADD code ./code 3 | WORKDIR ./code 4 | RUN pip install -r requirements.txt 5 | EXPOSE 8080 6 | CMD python app.py -------------------------------------------------------------------------------- /repos/app_example/buildspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | phases: 3 | pre_build: 4 | commands: 5 | - echo Logging in to Amazon ECR... 6 | - aws --version 7 | - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email) 8 | - REPOSITORY_URI=${REPO_ECR} 9 | - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) 10 | - IMAGE_TAG=${COMMIT_HASH:=latest} 11 | build: 12 | commands: 13 | - echo Build started on `date` 14 | - echo Building the Docker image... 15 | - docker build -t $REPOSITORY_URI:latest . 16 | - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG 17 | post_build: 18 | commands: 19 | - echo Build completed on `date` 20 | - echo Pushing the Docker images... 21 | - docker push $REPOSITORY_URI:latest 22 | - docker push $REPOSITORY_URI:$IMAGE_TAG -------------------------------------------------------------------------------- /repos/app_example/code/app.py: -------------------------------------------------------------------------------- 1 | import cherrypy 2 | 3 | class HelloWorld(object): 4 | @cherrypy.expose 5 | def index(self): 6 | return "Hello world!" 7 | 8 | if __name__ == '__main__': 9 | cherrypy.quickstart(HelloWorld()) 10 | -------------------------------------------------------------------------------- /repos/app_example/code/requirements.txt: -------------------------------------------------------------------------------- 1 | cherrypy -------------------------------------------------------------------------------- /repos/infra_example/podinfo-dep.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: awsome-app-flux 5 | labels: 6 | app: app 7 | annotations: 8 | fluxcd.io/automated: "true" 9 | spec: 10 | replicas: 2 11 | selector: 12 | matchLabels: 13 | app: awsome-app-flux 14 | template: 15 | metadata: 16 | labels: 17 | app: awsome-app-flux 18 | spec: 19 | containers: 20 | - name: awsome-app-flux 21 | image: 1234567896.dkr.ecr.us-east-1.amazonaws.com/awsome-flux-example:latest -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | -e . 2 | pytest 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | 4 | with open("README.md") as fp: 5 | long_description = fp.read() 6 | 7 | 8 | setuptools.setup( 9 | name="fluxcd", 10 | version="0.0.1", 11 | 12 | description="A sample CDK Python app", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | 16 | author="author", 17 | 18 | package_dir={"": "fluxcd"}, 19 | packages=setuptools.find_packages(where="fluxcd"), 20 | 21 | install_requires=[ 22 | "aws-cdk.core==1.75.0", 23 | "aws-cdk.aws_iam==1.75.0", 24 | "aws-cdk.aws_sqs==1.75.0", 25 | "aws-cdk.aws_sns==1.75.0", 26 | "aws-cdk.aws_sns_subscriptions==1.75.0", 27 | "aws-cdk.aws_s3==1.75.0", 28 | "aws-cdk.aws_codecommit==1.75.0", 29 | "aws-cdk.aws_codepipeline==1.75.0", 30 | "aws-cdk.aws_codebuild==1.75.0", 31 | "aws-cdk.aws_codepipeline_actions==1.75.0", 32 | "aws-cdk.aws_eks==1.75.0", 33 | ], 34 | 35 | python_requires=">=3.6", 36 | 37 | classifiers=[ 38 | "Development Status :: 4 - Beta", 39 | 40 | "Intended Audience :: Developers", 41 | 42 | "License :: OSI Approved :: Apache Software License", 43 | 44 | "Programming Language :: JavaScript", 45 | "Programming Language :: Python :: 3 :: Only", 46 | "Programming Language :: Python :: 3.6", 47 | "Programming Language :: Python :: 3.7", 48 | "Programming Language :: Python :: 3.8", 49 | 50 | "Topic :: Software Development :: Code Generators", 51 | "Topic :: Utilities", 52 | 53 | "Typing :: Typed", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /source.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem The sole purpose of this script is to make the command 4 | rem 5 | rem source .venv/bin/activate 6 | rem 7 | rem (which activates a Python virtualenv on Linux or Mac OS X) work on Windows. 8 | rem On Windows, this command just runs this batch file (the argument is ignored). 9 | rem 10 | rem Now we don't need to document a Windows command for activating a virtualenv. 11 | 12 | echo Executing .venv\Scripts\activate.bat for you 13 | .venv\Scripts\activate.bat 14 | --------------------------------------------------------------------------------