Devops
DevopsIntermediate

Platform Engineering: Building Modern Developer Platforms

DevHub Team
5 min read
Platform EngineeringDevOpsCloud NativeDeveloper Experience

TL;DR

Master Platform Engineering with this comprehensive guide covering internal developer platforms, self-service capabilities, and best practices for modern software delivery

Platform Engineering: Building Modern Developer Platforms

Platform Engineering focuses on building and maintaining scalable, self-service platforms that enhance developer productivity and operational efficiency. This guide explores the principles, patterns, and practices for creating effective internal developer platforms.

$1

``mermaid

graph TB

subgraph "Developer Experience"

A[Self-service Portal]

B[CLI Tools]

C[API Gateway]

end

subgraph "Platform Core"

D[Service Catalog]

E[Policy Engine]

F[Automation Engine]

end

subgraph "Infrastructure"

G[Cloud Resources]

H[Kubernetes Clusters]

I[Database Services]

end

A --> C

B --> C

C --> D

D --> E

E --> F

F --> G

F --> H

F --> I

classDef dev fill:#1a73e8,stroke:#fff,color:#fff

classDef core fill:#34a853,stroke:#fff,color:#fff

classDef infra fill:#fbbc04,stroke:#fff,color:#fff

class A,B,C dev

class D,E,F core

class G,H,I infra

`

$1

$1

`yaml

service-catalog.yaml

apiVersion: backstage.io/v1alpha1

kind: Component

metadata:

name: web-service

description: Web Service Template

tags:

- nodejs

- typescript

spec:

type: service

lifecycle: production

owner: team-a

system: web-platform

providesApis:

- web-api

consumesApis:

- auth-api

dependsOn:

- resource:database

- resource:cache

`

$1

`typescript

// infrastructure.ts

import * as pulumi from "@pulumi/pulumi";

import * as aws from "@pulumi/aws";

import * as k8s from "@pulumi/kubernetes";

export class ServiceInfrastructure extends pulumi.ComponentResource {

constructor(name: string, args: any, opts?: pulumi.ComponentResourceOptions) {

super("custom:service:Infrastructure", name, args, opts);

// Create VPC

const vpc = new aws.ec2.Vpc(${name}-vpc, {

cidrBlock: "10.0.0.0/16",

enableDnsHostnames: true,

enableDnsSupport: true,

});

// Create EKS Cluster

const cluster = new aws.eks.Cluster(${name}-cluster, {

roleArn: args.roleArn,

vpcConfig: {

subnetIds: vpc.publicSubnets.map(s => s.id),

},

});

// Deploy Service

const deployment = new k8s.apps.v1.Deployment(${name}-deployment, {

metadata: { namespace: args.namespace },

spec: {

replicas: 3,

selector: { matchLabels: { app: name } },

template: {

metadata: { labels: { app: name } },

spec: {

containers: [{

name: "app",

image: args.image,

ports: [{ containerPort: 8080 }],

}],

},

},

},

}, { provider: new k8s.Provider("k8s", { kubeconfig: cluster.kubeconfig }) });

}

}

`

$1

$1

`rego

policy.rego

package platform.policy

default allow = false

Allow only approved base images

allow {

input.request.kind == "Deployment"

image := input.request.object.spec.template.spec.containers[_].image

startswith(image, "approved-registry.com/")

}

Enforce resource quotas

deny[msg] {

input.request.kind == "Deployment"

container := input.request.object.spec.template.spec.containers[_]

not container.resources.limits.cpu

msg := "CPU limits are required"

}

`

$1

`yaml

rbac.yaml

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

name: developer-role

namespace: apps

rules:

  • apiGroups: ["", "apps"]
  • resources: ["deployments", "services"]

    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

    ---

    apiVersion: rbac.authorization.k8s.io/v1

    kind: RoleBinding

    metadata:

    name: developer-binding

    namespace: apps

    subjects:

  • kind: Group
  • name: developers

    apiGroup: rbac.authorization.k8s.io

    roleRef:

    kind: Role

    name: developer-role

    apiGroup: rbac.authorization.k8s.io

    `

    $1

    $1

    `yaml

    tekton-pipeline.yaml

    apiVersion: tekton.dev/v1beta1

    kind: Pipeline

    metadata:

    name: service-pipeline

    spec:

    workspaces:

    - name: shared-workspace

    params:

    - name: git-url

    - name: image-name

    tasks:

    - name: fetch-source

    taskRef:

    name: git-clone

    workspaces:

    - name: output

    workspace: shared-workspace

    params:

    - name: url

    value: $(params.git-url)

    - name: run-tests

    taskRef:

    name: npm-test

    runAfter:

    - fetch-source

    workspaces:

    - name: source

    workspace: shared-workspace

    - name: build-image

    taskRef:

    name: buildah

    runAfter:

    - run-tests

    params:

    - name: IMAGE

    value: $(params.image-name)

    workspaces:

    - name: source

    workspace: shared-workspace

    `

    $1

    $1

    `yaml

    prometheus-config.yaml

    global:

    scrape_interval: 15s

    evaluation_interval: 15s

    scrape_configs:

    - job_name: 'platform-services'

    kubernetes_sd_configs:

    - role: pod

    relabel_configs:

    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]

    action: keep

    regex: true

    - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]

    action: replace

    target_label: __metrics_path__

    regex: (.+)

    `

    $1

    `json

    {

    "dashboard": {

    "id": null,

    "title": "Platform Overview",

    "tags": ["platform", "overview"],

    "timezone": "browser",

    "panels": [

    {

    "title": "Service Health",

    "type": "gauge",

    "datasource": "Prometheus",

    "targets": [

    {

    "expr": "sum(up{job=\"platform-services\"})",

    "refId": "A"

    }

    ]

    },

    {

    "title": "Resource Usage",

    "type": "graph",

    "datasource": "Prometheus",

    "targets": [

    {

    "expr": "sum(container_memory_usage_bytes) by (namespace)",

    "refId": "B"

    }

    ]

    }

    ]

    }

    }

    `

    $1

    $1

    `typescript

    // platform-cli.ts

    import { Command } from 'commander';

    import { createService, deployService, getServiceStatus } from './platform-api';

    const program = new Command();

    program

    .command('create')

    .description('Create a new service')

    .option('-t, --template