Distributed systems like SOA/microservice are very difficult to develop, each service can take many parts to work, services can depend on each other for various reasons, this brings up the problems:
- Maintain the consistency/certainty inbetween parts of each service is difficult.
- Missing assets/image
- Using wrong configuration from 3) code repo 4) secret store 5) configuration store
- Maintain the consistency/certainty inbetween services is even more difficult. 3) beside configuration, service API changing 4) messaging schema changing
- Manual configuration already reached to limit
- Can't remember what/how/why/where/when, can easily be hijacked
- who/how/why created that repo?
- what/how/where/when is the repo deployed last time?
- how other services are using/depending on the repo?
- Is the code in the repo consistent to the deployed?
- Human mistake is inevitable and taking significant effort 3) one typo can easily take hours for a complex system 4) too difficult to track every change.
- Can't remember what/how/why/where/when, can easily be hijacked
- GitOps can't handle the complexity, templating yamls are the new binary in cloud era.
- Too shallow and ridgid to adapt change, simple change can require huge unpractical amount of change of yamls.
- Can require multiple commits and multiple deployments across multiple repos for a single change.
- Too many repeats in yamls across many files and repos, complexity grows exponentially.
- Certain files can easily reach thousands of lines, making it not scalable/sustainable
- For a distributed systems like SOA/microservice, each service needs multiple environment/versions, so that
- developers can compare different versions of code/config by comparing different deployed actual running environments.
- developers can experiment discover and learn.
- multiple environments to run more tests in different scenarios in parallel.
- Application architecture as actual code to describe services' relationship.
- Abstract contracting/interface/boundary of each service, define relationship among in code.
- Each service implements its contracting/interface/boundary, generate its deployment manifests/plans.
- Monitoring deployments of each environment/version of each service
- Automation, event driven and plan/simulation
- Dynamically generating DAG of dependency
- Dynamically generating deployment plans(phase/stages) based on DAG of dependency
- Configurable manual verification/approval based on IAM
- Data Model: team<-1:m->repo<-1:m->build<-1:m->service[deployment] | artifacts
- service[deployment] providing and consuming APIs by endpoints/topics.
- artifacts are container image or packages to be deployed as part of a service.
- service and artifacts both can have multiple versions/environments
- see https://github.com/ondemandenv/odmd-build-contracts for more details.
- Abstract contracting/interface/boundary of each service, define them in static and strong typed code so that:
- Better IDE support.
- Validate as early as compilation.
- Define services' contracts in one repo as lib, and a central service to implement typical services and coordinate cross service dependencies.
- AWS CDK to describe data/function model
- Github as source repo and Github workflow as continue deployment service.
- AWS Cloudformation service to execute different stacks
- Basic build types:
- container image to ECR
- ECR image deploy to EKS
- npm package to github package
- aws cdk deployment
- provided basic services.
- rds serverless v2 postgres
- eks cluster
- Define a build in two parts:
- In contracts repo together with other builds to declare how it contracts with other builds.
- which repo and how to build
- bootstraping target AWS account/region.
- what value it consumes from others, vpc cidr? eks-cluster, ECR repo? authentication service's endpoint?
- what value it produces, messaing topic? api endpoints? image in ECR? or package in github?
- Implementing the contract, this is optional because there are typical basic implementations can be used by declaration in contracts repo.
- In contracts repo together with other builds to declare how it contracts with other builds.
- let the central deploy infrastructures including pipelines to build's aws account and github repo.
- trigger pipeline to run this build.
- build's output will trigger other builds.