Skip to content
This repository has been archived by the owner on Jun 8, 2022. It is now read-only.

Commit

Permalink
An example sketch of a platform configuration
Browse files Browse the repository at this point in the history
Signed-off-by: Nic Cope <negz@rk0n.org>
  • Loading branch information
negz committed Jul 31, 2020
1 parent 2365bbc commit c1d0215
Show file tree
Hide file tree
Showing 10 changed files with 833 additions and 2 deletions.
102 changes: 100 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,100 @@
# aac
Platform API as Configuration
# Platform API as Configuration

This repository contains configuration for the Cloud Native Platform (CNP). CNP
consists of a series of Crossplane packages that are automatically built and
pushed to the Upbound Cloud Registry by CI/CD when commits are merged to this
repository. The following packages exist:

* `eks.clusters.cnp.example.org` - Defines a composite resource representing an
EKS cluster (including all network and IAM dependencies).
* `fluentbits.charts.cnp.example.org` - Defines a composite resource
representing a Helm release of the Fluent Bit logging daemonset.
* `clusters.cnp.example.org` - Defines a composite resource representing a 'CNP
Kubernetes Cluster'. This cluster is composed of the EKS cluster and Fluent
Bit composite resources above, and thus this package depends on the above two.
**The files in this package contain explanatory annotations; it's the most
interesting one to look at.**

The root of each package dependency contains a file named `crossplane.yaml`.
This file indicates that the directory represents a Crossplane package. A
Crossplane package is an OCI image that is expected to emit this file, followed
by any packaged resources in the order they should be applied, when its
entrypoint is invoked.

To create a package, the package author (or their CI/CD system runs) the
following commands:

```bash

# default `crossplane package unpack` will emit this file, then discover and
# emit any packagable resources (XRDs, Compositions, etc) at or below its path
# in lexicographical order. Alternately we could shift this discovery and
# ordering logic into the 'build' subcommand, creating a tiny package image
# with an ENTRYPOINT of `cat bigstreamofresources.yaml`.

# Any OCI image that omits a YAML resource of kind: Configuration or kind:
# Provider (in the pkg.crossplane.io API Group) followed by zero or more
# supplemental resources when its ENTRYPOINT is invoked is considered a valid
# Crossplane package. This tools builds a valid package by reading a file named
# crossplane.yaml at the root of the package directory (which must contain a
# kind: Configuration or a kind: Provider), then discovering all Crossplane
# resources at or below the level of crossplane.yaml in the directory tree.
# These resources are concatenated into a YAML stream in a randomly generated
# filename (to avoid implementations relying on the path of this file), and the
# ENTRYPOINT of the OCI image is set to `cat randomlynamedstream.yaml`.
$ crossplane package build --tag exampleorg/cnp-cluster:v0.1.0

# The `crossplane package` command provides a similar interface to the `docker`
# tool frequently used to build, tag, and push images. `crossplane package`
# publishes packages to the Upbound Cloud Registry rather than the Docker Hub
# by default.
$ crossplane package push exampleorg/cnp-cluster:v0.1.0
```

Note that package metadata does not include a version. Crossplane packages use
the package (image) tag as their version, and thus require that tags be valid
semantic versions. Images built by CI/CD as part of a gitops flow are encouraged
to derive their semantic version from a git tag. In such a case all packages
defined in this repository would be versioned in lock-step.

## Proposed Changes

This sketch assumes the acceptance of the in-flight [Package Manager refactor].
It also:

* Renames `InfrastructureDefinition` to `CompositeResourceDefinition` (XRD).
* Replaces `InfrastructurePublication` with a configuration field on an XRD.
* Automatically derives UI metadata from the OpenAPI schema of an XRD.
* Renames the `spec.to` and `spec.from` of a `Composition` to
`spec.compositeResource` and `spec.composedResources`, in order to allow for
'bidirectional patching' - i.e. patching from composed resource status to
composite resource status in addition to patching from composite resource spec
to composed resource spec (not yet demonstrated in this repo).
* Uses `metadata.annotations` to represent most package metadata (maintainer,
company, etc) in order to loosen the contract around purely informational
package metadata.
* Couples the creation and aggregation of suggested RBAC ClusterRoles to the
existence of XRDs, rather than Packages.

When automatic RBAC ClusterRole management is enabled by an XRD (management is
enabled by default) Crossplane will create `admin`, `edit`, and `view` RBAC
ClusterRoles granting access to the defined kind and its requirement (if any).
These ClusterRoles will labelled such that they aggregate (as appropriate) to
the ClusterRoles intended to be granted to:

* The Crossplane (Deployment) service account.
* The Crossplane superuser (`crossplane-admin`).
* Subjects allowed to administrate, edit, or view all Crossplane resources.

Furthermore, Crossplane will create `admin`, `edit`, and `view` ClusterRoles
corresponding to any namespace that is labelled with the name of one or more
XRD, for example `rbac.crossplane.io/clusters.cnp.example.org`. If the named XRD
exists and has `rbacPolicy: ManageClusterRoles` the ClusterRole corresponding to
the labelled namespace will have a `matchLabels` stanza added to its
`clusterRoleSelectors` such that the XRD's managed cluster roles aggregate up
to it. This allows consumers of the Crossplane API that wish to simulate a
kind of resource existing or not existing at the namespace level (i.e. Upbound
Cloud) to read and write namespace annotations to determine which resources are
allowed (by RBAC) in a particular namespace.

[Package Manager refactor]: https://github.com/crossplane/crossplane/pull/1616
39 changes: 39 additions & 0 deletions clusters.cnp.example.org/composition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: Composition
metadata:
name: clusters.cnp.example.org
spec:
writeConnectionSecretsToNamespace: crossplane-system
reclaimPolicy: Delete
compositeResource:
apiVersion: cnp.example.org/v1alpha1
kind: Cluster
composedResources:
- base:
apiVersion: clusters.cnp.example.org/v1alpha1
kind: EKS
patches:
- fromFieldPath: metadata.annotations[crossplane.io/external-name]
toFieldPath: metadata.annotations[crossplane.io/external-name]
- fromFieldPath: metadata.uid
toFieldPath: spec.writeConnectionSecretToRef.name
transforms:
- type: string
string:
fmt: "%s-eks"
- fromFieldPath: spec.parameters.nodes.count
toFieldPath: spec.parameters.nodes.count
- fromFieldPath: spec.parameters.nodes.size
toFieldPath: spec.parameters.nodes.size
- base:
apiVersion: charts.cnp.example.org/v1alpha1
kind: FluentBit
patches:
- fromFieldPath: metadata.uid
toFieldPath: spec.providerRef.name
transforms:
- type: string
string:
fmt: "%s-eks"
- fromFieldPath: spec.parameters.logging.token
toFieldPath: spec.parameters.splunk.token
35 changes: 35 additions & 0 deletions clusters.cnp.example.org/crossplane.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# The Configuration resource follows Kubernetes API conventions, but is simply
# a configuration file rather than a custom resource in an API server. This is
# similar to the approach the kubelet and kind take with their configuration.
# The content of this file is emitted by the `crossplane package unpack` tool
# when a Package CR is created, and used to create a PackageRevision.
apiVersion: pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: cnp-cluster
annotations:
# Package metadata is stored as well-known but optional, free-form metadata
# ala https://packaging.python.org/specifications/core-metadata/. The data
# is opaque to Crossplane and its tooling, allowing for maximum flexibility
# in the contract between the authors and consumers of package metadata (at
# the expense of some loss of schema).
company: ExampleCo
maintainer: Wan Jillies <wan@example.org>
keywords: cloud-native, kubernetes
source: github.com/negz/aac
license: Apache-2.0
description: |
An ExampleCo Cloud Native Platform (CNP) Kubernetes Cluster, complete with
supporting infrastructure services such as logging and monitoring daemons.
spec:
dependsOn:
- package: exampleco/cnp-eks
version: "0.1.0"
- package: exampleco/cnp-fluentbit
version: "0.1.0"
# Optional. Matching paths will be ignored by `crossplane package build`.
ignore:
- path: examples/
# crossplane.yaml may be of kind: Provider, rather than kind: Configuration.
# A Provider contains additional configuration, including an image to run.
# controllerImage: crossplane/provider-gcp:v0.11.0
71 changes: 71 additions & 0 deletions clusters.cnp.example.org/definition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: CompositeResourceDefinition
metadata:
name: clusters.cnp.example.org
spec:
defaultCompositionRef:
name: clusters.cnp.example.org
# This policy is equivalent to the existing InfrastructurePublication. Making
# this a field of the InfrastructureDefinition implies that the package author
# controls the publication of packaged types; it cannot easily be overridden
# without forking/duplicating the package.
publicationPolicy: PublishRequirement
# This policy determines whether Crossplane will automatically create cluster
# roles for this composite resource and its requirement. ManageClusterRoles is
# the default. Under this policy Crossplane will create edit and view RBAC
# cluster roles for the composite resource and requirement (if any). The roles
# will aggregate to the Crossplane service account, crossplane-admin role, the
# global edit and view roles, and any matching namespaced edit and view roles.
rbacPolicy: ManageClusterRoles
connectionSecretKeys:
- kubeconfig
# Note that there is no distinct UI metadata; UI forms are derived from the
# crdSpecTemplate, which includes enough detail to infer how to build a form.
crdSpecTemplate:
group: cnp.example.org
version: v1alpha1
names:
kind: Cluster
listKind: ClusterList
plural: clusters
singular: cluster
validation:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
description: Cluster configuration parameters.
nodes:
type: object
description: Cluster node configuration parameters.
count:
type: int
description: Desired node count, from 1 to 100.
size:
type: string
description: Size of node.
enum:
- small
- medium
- large
required:
- count
- type
logging:
type: object
description: Splunk logging configuration for cluster logs.
token:
type: string
description: Splunk API token.
required:
- token
required:
- nodes
- splunk
required:
- parameters
Loading

0 comments on commit c1d0215

Please sign in to comment.