From d5908beba6a9984270255b3d4f4f43b489393a2c Mon Sep 17 00:00:00 2001 From: Asare Nkansah Date: Thu, 1 Feb 2024 07:53:18 -0700 Subject: [PATCH] Update engineering playbooks (#8) * Update engineering playbooks * Remove test content --- docs/assets/rise8-planes.webp | Bin 0 -> 52806 bytes docs/blog/gitops.md | 53 +++ docs/blog/platform-wars.md | 60 +++ docs/blog/sample.md | 7 - docs/blog/users.md | 27 ++ .../practice-playbook.md | 0 docs/index.md | 7 +- .../methodologies/general-best-practices.md | 54 +++ .../practicals/argocd-examples.md | 87 +++++ .../practicals/create-api-example.md | 85 ++++ .../general-engineering/practice-playbook.md | 364 ++++++++++++++++++ .../concepts/argocd-best-practices.md | 61 +++ .../concepts/kubernetes-best-practices.md | 89 +++++ .../concepts/terraform-best-practices.md | 65 ++++ .../methodologies/general-best-practices.md | 54 +++ .../practicals/argocd-examples.md | 87 +++++ .../concepts/api-best-practices.md | 98 +++++ .../methodologies/general-best-practices.md | 89 +++++ .../practicals/create-api-example.md | 85 ++++ material/overrides/home.html | 279 ++++++++++++++ material/overrides/main.html | 45 +++ mkdocs.yml | 23 +- 22 files changed, 1704 insertions(+), 15 deletions(-) create mode 100644 docs/assets/rise8-planes.webp create mode 100644 docs/blog/gitops.md create mode 100644 docs/blog/platform-wars.md delete mode 100644 docs/blog/sample.md create mode 100644 docs/blog/users.md rename docs/{ => general-engineering}/practice-playbook.md (100%) create mode 100644 docs/platform-engineering/methodologies/general-best-practices.md create mode 100644 docs/platform-engineering/practicals/argocd-examples.md create mode 100644 docs/software-engineering/practicals/create-api-example.md create mode 100644 examples/general-engineering/practice-playbook.md create mode 100644 examples/platform-engineering/methodologies/concepts/argocd-best-practices.md create mode 100644 examples/platform-engineering/methodologies/concepts/kubernetes-best-practices.md create mode 100644 examples/platform-engineering/methodologies/concepts/terraform-best-practices.md create mode 100644 examples/platform-engineering/methodologies/general-best-practices.md create mode 100644 examples/platform-engineering/practicals/argocd-examples.md create mode 100644 examples/software-engineering/methodologies/concepts/api-best-practices.md create mode 100644 examples/software-engineering/methodologies/general-best-practices.md create mode 100644 examples/software-engineering/practicals/create-api-example.md create mode 100644 material/overrides/home.html create mode 100644 material/overrides/main.html diff --git a/docs/assets/rise8-planes.webp b/docs/assets/rise8-planes.webp new file mode 100644 index 0000000000000000000000000000000000000000..3e6560ae4f737000f447f034d0d3ca3c370628d6 GIT binary patch literal 52806 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 TH~c+*7+Rog2C$!RfB*mh$AP9K literal 0 HcmV?d00001 diff --git a/docs/blog/gitops.md b/docs/blog/gitops.md new file mode 100644 index 0000000..0e3a3c6 --- /dev/null +++ b/docs/blog/gitops.md @@ -0,0 +1,53 @@ +# How GitOps intertwines with Continuous Delivery + +## Introduction + +In the ever-evolving landscape of Kubernetes orchestration, managing and deploying applications efficiently is crucial. Enter GitOps, a methodology that leverages the power of version control systems like Git to streamline operations, improve collaboration, and enhance the overall development lifecycle. In this blog post, we'll explore the core principles and best practices of GitOps. + +## What is GitOps? + +GitOps is a set of practices that combine the benefits of declarative infrastructure as code and version control. The primary idea is to use Git repositories as a single source of truth for both application code and infrastructure configuration. This approach brings several advantages to the table, such as: + +- **Declarative Configuration:** Describe the desired state of your infrastructure and applications in a declarative manner, making it easier to understand and manage. + +- **Versioned Control:** Leverage Git's version control capabilities to track changes, rollback to previous states, and collaborate seamlessly with teams. + +- **Continuous Delivery:** Automate deployments by using Git as the trigger for CI/CD pipelines, ensuring a consistent and reproducible process. + +- **Operational Efficiency:** GitOps minimizes manual interventions by relying on automated processes, reducing the risk of human errors and improving operational efficiency. + +## Core Principles of GitOps + +### Declarative Configuration + +In GitOps, the entire infrastructure and application stack are defined declaratively. This means specifying the desired end state rather than prescribing a sequence of steps to reach that state. Tools like Kubernetes manifests, Helm charts, or custom YAML files serve as the declarative configuration, making it easy to understand and manage. + +### Version Control + +Git is at the heart of GitOps. Every change, whether it's a modification to infrastructure configuration or an update to application code, is committed and versioned. This not only provides an audit trail but also enables rollbacks to previous states in case of issues, offering a safety net for operations. + +### Automation + +Automation is a key enabler of GitOps. Continuous Integration (CI) pipelines automatically build, test, and package applications, while Continuous Delivery (CD) pipelines use Git as a trigger to deploy changes to the target environment. This ensures consistency, repeatability, and traceability throughout the development lifecycle. + +### Observability + +GitOps encourages a robust observability practice. By integrating monitoring, logging, and alerting into the deployment process, teams gain insights into the health and performance of applications. This proactive approach allows for quick detection and resolution of issues. + +## Best Practices + +1. **Infrastructure as Code (IaC):** Treat infrastructure as code, using tools like Terraform or Kubernetes manifests. This ensures that changes are versioned, reviewed, and applied consistently. + +2. **Git Workflow:** Adopt a Git branching strategy that aligns with your release and deployment strategy. Consider feature branches for development, main branches for production releases, and tags for versioning. + +3. **Automated Testing:** Implement automated testing at various stages of the pipeline, including unit tests for application code and integration tests for infrastructure changes. This helps catch issues early in the development process. + +4. **Secrets Management:** Use tools or practices for secure storage and management of sensitive information such as API keys and passwords. Avoid storing secrets directly in the Git repository. + +5. **Rollback Strategies:** Plan and document rollback strategies in case of failed deployments. GitOps allows for easy rollbacks by reverting to a previous commit or tag. + +6. **Immutable Infrastructure:** Aim for immutable infrastructure by rebuilding and redeploying entire environments for updates. This ensures consistency and reduces the likelihood of configuration drift. + +## Conclusion + +GitOps brings a paradigm shift to Kubernetes operations by promoting collaboration, automation, and version control. By leveraging Git as the source of truth, teams can enhance visibility, traceability, and reliability in their development and deployment processes. Embrace GitOps practices to navigate the complexities of Kubernetes with confidence and agility. Happy deploying! diff --git a/docs/blog/platform-wars.md b/docs/blog/platform-wars.md new file mode 100644 index 0000000..78833c0 --- /dev/null +++ b/docs/blog/platform-wars.md @@ -0,0 +1,60 @@ +# PaaS vs DIY Kubernetes + +In the current landscape of Kubernetes (k8s), there's a common misconception about whether Kubernetes is a Platform-as-a-Service (PaaS). Kubernetes' own documentation clarifies that it is not a traditional, all-inclusive PaaS system. However, this nuance doesn't make it a drawback; rather, it highlights an important distinction. As Kelsey Hightower puts it, "Kubernetes is for people building platforms." + +## Kubernetes Overview + +Kubernetes is an open-source platform that offers shared services across clusters or nodes, such as scaling, load balancing, or monitoring. Unlike traditional PaaS systems, Kubernetes operates at the container level, providing developers with flexibility in choosing services, resources, and tools. If an application can be containerized, it can run on k8s. + +### What Kubernetes Does + +- Provides flexibility for app developers. +- Operates at the container level, allowing a diverse set of workflows. +- Does not limit the types of applications supported. + +### What Kubernetes Doesn't Do + +- Does not provide services across applications, like databases or storage systems. +- Does not dictate a configuration language, leaving it open for diverse workflows. + +### DIY Kubernetes Pros + +- More out-of-the-box solutions available. +- More flexibility for app developers. +- Ease of containerized application migration. + +### DIY Kubernetes Cons + +- More required of app teams. +- More complex for simple applications. +- Challenges converting legacy applications. +- Flexibility drives compliance complexities. + +## Platform-as-a-Service (PaaS) + +A good PaaS decouples application development and deployment from platform operations, allowing for increased focus on Day 2 operations, improved performance capabilities, and streamlined billing. Cloud Foundry is an example of an open-source PaaS project that, while no longer recommended, provides a frame of reference for what a PaaS should be. + +### PaaS Pros + +- Provides cross-app services. +- Decouples platform and app development. +- Ease of multi-cloud and hybrid approach. +- Structure and opinionation drive simplified controls compliance. + +### PaaS Cons + +- More upfront cost. +- Less flexibility for app teams. +- Larger infrastructure resource requirements. + +## PaaS or K8s? + +Choosing between PaaS and raw Kubernetes depends on organizational needs, infrastructure ownership, and technical competence. Over time, teams using raw k8s tend to build internal structures and opinionation, resembling an internal PaaS. The decision may involve weighing the cost-effectiveness of building in-house solutions versus adopting vendor solutions. + +### Considerations + +- **Lock-in:** In-house solutions also exhibit lock-in, and it's essential to evaluate various forms of lock-in. +- **Costs:** Upfront costs for PaaS may be higher, but it alleviates the burden on application developers. +- **Flexibility:** Kubernetes provides more flexibility but also more responsibility. + +There's no definitive answer; the choice depends on the organization's goals and capabilities. Whether PaaS or DIY Kubernetes, the key is to achieve the desired capabilities for successful application deployment. \ No newline at end of file diff --git a/docs/blog/sample.md b/docs/blog/sample.md deleted file mode 100644 index 6057217..0000000 --- a/docs/blog/sample.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -hide: -- toc ---- - -# Sample -This is a sample blog page. \ No newline at end of file diff --git a/docs/blog/users.md b/docs/blog/users.md new file mode 100644 index 0000000..59f7039 --- /dev/null +++ b/docs/blog/users.md @@ -0,0 +1,27 @@ +# Rise8 Continuous Delivery Approach + +At **Rise8**, our mission revolves around achieving continuous delivery of impactful software that users love. + +## Continuous Delivery: The Feedback Loop + +Continuous delivery forms the feedback loop essential for achieving small batch sizes and iterating towards impactful software that brings joy to users. This process is carried out within a balanced team where the product manager practices lean enterprise, and UX focuses on user-centered design. + +## Continuous Delivery First Approach + +While numerous measures can be taken to mitigate risks, the ultimate validation point is the production environment. Hence, we adopt a continuous delivery first approach to establish learning feedback loops. + +## Leveraging DORA Insights + +We highly value the insights provided by the **DORA (DevOps Research and Assessment)** in identifying the key factors for achieving continuous delivery. We not only adhere to the DORA top five but also incorporate other crucial capabilities they've identified as contributors. This includes automated testing, clean code, loose coupling, monitoring, trunk-based development, and deployment automation, among others. + +## High Compliance Spaces: Ensuring Security and Best Practices + +In high compliance spaces, we are pioneers in ensuring that deployment automation encompasses security compliance and adheres to release engineering best practices. This is particularly crucial due to the sensitivity and complexity of deployment environments. + +## Balancing Capability and Security + +Emphasizing both capability and security, we want to make it clear that continuous delivery doesn't necessitate accepting more risk; in fact, it actively reduces risk. + +## Effective Communication for Stakeholder Buy-In + +Our team possesses the expertise to communicate these principles effectively to both customers and stakeholders. This ensures the necessary buy-in to complete the feedback loops that unlock continuous delivery. diff --git a/docs/practice-playbook.md b/docs/general-engineering/practice-playbook.md similarity index 100% rename from docs/practice-playbook.md rename to docs/general-engineering/practice-playbook.md diff --git a/docs/index.md b/docs/index.md index 55fcc53..607285c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,4 @@ --- -hide: - - navigation - - toc +title: Title +template: home.html --- -# Home -Welcome to Engineering! diff --git a/docs/platform-engineering/methodologies/general-best-practices.md b/docs/platform-engineering/methodologies/general-best-practices.md new file mode 100644 index 0000000..79f1857 --- /dev/null +++ b/docs/platform-engineering/methodologies/general-best-practices.md @@ -0,0 +1,54 @@ +# Platform Playbook + +Platform engineering involves designing, building, and maintaining the infrastructure and tools that enable software development and deployment. Adopting best practices in platform engineering ensures a stable, scalable, and efficient environment for development teams. Here are some detailed best practices: + +## 1. Infrastructure as Code (IaC): + - Use IaC tools like Terraform or Ansible to define and manage infrastructure. + - Version control your IaC scripts to track changes and enable collaboration. + - Implement a modular structure for IaC to promote reusability and maintainability. + +## 2. Containerization: + - Containerize applications using technologies like Docker for consistency across environments. + - Use orchestration tools such as Kubernetes for automated deployment, scaling, and management of containers. + - Optimize container images for size and security. + +## 3. Continuous Integration and Continuous Deployment (CI/CD): + - Implement CI/CD pipelines to automate testing, building, and deployment processes. + - Include automated testing at various stages to catch issues early. + - Use feature flags to enable gradual and safe feature rollouts. + +## 4. Monitoring and Logging: + - Establish comprehensive monitoring for applications and infrastructure. + - Utilize centralized logging to gather and analyze logs for troubleshooting. + - Implement alerting systems to detect and respond to issues proactively. + +## 5. Scalability: + - Design systems to scale horizontally by adding more instances. + - Use auto-scaling groups to automatically adjust resources based on demand. + - Regularly perform load testing to identify potential bottlenecks. + +## 6. Security: + - Implement security best practices for infrastructure and applications. + - Regularly update dependencies and conduct security audits. + - Enforce least privilege access controls and regularly rotate credentials. + +## 7. Documentation: + - Maintain comprehensive documentation for infrastructure, deployment processes, and configurations. + - Keep documentation up-to-date to facilitate knowledge sharing and onboarding. + +## 8. High Availability (HA): + - Design systems with redundancy to ensure availability in case of failures. + - Distribute applications across multiple availability zones or regions. + - Test and simulate failure scenarios to validate HA configurations. + +## 9. Collaboration and Communication: + - Foster collaboration between development, operations, and other teams. + - Use collaboration tools and platforms for effective communication. + - Conduct regular cross-functional meetings to align goals and address challenges. + +## 10. Performance Optimization: + - Regularly assess and optimize the performance of both infrastructure and applications. + - Use caching mechanisms, content delivery networks (CDNs), and other optimization techniques. + - Monitor and optimize database queries for efficiency. + +By adhering to these platform engineering best practices, teams can create a robust and efficient environment that supports the continuous delivery of high-quality software. diff --git a/docs/platform-engineering/practicals/argocd-examples.md b/docs/platform-engineering/practicals/argocd-examples.md new file mode 100644 index 0000000..5aa4ec0 --- /dev/null +++ b/docs/platform-engineering/practicals/argocd-examples.md @@ -0,0 +1,87 @@ +# ArgoCD: Application of ApplicationSets + +An application of ApplicationSets in ArgoCD is to efficiently manage and deploy similar applications or configurations across multiple clusters or namespaces. Here's a specific example to illustrate the application of ApplicationSets: + +## **Scenario** + +Imagine you have a microservices architecture, and you need to deploy the same application stack to multiple namespaces within a Kubernetes cluster. Each namespace may represent a different environment, such as development, testing, and production. + +## **ApplicationSets Implementation** + +### 1. **Generator:** + - Define a generator that generates application names, namespaces, and other parameters based on a specific pattern or set of rules. + + ```yaml + generators: + - list: + elements: + - name: my-app-{{randAlphaNum 5}} + namespace: {{item}} + ``` + +### 2. **Template:** + + - Create a template specifying the common configuration for your application. This includes the source repository, target revision, and destination settings. + + ```yaml + template: + metadata: + labels: + app.kubernetes.io/name: '{{.name}}' + spec: + project: default + source: + repoURL: 'https://github.com/example/repo' + targetRevision: HEAD + destination: + namespace: '{{.namespace}}' + server: 'https://kubernetes.default.svc' + ``` + +### 3. **ApplicationSet Manifest:** + +- Apply the ApplicationSet manifest that defines the generators and template. + + ```yaml + apiVersion: argoproj.io/v1alpha1 + kind: ApplicationSet + metadata: + name: my-app-set + spec: + generators: + - list: + elements: + - dev + - test + - prod + template: + metadata: + labels: + app.kubernetes.io/part-of: my-app-set + spec: + project: default + source: + repoURL: 'https://github.com/example/repo' + targetRevision: HEAD + destination: + server: 'https://kubernetes.default.svc' + ``` + +## **Result** + +- ArgoCD will dynamically generate and deploy three instances of the application, each to a different namespace (dev, test, prod). +- The common configuration specified in the template ensures consistency across all instances. +- Changes made to the ApplicationSet manifest automatically reflect in the generated applications, allowing for easy scaling and maintenance. + +## **Use Cases** + +### 1. **Scalable Deployments:** + - Easily scale deployments across different namespaces or clusters without manually managing each application. + +### 2. **Environment Isolation:** + - Isolate configurations for different environments, ensuring separation and consistency. + +### 3. **Efficient Management:** + - Streamline the deployment of similar applications with minimal manual intervention. + +ApplicationSets in ArgoCD provide a powerful mechanism for handling repetitive deployment scenarios and managing configurations at scale. diff --git a/docs/software-engineering/practicals/create-api-example.md b/docs/software-engineering/practicals/create-api-example.md new file mode 100644 index 0000000..9d403de --- /dev/null +++ b/docs/software-engineering/practicals/create-api-example.md @@ -0,0 +1,85 @@ +# Writing a Simple API with Flask (Python) + +## Introduction + +In this tutorial, we'll walk through the process of creating a simple RESTful API using Python and the Flask web framework. Flask is a lightweight and easy-to-use framework for building web applications, including APIs. + +### Prerequisites + +Before you begin, make sure you have the following installed: + +- Python ([Python Official Website](https://www.python.org/)) +- Flask (`pip install Flask`) + +## Step 1: Setting Up the Project + +Create a new directory for your project and navigate into it. + +```bash +mkdir flask-api-tutorial +cd flask-api-tutorial +``` + +## Step 2: Creating a Virtual Environment +It's good practice to use a virtual environment to isolate your project's dependencies. Create a virtual environment using the following commands: + +```bash +python -m venv venv +# On Windows: python -m venv venv +Activate the virtual environment: +``` + +```bash +# On macOS/Linux +source venv/bin/activate +# On Windows +venv\Scripts\activate +This step ensures that your project has a dedicated environment for its dependencies, minimizing conflicts and ensuring consistency across different projects. +``` + +## Step 3: Installing Flask +Install Flask within the virtual environment: + +```bash +pip install Flask +``` + +## Step 4: Writing the API Code +Create a file named app.py in your project directory and open it in a text editor. Add the following code: + +```python +from flask import Flask, jsonify + +app = Flask(__name__) + +@app.route('/api', methods=['GET']) +def get_data(): + data = {'message': 'Hello, API!'} + return jsonify(data) + +if __name__ == '__main__': + app.run(debug=True) +``` + +This code sets up a basic Flask application with a single endpoint (/api) that returns a JSON response. + +## Step 5: Running the API +In the terminal, run the Flask application: + +```bash +python app.py +Visit http://127.0.0.1:5000/api in your browser or use a tool like curl or Postman to make a GET request. +``` + +```bash +curl http://127.0.0.1:5000/api +You should receive a JSON response: {"message": "Hello, API!"} +``` + +## Conclusion + +Congratulations! You've successfully created a simple API using Flask. This is just a starting point, and you can expand and enhance your API by adding more routes, handling different HTTP methods, and integrating with databases. + +Explore Flask's documentation (Flask Documentation) for more advanced features and best practices. + +Feel free to adapt this tutorial to other frameworks or languages as needed. \ No newline at end of file diff --git a/examples/general-engineering/practice-playbook.md b/examples/general-engineering/practice-playbook.md new file mode 100644 index 0000000..ffcff95 --- /dev/null +++ b/examples/general-engineering/practice-playbook.md @@ -0,0 +1,364 @@ +--- +hide: + - navigation +--- +# Engineering Practice Playbook + +## Preamble +This document contains our opinions on software development. We understand that it is not always possible to hold to some of these standards. We trust each of our engineer's autonomy to respond to any given situation. + +## What is an Engineer? +--- + +An engineer on a balanced team is responsible for the technical delivery of a product to the customer. They focus their time on building a secure, reliable, scalable, and maintainable product. The engineer brings a unique perspective to the team as they best understand the amount of work needed to build features. They also understand the impact technical debt can have on velocity. They work hand in hand with the product manager to buy down risks through backlog prioritization. The engineer also works with the designer to execute a design system and tease out technical pain points from the user. The engineer works with operations to optimize product delivery and support. + +> “A team management philosophy that has people with a variety of skills and perspectives that support each other towards a shared goal.” - balancedteam.org + +## Foundation +**Agile Manifesto Principles** + +1. Our highest priority is to satisfy the customer through early and continuous delivery of valuable software. +2. Welcome changing requirements, even late in development. Agile processes harness change for the customer’s competitive advantage. +3. Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale. +4. Business people and developers must work together daily throughout the project. +5. Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done. +6. The most efficient and effective method of conveying information to and within a development team is face-to-face conversation. +7. Working software is the primary measure of progress. +8. Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely. +9. Continuous attention to technical excellence and good design enhances agility. +10. Simplicity – the art of maximizing the amount of work not done – is essential. +11. The best architectures, requirements, and designs emerge from self-organizing teams. +12. At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly. + +### Rise8 Takes +- Enablement is a primary skillset we practice here at Rise8. Not only building the product but helping build the team's skillset to continue product development. +- Pair engineers with projects they love. +- Offer opportunities for engineers to grow and expand. +- Trust allows agile teams to communicate quickly and respond rapidly to changes as they emerge. Without sufficient trust, team members can waste effort and energy hoarding information, forming cliques, dodging blame, and covering their tracks. +- Trust your team is making the best decisions with the information known at the moment, with or without your presence. You and your team have a common goal, there is more than one way to reach it. +- Technical facts and data overrule opinions and personal preferences. +- Use best practices and design patterns unless justified. +- Adheres to the team's code contract for styling. + + +## Discovery +--- + +### Discovery and Framing +D&F is a team effort where Product Manager and UI/UX roles will contribute significantly. + +### Build vs Buy Analysis +Engineers evaluate existing FOSS, Commercial, and Government Off the Shelf. Below are some helpful questions to get started in exploring your options and their potential return on investment. + +[todo]: # "Separate into groups (Build & Purchase/Use)" + +- Is there an offering that sufficiently meets the team's requirements +- Build, operate, maintain, and upgrade cost Vs buy and licensing cost? +- Do we have the expertise to build? +- What is the learning curve/developer experience of the commercial products? +- Security requirements? +- Will new features be required, can they be added to the buy option? +- How much granular control of the system is necessary? +- Will the buy/FOSS option be maintained long term +- Is the offering well documented/provide a satisfactory user experience? +- Time to market? + + +### Technology Stack +**We choose the right Tech stack for the problem space.** +**Here are a few things to consider when selecting tools and technologies** + +1. Is training necessary? What is the learning curve? How much documentation is available? Is it good documentation? +1. Are the skills and knowledge required common, or is the technology very niche? +1. Is the technology mature enough to adopt? +1. What are the costs? + - compute cost of a low level language + - engineering wage difference between one language to another + - tooling +1. Is there support for the technology within the current continuous integration process? +1. Can the technology be deployed to all environments? +1. Can the technology be managed in all environments? +1. Is the technology stack meeting security criteria and project constraints? +1. Does the technology stack performance, reliability, and maintainability satisfy the product's requirements? +1. Can the technology stack scale? + + +## Building an MVP +--- +Proof of Concept --> Prototype --> MVP + +### Proof of Concept +The Proof of Concept is for quick technical discovery, learning information, and empowering decision-making. It may be comprised of pseudo-code, code-fragments, and/or diagrams that depict how systems communicate or UIs interact. The outcome should validate & verify the concept, and becomes the reference for the prototype. + +Should we use best practices when building a proof of concept? + - Not required, but encouraged + - Use as needed to explain the proposed concept + +### Prototype +The goal of a Prototype is to demo limited functionality to end users in an ideal/sandbox environment and help teams evaluate risk. This becomes a candidate for the initial MVP. Code should follow best practices unless it would be a severe time sink to implement. + +Should we use best practices when building a prototype? +- Should try to use best practices, unless severe time sink + +What types of outcomes/information should the prototype produce? +- Technical discovery +- User traction/Customer feedback + +### MVP +An MVP builds on a Prototype by adding functionality, error handling, and integration with a production environment. + +What defines an MVP? +- Full functionality +- Meets all acceptance criteria + +Should we use best practices when building an MVP? +- Best practices are standardized and required + + +## Systems Design and Architecture +--- + +### Architecture +We will use `SPIKES` in the issue tracking system to document decisions that impact structure, non-functional characteristics, dependencies, interfaces, or construction techniques. A Spike should be short and capture the specific context around the decision. A Spike will have a Title, Status, Context, Decision, and Consequences section. Title Spikes with short Noun phrases such as "SPIKE: Caching with Redis". Status can be selected by the state of the issue in the issue tracking system. Context documents the technical and business forces at play; verbiage should be value neutral. Decision documents the why and how we choose to respond to the forces. Finally, Consequences documents any risks involved with the decision. + +It is good to keep a record of reversed decisions, and why it was reversed. It is common for old failed decisions to resurface without historical knowledge in long-running projects. + +### Design Patterns and Best Practices +We rely heavily on existing best practices and design patterns both for their proven capabilities and providing a common and well known means of solving a problem. Patterns and practices make it easier for engineers to move between projects. However, there may be times we need to deviate such as, the new pattern leading to decreased readability, maintainability, scalability, and/or performance. Note a performance issue in and of itself is not typically enough to justify a deviation. + +[todo]: # "Add resources for existing design patterns" + + +### Technical Debt +Technical debt can be defined as aspects of our code that will slow down future development. Debt can be intentional or unintentional but must be managed. Incurring too much technical debt can lead to a reduction in productivity, maintainability and testability which in turn leads to unhappy employees, decreased organizational performance, and lack of business outcomes. Engineers are responsible for making technical debt visible. Here are a few ways to mitigate and manage technical debt in your products: + +1. Keep a log of debt on your project for future conversations +1. Discuss during backlog grooming +1. Establish coding and documentation standards +1. Familiarize yourself with common design & architecture patterns +1. Be aware of new technologies + +## Ceremonies +--- +### Iterative Planning Meeting (IPM) +[todo]: # "Align with PMs" +The IPM selects the work that will be done in the next cycle typically 1-2 week sprints. It is our recommendation to target work as follows. +**Target ranges** + +- 30% - 50% Feature +- 15% - 30% Innovation/Tech debt sometimes call chore +- 5% - 20% Bugs + +When conducting an IPM the team will address: +**Acceptance Criteria** +Engineers can help the team by reviewing acceptance criteria before the sprint begins. The acceptance criteria should be clear and free of interpretation. + +**Story Point** +Engineers can help the team by helping to point stories. They can help estimate the amount or complexity of the work. Since engineers understand the work involved to fulfill a requirement, they can ensure that stories are granular and right sized. + + +[TODO]: # "define feature, bug Innovation/tech debt" + +**Feature** +A Feature is something that provides new capabilities or improves end user experience. A Feature will often have a story that reads something like this. As a: xxx, I want: xxx, So That xxx. A feature should also have an acceptance criteria or definition of done. + +**Innovation / Refactoring** +Innovation is proactive tech debt management. Innovation work is time spent incorporating **new** libraries, patterns, or services to make the code base easier to maintain, read, secure, and scale, or add capabilities. Innovation work should be closely evaluated to ensure that it provides a return on investment. Avoid innovation for innovation’s sake; there must be clearly definable advantage. + +Refactoring is an opportunity drive down existing technical debt, optimize, and re-architect the codebase. Refactoring keeps code simple, decoupled, easily read, and painlessly scaled. Engineers often complain about old programming languages as if the language is the root problem when the real problem is old messy spaghetti code. + +1. Knowledge sharing (both domain and technical knowledge) +2. Immediate code reviews +3. Improved interpersonal communication +4. Reduction in code defects + + +**Bug** +Any work being done to correct unexpected behaviors or faults that are inconsistent with the desired coded intent. + +**NOTE** +Security is a fundamental part of software development and as such can be characterized to fit in all three of the categories as needed. However, you may to create your own category for security work; this is common in high compliance environments. + +### Standup +A quick 10-15 min meeting typically held at the beginning of the day. Team members will give a **few** sentences on what they accomplished yesterday, are planning to do today, and any blockers they may have. If greater detail is required, coordinate a discussion with the relevant team members post standup. + +### Retro +A meeting to reflect on the past work cycle and identify what worked, what didn't and any actions needed to be taken going forward. Release some stress while looking forward to the making the next work cycle better. This is also a good time to call out your team members on their accomplishments. + +## Pair Programming +We believe there is great value in paired programming and advocate it as the first option. Pairing helps train inexperienced devs, allows for the propagation of tips and techniques, and provides accountability. + +Pair programming is a development technique where two developers author software using the same computer. In person, the computer is outfitted with two keyboards, two monitors and two mice. In a remote environment one user can share the screen with another via collaboration software such as [Zoom](https://zoom.us/) and Live Share. There are two roles in pair programming: + +Driver: The person who is writing the code. +Navigator: Helps the driver navigate the code development process. They can write code in the form of suggestions or corrections. + +Here are few helpful hints when pairing: + +1. Pairing can be tiring; take breaks often +2. Rotate pairs regularly. Each person brings something unique to the table which will improve the codebase as a whole. Swapping pairs also drives both knowledge sharing and alignment across the team. +3. Be open to new ideas and constructive criticism +4. Sometimes pairing might not be the best approach. Feel free to solo when it makes sense. But remember, committed code requires a peer review. + +## Development +--- +### Test Driven Development +Test Driven Development is a software development practice. The process starts with authoring a failing test and then implementing the functionality required for the test to succeed. Often times referred to as “Red Green Refactor”, it consists of three distinct steps (red-green-refactor): + +1. Author a failing test +2. Author just enough code for test to pass +3. Refactor + +### Code Review +The primary purpose of code review is to make sure that the overall code health of the project's codebase is improving over time, and a series of trade-offs have to be balanced. + +First, developers must be able to _make progress_ on their tasks. If you never submit an improvement to the codebase, then the codebase never improves. Also, if a reviewer makes it very difficult for _any_ change to go in, developers are disincentivised to improve in the future. + +Second, the reviewer must ensure that each merge request is of such a quality that their codebase's overall health is not decreasing as time goes on. This can be tricky because codebases degrade through small decreases in code health over time, especially when a team is under significant time constraints and feel that they have to take shortcuts to accomplish their goals. + +A reviewer has ownership and responsibility for the code they are reviewing. They want to ensure that the codebase stays consistent and maintainable. + +Thus, we get the following rule as the standard we expect in code reviews: + +In general, reviewers should favor approving a merge request once it is in a state where it improves the overall code health of the system being worked on, even if the merge request isn't perfect. + +There are limitations to this, of course. For example, if a merge request adds a feature that the reviewer doesn't want in their system, then the reviewer can certainly deny approval even if the code is well-designed. + +A key point here is that there is no such thing as "perfect" code—there is only _better_ code. Reviewers should not require the author to polish every tiny piece of a merge request before approving. Instead, the reviewer should balance out the need to make forward progress compared to the importance of the changes they are suggesting. Instead of seeking perfection, what a reviewer should seek is _continuous improvement_. A merge request that improves the maintainability, readability and understandability of the system shouldn't be delayed because it isn't "perfect." + +Reviewers should _always_ feel free to leave comments expressing that something could be better, but if it's not very important, prefix it with something like "Nit: "to let the author know that it's just a point of polish that they could choose to ignore (Nit means nit-pick). + +Note: Nothing in this document justifies checking in merge requests that _worsen_ the system's overall code health. The only time you would do that would be in an emergency. + +- Aspects of software design are seldom a pure style issue or just a personal preference**.** They are based on underlying principles and should be weighed on those principles, not simply by subjective opinion. Sometimes there are a few valid options. If the author can demonstrate (either through data or based on solid engineering principles) that several approaches are equally good, the reviewer should accept the author's preference. Otherwise, the choice is dictated by standard principles of software design. +- If no other rule applies, then the reviewer may ask the author to be consistent with the current codebase, as long as that doesn't worsen the system's overall code health. +- On matters of style, the style guide is the absolute authority. Any purely style point (whitespace, etc.) not in the style guide is a personal preference. The style should be consistent with what is there. If there is no previous style, accept the author's style. + + +**An opportunity for sharing knowledge** +Code reviews can be an essential function for teaching developers something new about a language, a framework, or general software design principles. It's always OK to leave comments that help a developer learn something new. Sharing knowledge is part of improving the code health of a system over time. Just keep in mind that if your comment is purely educational but not critical to meeting the standards described in this document, prefix it with "Nit:" or otherwise indicate that the author doesn't need to resolve it in this merge request. + + +**Resolving Conflicts** +In any conflict on a code review, the first step should always be for the developer and reviewer to reach an agreement. + +When coming to consensus becomes especially difficult, it can help to have a face-to-face meeting or a video conference between the reviewer and the author, instead of just trying to resolve the conflict through code review comments. (If you do this, though, make sure to record the discussion results as a comment on the merge request for future readers.) + +If that doesn't resolve the situation, the most common way to resolve it would be to escalate. Often the escalation path is to a broader team discussion, having a Technical Lead weigh in, asking for a decision from a maintainer of the code, or asking an Eng Manager to help. + +Don't let a merge request sit around because the author and the reviewer can't agree. + +_This section was derived, with modifications, from [Google Engineering Practices Documentation](https://github.com/google/eng-practices)_ + +## Git ops +--- +Git is today's standard for source control. +### HOOKS +We strongly encourage the use of commit hooks to further ensure code quality. These hooks can range from enforcing commit formats to running unit tests and may be left up to the team to decide. + +### COMMIT MESSAGES +Commit messages should be a brief, concise description in imperative tense of what the commit adds, with the appropriate authors (alternating authors or using tools such as git with .git-together), and the ID of the corresponding story. Using industry standards such as [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) are not required but teams may choose to follow any given industry standard. + +### MERGE REQUEST COMMENTS +We encourage comments/suggestions/questions/discussion/etc. on MR per our belief in strong opinions loosely held >> better resulting code + +### REBASE +We encourage squashing and rebasing to preserve the cleanliness and readability of the git history on the master branch. This should only be performed by an engineer that understands the rebasing process in order to avoid causing irreparable damage to the master branch. If done correctly, there should be no explicit merge commits. + +NOTE: Certain technologies (i.e. GitLab) default behavior creates merge commits. This can be changed. + +### BRANCHING +Trunk based or short-lived feature branching is preferred. + +Branch naming should be clear and concise. We recommend the convention of including the story ID followed by a few words for the branch's purpose, using dashes (-) as the delimiter. + +Cleanup/remove branches post merge completion. Developers should be wary and not have too many inactive/stale branches linger. Abandoned branches should be removed to avoid Git pollution. + + +## CI/CD Pipeline +--- +**Continuous Integration** +We believe CI begins at the local development env. This includes the tools to run automated tests, linting, and other checks on branches **BEFORE** you merge up. + +We believe CI is non-negotiable and must begin at the initial conception of development to ensure comprehensive software security, testing, and fast feedback on the main branch health. Furthermore, it empowers the ability of the team to hold to agile practices. + +**CI stages should include at a minimum** +- linting +- unit tests +- static code analysis +- dependency scans + +**Continuous Delivery** +We believe that any merge to main should be able to deploy to production and main should always be deployable. Merges should be self-contained and not dependant upon another branch. + +[TODO]: # "Expand the section on CI" + +## Testing +--- +Building testing into our products provides us the confidence that we need to quickly deliver new features without the fear of breaking our products. The test pyramid depicts the types of test we can author along with the general distribution. + +### Unit +The unit test is designed to test a small, singular component/function/method. Target the public methods of your classes, private and protected methods are part of the public unit. The tests are easy to author and maintain, and are fast to run. Unit Tests represent the largest portion of tests within the code. + +### Contract Testing +TDD for microservice architecture contracts are written on what will be consumed and then consumers and producers are tested against these contracts. Eliminates the need for test environments that have all services running and at a specific version. + +### Integration +The integration test is designed to test between components. A typical example might be integrating with a database or a provided REST service. Integration tests require that you stand up not only your product but also the components with which you integrate. For this reason, they require more time and effort than unit tests. They are often times the second most frequently used test. + +### End to End (E2E) +The end-to-end test is designed to test through your stack starting at the front end. The tests require the most time and effort to write and maintain. For this reason, they often represent the smallest portion of your tests. + +[TODO]: # "Add Acceptance test blurb" + +For further reading take a look at the list of curated resources + +* [https://martinfowler.com/articles/practical-test-pyramid.html](https://martinfowler.com/articles/practical-test-pyramid.html) + +## Operating Apps +--- +### Logging (Operating apps) +As you ship your application into production you want to make sure that your logs can be processed and aggregated easily. Designing your application in this fashion will allow the platform to treat all application logs the same. Additionally, it allows for providing a base set of services your organization will need to support and operate your application. A few examples include, access to logs for debugging as well as setting up alerts for monitoring. The standard practice is to write log entries to stdout. For further information, check out the [logs](https://12factor.net/logs) section on [12factor.net](https://12factor.net/) + +### Configuration (Design) +Your application will exist in numerous environments including development, staging and production. For this reason, it is important that your application can be configured easily. Keep in mind that your application is likely to end up on a platform like Kubernetes where managing the lifecycle of an application is significant. The standard practice is to expose configuration via granular environment variables. The configuration defines a contract with the tools that manages your application’s lifetime. For further information, check out the [config](https://12factor.net/config) section on [12factor.net](https://12factor.net/) + + +### Backing Services (Design) +As you build out your application, there will be a set of services you wish to consume. You should consider what services are needed and if they are provided as part of the platform offering. Configuring these services is as simple as adding environment variables to your configuration (see above). Listed below are common services: + +1. Identity Management (ie Keycloak) +1. Databases (ie Relational, NoSQL) +1. Storage (ie S3, Minio, Volumes) +1. Message Queues (ie RabbitMQ, Kafka) +1. Email (ie SMTP) + +### Monitoring (Operating) +Monitoring your application will help you be successful. Monitoring can help you understand how your application is being used and by whom. Monitoring can help you understand whether your application is functioning. When you start building your application consider the following: + +1. Are health endpoints available in my application? What engineering aspects should be part of the health endpoint? How are the health endpoints monitored? +2. Are there important product metrics to capture? Are there any technologies available to support metrics collection (ie Elasticsearch, Kibana, Grafana)? +3. Are there technologies available to support alerting? + + +## Additional Resources +--- +* [https://12factor.net](https://12factor.net/) + + +## Recommended Reads +--- +* [Clean Code by Robert C. Martin](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882) +* [Composing Software by Eric Elliot](https://www.amazon.com/Composing-Software-Exploration-Programming-Composition/dp/1661212565) +* [Design Patterns by Gang of Four](https://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional-ebook/dp/B000SEIBB8) +* [Pragmatic Programmer](https://www.amazon.com/Pragmatic-Programmer-Anniversary-Journey-Mastery/dp/B0833FBNHV/ref=sr_1_1?dchild=1&gclid=Cj0KCQiAst2BBhDJARIsAGo2ldUUR4IfnxCjch0ni9ici1HmmtCYjITL9ghoHWfJRZJjlTOXIRdR5DEaAiXrEALw_wcB&hvadid=241894030769&hvdev=c&hvlocphy=9008585&hvnetw=g&hvqmt=e&hvrand=15887975436101901235&hvtargid=kwd-131403882&hydadcr=16400_10303601&keywords=pragmatic+programmer&qid=1614290816&sr=8-1&tag=googhydr-20) +* [Event-Driven Microservices](https://www.oreilly.com/library/view/building-event-driven-microservices/9781492057888/) + + +## Notes + +[^1]: +Accelerate + +[^2]: +Accelerate diff --git a/examples/platform-engineering/methodologies/concepts/argocd-best-practices.md b/examples/platform-engineering/methodologies/concepts/argocd-best-practices.md new file mode 100644 index 0000000..1de46cf --- /dev/null +++ b/examples/platform-engineering/methodologies/concepts/argocd-best-practices.md @@ -0,0 +1,61 @@ +# ArgoCD Best Practices + +[ArgoCD](https://argoproj.github.io/argo-cd/) is a declarative, GitOps continuous delivery tool for Kubernetes. To ensure optimal use and management, consider the following best practices: + +## 1. Declarative Configuration: + - Use ArgoCD to manage Kubernetes manifests declaratively through Git repositories. + - Store all application and environment configurations in version-controlled repositories. + +## 2. Repository Structure: + - Organize your Git repositories logically, separating applications and environments. + - Follow a directory structure that reflects the hierarchy of your clusters and applications. + +## 3. Sync and Health Status: + - Regularly monitor the synchronization status of applications. + - Leverage the ArgoCD UI or CLI to check the health status of your applications. + +## 4. Automated Sync Policies: + - Configure automated synchronization policies based on your deployment requirements. + - Set up periodic syncs to ensure that the desired state is continuously maintained. + +## 5. Promotion Workflow: + - Implement a promotion workflow through different Git branches (e.g., `dev`, `staging`, `production`). + - Use ArgoCD AppProject to define access control policies for different environments. + +## 6. Helm and Kustomize Support: + - Utilize Helm charts or Kustomize for managing complex application configurations. + - ArgoCD natively supports Helm charts and Kustomize overlays. + +## 7. Secret Management: + - Securely manage sensitive information like secrets and credentials outside of the Git repository. + - Integrate with external secret management tools and Kubernetes Secret resources. + +## 8. Rollback and Roll-forward: + - Test and document rollback procedures for easy recovery in case of issues. + - Embrace roll-forward by applying corrections or updates instead of reverting changes. + +## 9. Monitoring and Alerts: + - Set up monitoring for ArgoCD itself using tools like Prometheus and Grafana. + - Define alerts to notify teams about synchronization failures or other critical issues. + +## 10. RBAC and Security: + - Implement Role-Based Access Control (RBAC) to control access to ArgoCD resources. + - Regularly review and update RBAC policies based on team changes. + +## 11. Custom Resource Definitions (CRDs): + - Leverage ArgoCD's Custom Resource Definitions (CRDs) to define and manage applications. + - Understand and use ArgoCD-specific features like AppProject for advanced application management. + +## 12. Backup and Restore: + - Periodically back up the ArgoCD server's data, including the configuration and application state. + - Have a well-documented process for restoring ArgoCD from backups. + +## 13. Documentation: + - Maintain comprehensive documentation on ArgoCD usage, configurations, and best practices. + - Provide guidance on common tasks, troubleshooting, and onboarding. + +## 14. Community Engagement: + - Stay informed about ArgoCD updates, releases, and community discussions. + - Contribute to the ArgoCD community and share experiences and best practices. + +By adhering to these ArgoCD best practices, teams can effectively manage Kubernetes applications, streamline deployment workflows, and ensure a robust GitOps-based continuous delivery process. diff --git a/examples/platform-engineering/methodologies/concepts/kubernetes-best-practices.md b/examples/platform-engineering/methodologies/concepts/kubernetes-best-practices.md new file mode 100644 index 0000000..302b5a4 --- /dev/null +++ b/examples/platform-engineering/methodologies/concepts/kubernetes-best-practices.md @@ -0,0 +1,89 @@ +# Kubernetes Best Practices + +## Cluster Architecture + +- **High Availability:** + - Design clusters with high availability in mind to minimize downtime. + - Distribute nodes across multiple availability zones. + +- **Networking:** + - Use a well-defined network architecture. + - Leverage Network Policies to control pod-to-pod communication. + +## Resource Management + +- **Resource Requests and Limits:** + - Set resource requests and limits for containers to ensure fair resource allocation. + +- **Horizontal Pod Autoscaling (HPA):** + - Implement HPA for automatic scaling based on resource usage. + +## Pod Design + +- **Single Responsibility Principle:** + - Design pods to have a single responsibility. + - Avoid running multiple applications in a single pod. + +- **Health Probes:** + - Use readiness and liveness probes to enhance pod reliability. + +## Service Communication + +- **Service Discovery:** + - Leverage Kubernetes Services for service discovery. + - Use DNS names to communicate between services. + +- **Ingress Controllers:** + - Implement Ingress controllers for managing external access to services. + +## Configuration Management + +- **ConfigMaps and Secrets:** + - Use ConfigMaps for configuration data. + - Store sensitive information in Secrets. + +- **Immutable Infrastructure:** + - Treat containers as immutable and avoid modifying them at runtime. + +## Security + +- **Role-Based Access Control (RBAC):** + - Implement RBAC to control access to resources. + - Assign the principle of least privilege. + +- **Pod Security Policies:** + - Enforce security policies using Pod Security Policies. + +- **Network Policies:** + - Define Network Policies to control traffic between pods. + +## Monitoring and Logging + +- **Prometheus and Grafana:** + - Set up monitoring with Prometheus for metrics and Grafana for visualization. + +- **Centralized Logging:** + - Use centralized logging solutions for aggregating logs. + +## Scaling + +- **Vertical Scaling:** + - Use vertical scaling for individual nodes. + +- **Horizontal Scaling:** + - Implement horizontal scaling for application components. + +## Upgrades and Maintenance + +- **Rolling Updates:** + - Perform rolling updates to minimize downtime during application updates. + +- **Backup and Restore:** + - Regularly backup critical data and practice restores. + +## Documentation + +- **Maintain Documentation:** + - Keep comprehensive documentation for configurations, deployments, and best practices. + - Include information about troubleshooting and recovery procedures. + diff --git a/examples/platform-engineering/methodologies/concepts/terraform-best-practices.md b/examples/platform-engineering/methodologies/concepts/terraform-best-practices.md new file mode 100644 index 0000000..1e40499 --- /dev/null +++ b/examples/platform-engineering/methodologies/concepts/terraform-best-practices.md @@ -0,0 +1,65 @@ +# Terraform Best Practices + +[Terraform](https://www.terraform.io/) is an Infrastructure as Code (IaC) tool that allows for the provisioning and management of infrastructure in a declarative and version-controlled manner. To optimize the usage of Terraform, follow these best practices: + +## 1. Infrastructure as Code (IaC): + - Define infrastructure using Terraform code to capture the desired state. + - Store Terraform configurations in version-controlled repositories for traceability and collaboration. + +## 2. Directory Structure: + - Organize Terraform code into modular and reusable directories. + - Follow a structured layout for different environments (e.g., `dev`, `staging`, `production`). + +## 3. Variables and Input Parameters: + - Use variables to parameterize configurations for flexibility. + - Leverage input parameter files to separate sensitive information from the code. + +## 4. Remote State Storage: + - Store Terraform remote state in a centralized and secure backend (e.g., AWS S3, Azure Storage). + - Enable versioning and locking to manage state changes collaboratively. + +## 5. Module Usage: + - Create modular and shareable Terraform modules for common components. + - Reuse modules across different projects to promote consistency. + +## 6. Naming Conventions: + - Establish clear and consistent naming conventions for resources. + - Use variables for resource names to enable easy customization. + +## 7. Documentation: + - Maintain documentation for Terraform configurations, including resource descriptions and variable usage. + - Include information about the purpose, inputs, and outputs of each module. + +## 8. Versioning: + - Version control Terraform configurations using a VCS (Version Control System) like Git. + - Tag releases and changes for better tracking and rollback capabilities. + +## 9. State Locking: + - Enable state locking to prevent concurrent modifications and potential conflicts. + - Implement a mechanism for unlocking the state in case of failures. + +## 10. Backends and Workspaces: + - Use Terraform backends to store state remotely. + - Leverage workspaces for managing multiple environments within a single configuration. + +## 11. Sensitive Data Handling: + - Avoid hardcoding sensitive data directly in Terraform code. + - Use environment variables or secure input files for managing sensitive information. + +## 12. Testing and Validation: + - Implement automated testing for Terraform configurations using tools like `terraform validate` and `tflint`. + - Use Terratest for more comprehensive integration testing. + +## 13. Logging and Monitoring: + - Implement logging for Terraform executions to capture changes and potential issues. + - Utilize monitoring tools to detect infrastructure changes and performance metrics. + +## 14. Continuous Integration (CI) and Continuous Deployment (CD): + - Integrate Terraform into CI/CD pipelines for automated testing and deployment. + - Automate the approval process for Terraform changes to streamline the release cycle. + +## 15. Education and Training: + - Provide training for team members on Terraform best practices. + - Foster a culture of learning and continuous improvement. + +By adhering to these Terraform best practices, teams can create and manage infrastructure efficiently, ensuring scalability, maintainability, and collaboration in an IaC environment. diff --git a/examples/platform-engineering/methodologies/general-best-practices.md b/examples/platform-engineering/methodologies/general-best-practices.md new file mode 100644 index 0000000..79f1857 --- /dev/null +++ b/examples/platform-engineering/methodologies/general-best-practices.md @@ -0,0 +1,54 @@ +# Platform Playbook + +Platform engineering involves designing, building, and maintaining the infrastructure and tools that enable software development and deployment. Adopting best practices in platform engineering ensures a stable, scalable, and efficient environment for development teams. Here are some detailed best practices: + +## 1. Infrastructure as Code (IaC): + - Use IaC tools like Terraform or Ansible to define and manage infrastructure. + - Version control your IaC scripts to track changes and enable collaboration. + - Implement a modular structure for IaC to promote reusability and maintainability. + +## 2. Containerization: + - Containerize applications using technologies like Docker for consistency across environments. + - Use orchestration tools such as Kubernetes for automated deployment, scaling, and management of containers. + - Optimize container images for size and security. + +## 3. Continuous Integration and Continuous Deployment (CI/CD): + - Implement CI/CD pipelines to automate testing, building, and deployment processes. + - Include automated testing at various stages to catch issues early. + - Use feature flags to enable gradual and safe feature rollouts. + +## 4. Monitoring and Logging: + - Establish comprehensive monitoring for applications and infrastructure. + - Utilize centralized logging to gather and analyze logs for troubleshooting. + - Implement alerting systems to detect and respond to issues proactively. + +## 5. Scalability: + - Design systems to scale horizontally by adding more instances. + - Use auto-scaling groups to automatically adjust resources based on demand. + - Regularly perform load testing to identify potential bottlenecks. + +## 6. Security: + - Implement security best practices for infrastructure and applications. + - Regularly update dependencies and conduct security audits. + - Enforce least privilege access controls and regularly rotate credentials. + +## 7. Documentation: + - Maintain comprehensive documentation for infrastructure, deployment processes, and configurations. + - Keep documentation up-to-date to facilitate knowledge sharing and onboarding. + +## 8. High Availability (HA): + - Design systems with redundancy to ensure availability in case of failures. + - Distribute applications across multiple availability zones or regions. + - Test and simulate failure scenarios to validate HA configurations. + +## 9. Collaboration and Communication: + - Foster collaboration between development, operations, and other teams. + - Use collaboration tools and platforms for effective communication. + - Conduct regular cross-functional meetings to align goals and address challenges. + +## 10. Performance Optimization: + - Regularly assess and optimize the performance of both infrastructure and applications. + - Use caching mechanisms, content delivery networks (CDNs), and other optimization techniques. + - Monitor and optimize database queries for efficiency. + +By adhering to these platform engineering best practices, teams can create a robust and efficient environment that supports the continuous delivery of high-quality software. diff --git a/examples/platform-engineering/practicals/argocd-examples.md b/examples/platform-engineering/practicals/argocd-examples.md new file mode 100644 index 0000000..5aa4ec0 --- /dev/null +++ b/examples/platform-engineering/practicals/argocd-examples.md @@ -0,0 +1,87 @@ +# ArgoCD: Application of ApplicationSets + +An application of ApplicationSets in ArgoCD is to efficiently manage and deploy similar applications or configurations across multiple clusters or namespaces. Here's a specific example to illustrate the application of ApplicationSets: + +## **Scenario** + +Imagine you have a microservices architecture, and you need to deploy the same application stack to multiple namespaces within a Kubernetes cluster. Each namespace may represent a different environment, such as development, testing, and production. + +## **ApplicationSets Implementation** + +### 1. **Generator:** + - Define a generator that generates application names, namespaces, and other parameters based on a specific pattern or set of rules. + + ```yaml + generators: + - list: + elements: + - name: my-app-{{randAlphaNum 5}} + namespace: {{item}} + ``` + +### 2. **Template:** + + - Create a template specifying the common configuration for your application. This includes the source repository, target revision, and destination settings. + + ```yaml + template: + metadata: + labels: + app.kubernetes.io/name: '{{.name}}' + spec: + project: default + source: + repoURL: 'https://github.com/example/repo' + targetRevision: HEAD + destination: + namespace: '{{.namespace}}' + server: 'https://kubernetes.default.svc' + ``` + +### 3. **ApplicationSet Manifest:** + +- Apply the ApplicationSet manifest that defines the generators and template. + + ```yaml + apiVersion: argoproj.io/v1alpha1 + kind: ApplicationSet + metadata: + name: my-app-set + spec: + generators: + - list: + elements: + - dev + - test + - prod + template: + metadata: + labels: + app.kubernetes.io/part-of: my-app-set + spec: + project: default + source: + repoURL: 'https://github.com/example/repo' + targetRevision: HEAD + destination: + server: 'https://kubernetes.default.svc' + ``` + +## **Result** + +- ArgoCD will dynamically generate and deploy three instances of the application, each to a different namespace (dev, test, prod). +- The common configuration specified in the template ensures consistency across all instances. +- Changes made to the ApplicationSet manifest automatically reflect in the generated applications, allowing for easy scaling and maintenance. + +## **Use Cases** + +### 1. **Scalable Deployments:** + - Easily scale deployments across different namespaces or clusters without manually managing each application. + +### 2. **Environment Isolation:** + - Isolate configurations for different environments, ensuring separation and consistency. + +### 3. **Efficient Management:** + - Streamline the deployment of similar applications with minimal manual intervention. + +ApplicationSets in ArgoCD provide a powerful mechanism for handling repetitive deployment scenarios and managing configurations at scale. diff --git a/examples/software-engineering/methodologies/concepts/api-best-practices.md b/examples/software-engineering/methodologies/concepts/api-best-practices.md new file mode 100644 index 0000000..85d313c --- /dev/null +++ b/examples/software-engineering/methodologies/concepts/api-best-practices.md @@ -0,0 +1,98 @@ +# API Development Best Practices + + +## Design Principles + +#### **RESTful Principles:** + - Follow RESTful design principles for a standardized and predictable API. + +#### **Consistency:** + - Maintain consistency in naming conventions, response formats, and URI structures. + +## Endpoint Design + +#### **Meaningful URIs:** + - Use meaningful and resource-oriented URIs. + - Avoid exposing implementation details in URIs. + +#### **Resource Naming:** + - Choose clear and concise resource names. + - Utilize plural nouns for resource names. + +## Request and Response + +#### **HTTP Methods:** + - Use appropriate HTTP methods (GET, POST, PUT, DELETE) for CRUD operations. + +#### **Request Payloads:** + - Keep request payloads simple and well-structured. + - Prefer JSON format for request and response payloads. + +#### **Response Status Codes:** + - Use standard HTTP status codes to convey the result of the request. + +## Authentication and Authorization + +#### **Token-based Authentication:** + - Implement token-based authentication for secure API access. + - Utilize industry-standard authentication protocols like OAuth. + +#### **Role-Based Access Control (RBAC):** + - Enforce RBAC to control access to API resources. + - Limit access based on user roles. + +## Error Handling + +#### **Consistent Error Format:** + - Use a consistent format for error responses. + - Include error codes, messages, and details in error responses. + +#### **HTTP Status Codes:** + - Choose appropriate HTTP status codes for different error scenarios. + +## Versioning + +#### **Semantic Versioning:** + - Apply semantic versioning to API versions. + - Clearly communicate version changes in the API. + +#### **Backward Compatibility:** + - Strive for backward compatibility to minimize disruptions for existing clients. + +## Documentation + +#### **Swagger/OpenAPI:** + - Generate API documentation using Swagger or OpenAPI. + - Include clear examples and use cases in documentation. + +#### **Interactive Documentation:** + - Provide interactive documentation with sample requests and responses. + +## Testing + +#### **Unit Testing:** + - Implement unit tests for individual API components. + - Utilize testing frameworks for automated testing. + +#### **Integration Testing:** + - Perform integration testing to ensure components work together seamlessly. + +## Security + +#### **SSL/TLS Encryption:** + - Enforce SSL/TLS encryption to secure data in transit. + +#### **Input Validation:** + - Validate and sanitize input to prevent security vulnerabilities. + +## Performance + +#### **Caching:** + - Implement caching mechanisms to enhance API performance. + +#### **Pagination:** + - Use pagination for large data sets to optimize response times. + +#### **Rate Limiting:** + - Enforce rate limiting to prevent abuse and ensure fair usage. + diff --git a/examples/software-engineering/methodologies/general-best-practices.md b/examples/software-engineering/methodologies/general-best-practices.md new file mode 100644 index 0000000..8cb3cc8 --- /dev/null +++ b/examples/software-engineering/methodologies/general-best-practices.md @@ -0,0 +1,89 @@ +# SWE Playbook + +## Introduction + +This playbook outlines best practices for software engineering (SWE) to ensure high-quality, maintainable, and efficient code. + +## Coding Standards + +### 1. Consistent Code Formatting + +Follow a consistent code formatting style across the codebase. Consider using automated tools like linters and formatters. + +### 2. Descriptive Variable and Function Naming + +Use meaningful and descriptive names for variables and functions to enhance code readability. + +### 3. Modularity + +Design code with modularity in mind. Break down large modules into smaller, reusable components for better maintainability. + +### 4. Version Control + +Utilize version control systems (e.g., Git) effectively. Commit frequently, write clear commit messages, and branch logically. + +## Development Practices + +### 5. Test-Driven Development (TDD) + +Adopt TDD practices. Write tests before implementing new features to ensure code correctness and maintainability. + +### 6. Code Reviews + +Conduct regular code reviews to catch bugs, ensure adherence to coding standards, and promote knowledge sharing among team members. + +### 7. Pair Programming + +Encourage pair programming to enhance collaboration, share knowledge, and catch issues early in the development process. + +### 8. Continuous Integration and Continuous Deployment (CI/CD) + +Implement CI/CD pipelines to automate testing, integration, and deployment processes, ensuring faster and reliable software delivery. + +## Documentation + +### 9. Inline Comments + +Use clear and concise inline comments to explain complex sections of code, making it easier for developers to understand. + +### 10. Readme Files + +Maintain well-documented Readme files that provide essential information about the project, including setup instructions, dependencies, and usage guidelines. + +### 11. API Documentation + +For projects with APIs, generate and maintain comprehensive API documentation to assist developers in integrating and using the APIs. + +## Security + +### 12. Regular Security Audits + +Conduct regular security audits to identify and address potential vulnerabilities in the codebase. + +### 13. Input Validation + +Implement robust input validation mechanisms to protect against common security threats like injection attacks. + +## Performance Optimization + +### 14. Code Profiling + +Regularly profile code to identify performance bottlenecks and optimize critical sections for improved efficiency. + +### 15. Resource Management + +Optimize resource usage, including memory and CPU, to ensure efficient performance. + +## Continuous Learning + +### 16. Knowledge Sharing + +Encourage knowledge sharing sessions within the team to stay updated on industry best practices, new technologies, and advancements. + +### 17. Training and Development + +Invest in continuous training and development opportunities for team members to enhance their skills and stay current. + +## Conclusion + +By following these best practices, we aim to create a collaborative, efficient, and sustainable software development environment. Regularly review and update these practices to align with evolving industry standards and project requirements. diff --git a/examples/software-engineering/practicals/create-api-example.md b/examples/software-engineering/practicals/create-api-example.md new file mode 100644 index 0000000..9d403de --- /dev/null +++ b/examples/software-engineering/practicals/create-api-example.md @@ -0,0 +1,85 @@ +# Writing a Simple API with Flask (Python) + +## Introduction + +In this tutorial, we'll walk through the process of creating a simple RESTful API using Python and the Flask web framework. Flask is a lightweight and easy-to-use framework for building web applications, including APIs. + +### Prerequisites + +Before you begin, make sure you have the following installed: + +- Python ([Python Official Website](https://www.python.org/)) +- Flask (`pip install Flask`) + +## Step 1: Setting Up the Project + +Create a new directory for your project and navigate into it. + +```bash +mkdir flask-api-tutorial +cd flask-api-tutorial +``` + +## Step 2: Creating a Virtual Environment +It's good practice to use a virtual environment to isolate your project's dependencies. Create a virtual environment using the following commands: + +```bash +python -m venv venv +# On Windows: python -m venv venv +Activate the virtual environment: +``` + +```bash +# On macOS/Linux +source venv/bin/activate +# On Windows +venv\Scripts\activate +This step ensures that your project has a dedicated environment for its dependencies, minimizing conflicts and ensuring consistency across different projects. +``` + +## Step 3: Installing Flask +Install Flask within the virtual environment: + +```bash +pip install Flask +``` + +## Step 4: Writing the API Code +Create a file named app.py in your project directory and open it in a text editor. Add the following code: + +```python +from flask import Flask, jsonify + +app = Flask(__name__) + +@app.route('/api', methods=['GET']) +def get_data(): + data = {'message': 'Hello, API!'} + return jsonify(data) + +if __name__ == '__main__': + app.run(debug=True) +``` + +This code sets up a basic Flask application with a single endpoint (/api) that returns a JSON response. + +## Step 5: Running the API +In the terminal, run the Flask application: + +```bash +python app.py +Visit http://127.0.0.1:5000/api in your browser or use a tool like curl or Postman to make a GET request. +``` + +```bash +curl http://127.0.0.1:5000/api +You should receive a JSON response: {"message": "Hello, API!"} +``` + +## Conclusion + +Congratulations! You've successfully created a simple API using Flask. This is just a starting point, and you can expand and enhance your API by adding more routes, handling different HTTP methods, and integrating with databases. + +Explore Flask's documentation (Flask Documentation) for more advanced features and best practices. + +Feel free to adapt this tutorial to other frameworks or languages as needed. \ No newline at end of file diff --git a/material/overrides/home.html b/material/overrides/home.html new file mode 100644 index 0000000..c440ac8 --- /dev/null +++ b/material/overrides/home.html @@ -0,0 +1,279 @@ + + +{% extends "main.html" %} +{% block tabs %} +{{ super() }} + + + +
+
+
+
+ +
+
+

The Rise8 Playbook

+

Move at the speed your users demand.

+ + Get started + + + Go to GitHub + +
+
+
+
+ + +
+
+

+ + + + Engineering Best Practices +

+

Documentation to help all engineers strive for excellence and promote standardization across the organization.

+
+
+

+ + + Practical Examples +

+

Draw from the vast experience of engineers across the company to help you make sustainable decisions.

+
+
+

+ + Blog Posts +

+

Dive into concepts and thoughts that have proved valuable to Rise8 quest to achieve continous delivery.

+
+
+ +
+
+
+
+ + +{% endblock %} +{% block content %}{% endblock %} +{% block footer %}{% endblock %} diff --git a/material/overrides/main.html b/material/overrides/main.html new file mode 100644 index 0000000..ce92dc1 --- /dev/null +++ b/material/overrides/main.html @@ -0,0 +1,45 @@ + +{% extends "base.html" %} + + +{% block libs %} + +{% endblock %} + + +{% block footer %} + +{% endblock %} diff --git a/mkdocs.yml b/mkdocs.yml index 4e57abb..b6b9257 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,11 +2,28 @@ site_name: Engineering site_url: https://engineering.rise8.us nav: - Home: index.md - - Practice Playbook: practice-playbook.md + - General Practices: general-engineering/practice-playbook.md + - Platform Engineering: + - Methodology: + - platform-engineering/methodologies/general-best-practices.md + # - Concepts: + # - platform-engineering/methodologies/concepts/argocd-best-practices.md + - Practical Examples: + - platform-engineering/practicals/argocd-examples.md + # - Software Engineering: + # - Methodology: + # - software-engineering/methodologies/general-best-practices.md + # - Concepts: + # - software-engineering/methodologies/concepts/api-best-practices.md + # - Practical Examples: + # - software-engineering/practicals/create-api-example.md - Blog: - - blog/sample.md - - Company: https://rise8.us + - blog/gitops.md + - blog/platform-wars.md + - blog/users.md + - Company: https://rise8.us theme: + custom_dir: material/overrides name: material logo: logo-rise8.svg favicon: https://rise8.us/images/favicons/cropped-rise8-favicon-32x32.png