oam-dev / spec

Open Application Model (OAM).
https://oam.dev
Other
3.03k stars 246 forks source link

OAM Spec v0.3.0 Working Draft [Public Review and Comment] #443

Open resouer opened 3 years ago

resouer commented 3 years ago

OAM Spec v0.3.0 Working Draft

Hi all, this is the issue tracker to finalize the design of OAM spec v0.3.0. It reflects the high level ideas of the existing working draft in master branch with considerations on backward compatibility in existing releases.

As a working draft, the below design is open for revise, but we should try best to keep the changes minimal.

1. ComponentDefinition

Purpose: refactor Component in v0.2.1 and ComponentSchematic of v1alpha1 to combine all the schematic primitives in one object, w/o any instance values.

Target user: component provider, software distributor

apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
  name: webservice
  namespace: foo # declare this component is in namespace foo
spec:
  workload: # workload type descriptor
    type: containerizedworkloads.core.oam.dev # ref to a WorkloadDefinition via name
  schematic:
    kube: # this section is same with v0.2.1 component spec (i.e. raw k8s resource template)
      template:
        apiVersion: core.oam.dev/v1alpha2
        kind: ContainerizedWorkload
        spec:
        ...
          containers:
          - name: my-cool-workload
            image: example/very-cool-workload:0.1.2@sha256:verytrustworthyhash
            resources:
              cpu:
                required: 1.0
              memory:
                required: 100MB
            cmd:
            - "bash lscpu"
      parameters: 
      - name: image
        required: true
        fieldPaths: 
        - "spec.containers[0].image"
      - name: cmd
        required: true
        fieldPaths:
        - "spec.containers[0].cmd"
    cue:
      # cue template and parameters 
    helm:
      # a helm chart
status:
  parameters: # a generated json schema of parameters, equivalent to spec.parameters but friendly to k8s impl

The implementation will auto generate the jsonschema of module parameters and patch it to the status of ComponentDefinition.

2. WorkloadDefinition

Purpose: equivalent to WorkloadDefinition in v0.2.1, a missing concept in v1alpha1

Target user: this is an optional system level object, the main use case is for custom workload type discovering.

apiVersion: core.oam.dev/v1beta1
kind: WorkloadDefinition
metadata:
  name: containerizedworkloads.core.oam.dev
spec:
  definitionRef: # crd of this workload
    apiVersion: core.oam.dev/v1alpha2
    kind: ContainerizedWorkload
  childResources:
    - apiVersion: apps/v1
      kind: Deployment

3. Application

Purpose: equivalent to ApplicationConfiguration in v0.2.1 and v1alpha1

Target user: app dev, app ops, end users

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: application-sample
spec:
  components:
    - name: myweb
      type: foo/webservice # ref to ComponentDefinition, optionally, in namespace foo
      properties: # parameter values of the component
        image: "busybox"
        cmd:
        - sleep
        - "1000"
      traits: # assume traits are in oam system namespace for now
        - type: scaler
          properties:
            replicas: 10
        - type: sidecar
          properties:
            name: "sidecar-test"
            image: "nginx"

4. TraitDefinition

Purpose: equivalent to TraitDefinition in v0.2.1 and Trait of v1alpha1

Target user: infra ops, platform builders, traits are platform provided capabilities, end users should not modify traits - they only use them

apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
  name: scaler
spec:
  appliesToWorkloads:
    - containerizedworkloads.core.oam.dev # arbitrary workload definition
    # support k8s label selector in the future
  definitionRef:
    apiVersion: xxx
    kind: xxx
  schematic:
    # seems we don't need `kube` template for trait, definitionRef is enough
    cue:
      # cue template and parameters
    helm:
      # a helm chart
    ... # could have more module types in the future
status:
  parameters: # a optional generated json schema of parameters, equivalent to spec.parameters but friendly to k8s impl

5. ApplicationScope

No change with spec v0.2.1

Open Questions

1. Behavior of traits for revisioned components.

Traits are attached to component instances, and those instances are revisioned. Should we replica the traits then (e.g. ingress vs. {ingress-v1, ingress-v2})?

In previous code, as a workaround, we tagged TraitDefinition as revisionEnabled to control this behavior, though recently we fallback to assume ALL traits are replicated but have to leave rollout to a seperate field (since it is across-revisions).

wonderflow commented 3 years ago

package: # the encapsulation of this component. alternative name: module, componentSpec, encapsulation, templateModule, schematic

I vote for package.

ryanzhang-oss commented 3 years ago
  package: # the encapsulation of this component. alternative name: module, componentSpec, encapsulation, templateModule, schematic

I vote for "schematic"

hongchaodeng commented 3 years ago

Vote for schematic

wonderflow commented 3 years ago

Fine, let's use schematic

kminder commented 3 years ago

Below are points that I think are important to address with the current proposal.

  1. Seems like this should be at least 0.2->0.3 vs a "patch" 0.2.1->0.2.2.
  2. Needs to retain or replace scopes in 0.2.2 (0.3) resources.
  3. Needs to support complex traits. eg https://github.com/oam-dev/catalog/blob/master/applications/istio/bookinfo/appconfig-1-bookinfo.yaml, https://github.com/oam-dev/catalog/tree/master/traits/ingresstrait
  4. Needs to support Component isolation. Different users having access to different Components.
  5. Needs to have an extensible template "plugin" model that does not require spec change.
  6. Needs to normalize parameter handling between template types, including parameter schema.
  7. Needs to normalize use of setting vs parameter.
kminder commented 3 years ago

More detailed questions and comments.

  1. ComponentDefinition

    • Can we (at least optionally) share a "contract" between ComponentDefinitions?
    • At a minimum ComponentDefinitions will be hard to write and we expect users/component providers to do so.
    • Seems spec:workload:definition: doesn't reference a WorkloadDefinition, right? Does the naming need alignment?
    • Need more detail on how characteristics are handled especially if they will result in labels. How are these "namespaced" to prevent conflict?
    • Requiring consumers to find the right location for parameter schema is non-optimal. Can this always be declared by template author?
    • Rename childResource to childResources
  2. WorkloadDefinition

    • This has no value as currently proposed unless the "contract" question above is addressed.
  3. Application

    • Components are not provided by the platform but rather a component provider. Won't a namespace be required for isolation/security?
    • Components and traits should use the same term for settings/properties
    • Can settings really be either scalar or array? That needs to be in param schema somehow (especially for kube template type).
  4. TraitDefinition

    • The appliesToWorkload doesn't seem flexible enough to be useful. It should use something more like k8s label matching. It need or/in/notin at least.
    • The appliesToWorkload need better details about how workload definition and childResources are translated to a characteristic if they are.
    • Can appliesToWorkload use any label or just those in a ComponentDefinition's characteristics? If so what labels?
    • Doesn't appliesToWorkload need to operate against the ComponentDefinition vs the workload instance for validation?
  5. ApplicationScope

    • Scope support must be included in 0.2.2 in some form for functional compatibility.
kminder commented 3 years ago

WRT

  1. Needs to support Component isolation. Different users having access to different Components.

What I really mean is that a ComponentDefinition needs to be namespace qualified. Just adding a namespace appears awkward though as it isn't clear if it applies to the name or the type.

apiVersion: core.oam.dev/v1alpha2
kind: Application
...
spec:
  components:
    - name: my-comp-inst
      namespace: my-comp-def-ns
      type: my-comp-def

Honestly I've always felt Kubernetes needed standardized single value qualified reference formats (e.g. namespace/name and group/version.kind@namespace/name or similar).

spec:
  components:
    - name: my-comp-inst
      type: my-comp-def-ns/my-comp-def
dhiguero commented 3 years ago

Hi all, these are our comments on the spec proposal.

Component Definition

Workload definition

Application

Trait definition

Application Scope

Other aspects

Versioning

Extra information on user facing entities

Component Security Context

We have submitted a PR for the OAM runtime controller to include security context information on components limiting the information to aspects of the container, not to the underlying orchestration system. We think that this information should also be part of the new OAM proposal at least for the spec.schematic.kube aspect.

OAM Compliance

With the growth of OAM in the industry we think that the spec should have a clear definition of which are the minimum requirements for an OAM runtime. Before this proposal, our understanding was that the differentiation from one provider to another would be the different workload types and traits that were present, not parts of the spec.

Trait consolidation

Traits are currently implemented as Kubernetes operators that modify the generated resource according to their internal logic. However, this opens up the door for consolidation failure scenarios where two traits may want to modify the same characteristic. For example, image two trait trying to set different number of replicas.

Maybe it is too much of a change for the current proposal/scope, but it will be nice to consider this issue in the future. If traits are applied in order by some mechanism, we feel the system becomes much more robust, even if that requires traits not being operators, but implementing a common gRPC interface to return the altered entity.

Configuration and secrets

This issue is not referenced by the spec, and may not be clear for a new user how this is expected to be supported. One option is to add this type of information as a new entity or include it on the Application one, while other could be to use a specific Trait. Either way, the spec should contain information about how to proceed when deploying an application that requires a config map. While many containerized application rely on environment variables to set options, others just use a plain config file on known locations.

resouer commented 3 years ago

@kminder @dhiguero Just updated the spec description based on your inputs, they are valuable!

We will leave some features as Non-Goal for this release, for example:

  1. Make .schematic fully extensible. There's no intension to expand this until there're significant requirements to open this as an extension point and conformance design will be needed then. We will focus on the schematic types listed above which are all driven by real user requirements.
  2. Advanced trait appliesTo behavior. This is a highly demanded feature (i.e. applies to characteristics instead of workload def'n name), but we decide won't couple it in this release and tackle it separately in issue https://github.com/oam-dev/spec/issues/392. A similar feature is ConflictsWith on traits.
wonderflow commented 3 years ago

Speaking of consistency, what about using kind for all.

apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
  name: application-sample
spec:
  components:
    - name: myweb
      kind: foo/webservice # ref to ComponentDefinition, optionally, in namespace foo
      properties: # parameter values of the component
        image: "busybox"
        cmd:
        - sleep
        - "1000"
      traits: # assume traits are in oam system namespace for now
        - kind: scaler
          properties:
            replicas: 10
        - kind: sidecar
          properties:
            name: "sidecar-test"
            image: "nginx"
resouer commented 3 years ago

Speaking of consistency, what about using kind for all.

apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
  name: application-sample
spec:
  components:
    - name: myweb
      kind: foo/webservice # ref to ComponentDefinition, optionally, in namespace foo
      properties: # parameter values of the component
        image: "busybox"
        cmd:
        - sleep
        - "1000"
      traits: # assume traits are in oam system namespace for now
        - kind: scaler
          properties:
            replicas: 10
        - kind: sidecar
          properties:
            name: "sidecar-test"
            image: "nginx"

@kminder @dhiguero please check the proposal above and +1/-1 for this.

kminder commented 3 years ago

In spirit I agree with the suggestion above about making the syntax for references to type definitions consistent. However I'm not a fan of using kind as that has a very specific meaning in Kubernetes. Therefore I make a counter proposal to use type instead.

apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
  name: application-sample
spec:
  components:
    - name: myweb
      type: foo/webservice # ref to ComponentDefinition, optionally, in namespace foo
      properties: # parameter values of the component
        image: "busybox"
        cmd:
        - sleep
        - "1000"
      traits: # assume traits are in oam system namespace for now
        - type: scaler
          properties:
            replicas: 10
        - type: sidecar
          properties:
            name: "sidecar-test"
            image: "nginx"
dhiguero commented 3 years ago

I also think that kind may be confusing due to its kubernetes meaning as the kind in the second line of the example (kind: Application) does not accept the same syntax that the proposed one. I think that naming it type as @kminder suggested is a better option.

wonderflow commented 3 years ago

Cool, then we confirm using type. BTW, let's move the API to v1beta1.

So the final example could be:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: application-sample
spec:
  components:
    - name: myweb
      type: foo/webservice # ref to ComponentDefinition, optionally, in namespace foo
      properties: # parameter values of the component
        image: "busybox"
        cmd:
        - sleep
        - "1000"
      traits: # assume traits are in oam system namespace for now
        - type: scaler
          properties:
            replicas: 10
        - type: sidecar
          properties:
            name: "sidecar-test"
            image: "nginx"

\cc @resouer @dhiguero @kminder

wonderflow commented 3 years ago

ref https://github.com/oam-dev/kubevela/pull/1282

rbbarbosa commented 3 years ago

The comment after namespace is slightly misleading because it gives the impression that foo/webservice is an instance rather than a type.

apiVersion: core.oam.dev/v1alpha3
kind: ComponentDefinition
metadata:
  name: webservice
  namespace: foo # install this component in namespace foo

Maybe change "install" to "declare".