SlideShare une entreprise Scribd logo
1  sur  35
Télécharger pour lire hors ligne
Extending Kubernetes with
CustomResourceDefinitions
Stefan Schimanski
sttts@redhat.com / sttts @ GitHub / @the_sttts
CONTAINERdays 2018
Restful
http API
/
/version
/api
/api/v1/pods
/api/v1/pods/<name>
/api/v1/pods/<name>/status
/apis
/apis/batch
/apis/batch/v2alpha1
/apis/batch/v2alpha1/jobs
/apis/batch/v2alpha1/cronjobs
/apis/batch/v1
/apis/batch/v1/jobs
kube-apiserver
kubeletproxy
Node:
$ kubectl create -f foo.yaml
User:
scheduler
controller
manager
apiserver
ingress
controller
Master:
cloud native apps
Pods:
Restful
http API
/
/version
/api
/api/v1/pods
/api/v1/pods/<name>
/api/v1/pods/<name>/status
/apis
/apis/batch
/apis/batch/v2alpha1
/apis/batch/v2alpha1/jobs
/apis/batch/v2alpha1/cronjobs
/apis/batch/v1
/apis/batch/v1/jobs
/apis/<our-group>/v1/<your-resource>
kube-apiserver
kubeletproxy
Node:
$ kubectl create -f foo.yaml
User:
scheduler
controller
manager
apiserver
ingress
controller
Master:
cloud native
apps
Pods:
your
controller
$ kube-apiserver
--secure-port 0
--etcd-servers http://127.0.0.1:2379
--service-cluster-ip-range 10.0.0.0/16
--storage-backend etcd2
--storage-media-type application/json
$ etcd
$ kubectl config set-cluster local --server=http://127.0.0.1:8080
$ kubectl config set-context local --cluster=local
$ kubectl config use-context local
$ kubectl get namespaces --v=7
$ kubectl get namespace default -o json
$ kubectl annotate namespace default meetup=hello
$ curl http://127.0.0.1:8080/api/v1/namespaces/default
$ etcdctl ls --recursive
$ etcdctl get /registry/namespaces/default
$ etcdctl -o extended get /registry/namespaces/default
$ http GET http://127.0.0.1:8080/api/v1/namespaces/default
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"annotations": {
"meetup": “hallo"
},
"creationTimestamp": "2017-03-10T07:51:39Z",
"name": "default",
"resourceVersion": “73",
},
"spec": { "finalizers": ["kubernetes“] },
"status": { "phase": "Active“ }
}
$ http GET http://127.0.0.1:8080/api/v1/namespaces/default |
jq ".metadata.annotations["meetup"] = "$(date)"" |
http PUT http://127.0.0.1:8080/api/v1/namespaces/default
HTTP/1.1 200 OK
Content-Length: 341
Content-Type: application/json
Date: Fri, 10 Mar 2017 08:28:01 GMT
/apis/batch/v2alpha1/jobs
group version resource
HTTP paths:
{
“apiVersion“: “v2alpha1“,
“kind“: “Job“,
“metadata“: {
“name“: “backup“
},
“spec“: { ... }
}
http POST
as JSON
or Proto
/namespaces/<name>/
Possible (logical) verbs:
• GET
• CREATE (= POST)
• UPDATE (= PUT)
• LIST (GET on root path)
• DELETE
• PATCH
• WATCH (?watch=true)
Custom Resources (CRs)
&
Custom Resource Definitions (CRDs)
apiextensions/v1beta1
Custom Resource
hamburg-sensor.yaml
apiVersion: containerdays.io/v1
kind: Sensor
metadata:
name: hamburg
namespace: germany
spec:
unit: Celcius
status:
lastUpdated: 2010-03-26T15:13:42.05Z
temperature: 28
We want to store these
apiextensions-apiserver inside kube-apiserver
https://github.com/kubernetes/apiextensions-apiserver
In every Kubernetes 1.7+ cluster.
kube-apiserver
kube-aggregator kube resources apiextensions-
apiserver
404
etcd
"delegation"
"aggregation"
Custom Resource
hamburg-sensor.yaml
apiVersion: containerdays.io/v1
kind: Sensor
metadata:
name: hamburg
namespace: germany
spec:
unit: Celcius
status:
lastUpdated: 2010-03-26T15:13:42.05Z
temperature: 28
We want to store these
Custom Resource Definition (CRD)
apiextensions/v1beta1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: sensors.containerdays.io
spec:
group: containerdays.io
version: v1
names:
kind: Sensor
plural: sensors
scope: Namespaced mustmatch
Defines how CRs are stored
Custom Resource Definition (CRD)
apiextensions/v1beta1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: sensors.containerdays.io
spec:
group: containerdays.io
version: v1
names:
kind: Sensor
plural: sensors
scope: Namespaced
$ kubectl create –f sensors-crd.yaml
a moment
...
status:
acceptedNames:
kind: Sensor
listKind: SensorList
plural: sensors
singular: sensor
conditions:
- type: NamesAccepted
message: no conflicts found
reason: NoConflicts
status: "True“
- type: Established
message: the initial names have
been accepted
reason: InitialNamesAccepted
status: "True“
mustmatch
$ kubectl get sensors –v=7
• I0429 21:17:53.042783 66743 round_trippers.go:383] GET https://localhost:6443/apis
• I0429 21:17:53.135811 66743 round_trippers.go:383] GET
https://localhost:6443/apis/containerdays.io/v1
• I0429 21:17:53.138353 66743 round_trippers.go:383] GET
https://localhost:6443/apis/containerdays.io/v1/namespaces/default/sensors
No resources found.
sensors → kind Sensor
resource sensors
discovery
LIST
API group containerdays.io/v1
We call this "REST mapping"
$ http localhost:8080/apis/
{
"groups": [{
"name": "containerdays.io",
"preferredVersion": {"groupVersion": "containerdays.io/v1", "version": "v1“},
"versions": [{"groupVersion": "containerdays.io/v1", "version": "v1"}]
}, ...]
}
$ http localhost:8080/apis/containerdays.io/v1
{
"apiVersion": "v1",
"groupVersion": "containerdays.io/v1",
"kind": "APIResourceList",
"resources": [{
"kind": "Sensor",
"name": "sensors",
"namespaced": true,
"verbs": ["create", "delete", "deletecollection",
"get", "list", "patch", "update", "watch“
]
}, ...]
}
resource name ⇒ /apis/containerdays.io/v1/sensors
/namespaces/<name>/
$ kubectl get sensors –v=7
• I0429 21:17:53.042783 66743 round_trippers.go:383] GET https://localhost:6443/apis
• I0429 21:17:53.135811 66743 round_trippers.go:383] GET
https://localhost:6443/apis/containerdays.io/v1
• I0429 21:17:53.138353 66743 round_trippers.go:383] GET
https://localhost:6443/apis/containerdays.io/v1/namespaces/default/sensors
No resources found.
sensors → kind Sensor
resource sensors
discovery
LIST
API group containerdays.io/v1
We call this "REST mapping"
$ kubectl create –f sensors-crd.yaml $ kubectl create –f hamburg-sensor.yaml
apiVersion: containerdays.io/v1
kind: Sensor
metadata:
name: hamburg
namespace: germany
spec:
unit: Celcius
status:
lastUpdate: 2010-03-26T15:13:42.05Z
temperature: 28
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: sensors.containerdays.io
spec:
group: containerdays.io
version: v1
names:
kind: Sensor
plural: sensors
scope: Namespaced
1 2
Create the CRD Create CustomResources
$ kubectl create –f sensors-crd.yaml $ kubectl create –f hamburg-sensor.yaml
apiVersion: containerdays.io/v1
kind: Sensor
metadata:
name: hamburg
namespace: germany
spec:
unit: Celcius
status:
lastUpdate: 2010-03-26T15:13:42.05Z
temperature: 28
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: sensors.containerdays.io
spec:
group: containerdays.io
version: v1
names:
kind: Sensor
plural: sensors
scope: Namespaced
1 2
Create the CRD Create CustomResources
Follow spec+status pattern.
$ kubectl get sensors –w --no-headers
brussels <none> {"apiVersion":"containerdays.io/v1","kind":"Sensor",...
hamburg <none> {"apiVersion":"containerdays.io/v1","kind":"Sensor",...
$ curl -f 'http://127.0.0.1:8080/apis/containerdays.io/v1/namespaces/default/sensors?watch=true&resourceVersion=434‘
{"type":"DELETED","object":{"apiVersion":"containerdays.io/v1","kind":"Sensor","metadata":{"name":"brussels","namespace
":"hamburg","selfLink":"/apis/containerdays.io/v1/namespaces/belgium/sensors/brussels","uid":"8f5312c0-29c8-11e7-88f9-
4c3275978b79","resourceVersion":"435","creationTimestamp":"2017-04-25T15:05:03Z"},"spec":{...}}}
{"type":"ADDED","object":{"apiVersion":"containerdays.io/v1","kind":"Sensor","metadata":{"name":"hamburg","namespace
":"germany","selfLink":"/apis/containerdays.io/v1/namespaces/germany/sensors/berlin","uid":"b4318cb5-29c8-11e7-88f9-
4c3275978b79","resourceVersion":"436","creationTimestamp":"2017-04-25T15:06:05Z"},"spec":{...}}}
Watch, i.e. event stream
Validation
• The standard: OpenAPI v3 schema
• based on JSON Schema
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: sensors.containerdays.io
spec:
group: containerdays.io
version: v1
names: ...
validation:
openAPIV3Schema: <see next slide>
spec:
unit: Celclius
status:
lastUpdate: 2010-03-26T...
temperatur: true
properties:
spec:
properties:
unit:
anyOf: [{"pattern": "^Celclius$"}, …]
default: "Celcius"}
required: ["unit"]
status:
properties:
lastUpdate: {"type": "string", "pattern": "^[0-9]+-...$"},
temperature: {"type": "number", "minimum": -273.15},
required: []
OpenAPIv3Schema
a quantor (anyOf, oneOf, allOf exist)
note: enum is forbidden (why?)
regular expression
probably in 1.12+
Custom Resource
Helpful tools:
kubernetes/kube-openapi#37
tamalsaha/kube-openapi-generator
Some other tool from prometheus-operator?
Rancher has another one, speak to @lemonjet
Controllers
where is the business logic?
$ while true; do
http GET http://127.0.0.1:8080/api/v1/namespaces/default |
jq ".metadata.annotations["meetup"] = "$(date)"" |
http --check-status PUT http://127.0.0.1:8080/api/v1/namespaces/default || break
done
⟲
1. read object (preferably event driven with watches)
2. change object, update the world
3. update object on apiserver
4. repeat
$ while true; do
http GET http://127.0.0.1:8080/api/v1/namespaces/default |
{jq ".metadata.annotations["meetup"] = "$RANDOM""; sleep 1;} |
http --check-status PUT http://127.0.0.1:8080/api/v1/namespaces/default || break
done
HTTP/1.1 409 Conflict
Content-Length: 310
Content-Type: application/json
Date: Fri, 10 Mar 2017 08:27:58 GMT
{
"apiVersion": "v1",
"code": 409,
"details": {
"kind": "namespaces",
"name": "default“
},
"kind": "Status",
"message": "Operation cannot be fulfilled on namespaces "default": the object has been
modified; please apply your changes to the latest version and try again",
"metadata": {},
"reason": "Conflict",
"status": "Failure“
}
„optimistic concurrency“
$ while true; do
http GET http://127.0.0.1:8080/api/v1/namespaces/default |
jq ".metadata.annotations["meetup"] = "$(date)"" |
http --check-status PUT http://127.0.0.1:8080/api/v1/namespaces/default || break
done
⟲
1. read object (preferably event driven with watches)
2. change object, update the world
3. update object on apiserver
4. repeat
expect version conflicts,
remember: optimistic concurrency
$ kubectl get namespaces --watch --no-headers |
while read NS STATUS TIME ; do
# do whatever you like here, e.g. change the namespace
echo "$NS changed“
done
⟲
W
atch=nohot looping
$ curl -f 'http://127.0.0.1:8080/api/v1/namespaces?watch=true&resourceVersion=4711‘
{"type":"ADDED","object":{"kind":"Namespace","apiVersion":"v1","metadata":{"name ...
{"type":“MODIFIED","object":{"kind":"Namespace","apiVersion":"v1","metadata":{"name ...
{"type":“DELETED","object":{"kind":"Namespace","apiVersion":"v1","metadata":{"name ...
k8s.io/sample-controller
"CRDs are limited"
• no version conversion (only one version possible per CRD)
• in 1.11 multiple versions, but no conversion
• in 1.12+ conversions come, but slowly
• no defaulting (PR exists)
• no validation (beta in 1.9, Google Summer of Code project)
• no subresources (scale, status) (beta in 1.11)
• no admission (since 1.7: admission webhooks + initializers)
• alpha CRDs are beta
• no custom printing in kubectl (in 1.11: custom printer columns)
Outlook – Custom Resources
• Kubernetes 1.11
• Server Side Printing Columns – “kubectl get” customization – #60991
• β : Multiple versions without conversion – design proposal
• β: Subresources – ⍺ since 1.10 – #62786
• OpenAPI additionalProperties allowed now
(mutually exclusive with properties)
• Kubernetes 1.12+
• ⍺: Multiple versions with declarative field renames
• ⍺: Graceful Deletion – being discussed – #63162
• ⍺: Pruning – in validation spec unspecified fields are removed – blocker for GA
• ⍺: Defaulting – defaults from OpenAPI validation schema are applied
• Strict create mode? Discuss: #5889 – my favorite CRD UX issue
Related: CRD OpenAPI validation spec not served by kube-apiserver
Backup
Zoom into apiextensions-apiserver
kube-apiserver
kube-
aggregator
kube
resources
apiextensions-apiserver
404
etcd
"delegation"
"aggregation"
authn/z
CR handlers
CR handlers
CR handlers
⟲Naming Controller
⟲CRD Finalizer
request
conversion&
defaulting
storage
conversion &
defaulting
REST logic
result
conversion
validation
admission
decoding
encode
GET
CREATE
LIST
UPDATE
DELETE
WATCH
mutating
webhooks
validating
webhooks NoOps
json.Unmarshal
/apis/extensions/v1alpha1/jobs/backup
/apis/batch/v2alpha1/jobs/backup
/apis/batch/v1/jobs/backup
{
“apiVersion“: “v1alpha1“,
“kind“: “Job“,
“metadata“: {
“name“: “backup“
},
“spec“: { ... }
}
{
“apiVersion“: “v2alpha1“,
“kind“: “Job“,
“metadata“: {
“name“: “backup“
},
“spec“: { ... }
}
{
“apiVersion“: “v1“,
“kind“: “Job“,
“metadata“: {
“name“: “backup“
},
“spec“: { ... }
}
lossless
conversion
* I omitted the namespace in /apis/batch/v1/jobs/namespaces/default/backup
{
“apiVersion“: “v1alpha1“,
“kind“: “Job“,
“metadata“: {
“name“: “backup“
},
“spec“: { ... }
}
{
“apiVersion“: “v2alpha1“,
“kind“: “Job“,
“metadata“: {
“name“: “backup“
},
“spec“: { ... }
}
{
“apiVersion“: “v1 “,
“kind“: “Job“,
“metadata“: {
“name“: “backup“
},
“spec“: { ... }
}
lossless
conversion
etcd
{
“apiVersion“: “v1 “,
“kind“: “Job“,
“metadata“: {
“name“: “backup“
},
“spec“: { ... }
}
Protobuf
or
JSON
storage
version
encoding
Extending kubernetes with CustomResourceDefinitions

Contenu connexe

Tendances

Tendances (20)

Introduction to kubernetes
Introduction to kubernetesIntroduction to kubernetes
Introduction to kubernetes
 
Introduction to Kubernetes Workshop
Introduction to Kubernetes WorkshopIntroduction to Kubernetes Workshop
Introduction to Kubernetes Workshop
 
K8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals TrainingK8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals Training
 
Kubernetes extensibility: crd & operators
Kubernetes extensibility: crd & operators Kubernetes extensibility: crd & operators
Kubernetes extensibility: crd & operators
 
Secrets in Kubernetes
Secrets in KubernetesSecrets in Kubernetes
Secrets in Kubernetes
 
Hands-On Introduction to Kubernetes at LISA17
Hands-On Introduction to Kubernetes at LISA17Hands-On Introduction to Kubernetes at LISA17
Hands-On Introduction to Kubernetes at LISA17
 
Kubernetes security
Kubernetes securityKubernetes security
Kubernetes security
 
Docker Swarm 0.2.0
Docker Swarm 0.2.0Docker Swarm 0.2.0
Docker Swarm 0.2.0
 
Kubernetes - introduction
Kubernetes - introductionKubernetes - introduction
Kubernetes - introduction
 
Kubernetes Introduction
Kubernetes IntroductionKubernetes Introduction
Kubernetes Introduction
 
Kubernetes: A Short Introduction (2019)
Kubernetes: A Short Introduction (2019)Kubernetes: A Short Introduction (2019)
Kubernetes: A Short Introduction (2019)
 
Introduction to kubernetes
Introduction to kubernetesIntroduction to kubernetes
Introduction to kubernetes
 
Introduction to helm
Introduction to helmIntroduction to helm
Introduction to helm
 
An Architectural Deep Dive With Kubernetes And Containers Powerpoint Presenta...
An Architectural Deep Dive With Kubernetes And Containers Powerpoint Presenta...An Architectural Deep Dive With Kubernetes And Containers Powerpoint Presenta...
An Architectural Deep Dive With Kubernetes And Containers Powerpoint Presenta...
 
Kubernetes Architecture | Understanding Kubernetes Components | Kubernetes Tu...
Kubernetes Architecture | Understanding Kubernetes Components | Kubernetes Tu...Kubernetes Architecture | Understanding Kubernetes Components | Kubernetes Tu...
Kubernetes Architecture | Understanding Kubernetes Components | Kubernetes Tu...
 
Kubernetes for Beginners: An Introductory Guide
Kubernetes for Beginners: An Introductory GuideKubernetes for Beginners: An Introductory Guide
Kubernetes for Beginners: An Introductory Guide
 
Kubernetes - Security Journey
Kubernetes - Security JourneyKubernetes - Security Journey
Kubernetes - Security Journey
 
Terraform modules restructured
Terraform modules restructuredTerraform modules restructured
Terraform modules restructured
 
Helm - the Better Way to Deploy on Kubernetes - Reinhard Nägele - Codemotion...
 Helm - the Better Way to Deploy on Kubernetes - Reinhard Nägele - Codemotion... Helm - the Better Way to Deploy on Kubernetes - Reinhard Nägele - Codemotion...
Helm - the Better Way to Deploy on Kubernetes - Reinhard Nägele - Codemotion...
 
Kubernetes Secrets Management on Production with Demo
Kubernetes Secrets Management on Production with DemoKubernetes Secrets Management on Production with Demo
Kubernetes Secrets Management on Production with Demo
 

Similaire à Extending kubernetes with CustomResourceDefinitions

Similaire à Extending kubernetes with CustomResourceDefinitions (20)

Meetup - Principles of the kube api and how to extend it
Meetup - Principles of the kube api and how to extend itMeetup - Principles of the kube api and how to extend it
Meetup - Principles of the kube api and how to extend it
 
An Introduction to the Kubernetes API
An Introduction to the Kubernetes APIAn Introduction to the Kubernetes API
An Introduction to the Kubernetes API
 
Who is afraid of privileged containers ?
Who is afraid of privileged containers ?Who is afraid of privileged containers ?
Who is afraid of privileged containers ?
 
Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)
 
Extending the Kube API
Extending the Kube APIExtending the Kube API
Extending the Kube API
 
Infracoders VII - Someone is Watching You
Infracoders VII   - Someone is Watching YouInfracoders VII   - Someone is Watching You
Infracoders VII - Someone is Watching You
 
DevOpSec_KubernetesOperatorUsingJava.pdf
DevOpSec_KubernetesOperatorUsingJava.pdfDevOpSec_KubernetesOperatorUsingJava.pdf
DevOpSec_KubernetesOperatorUsingJava.pdf
 
Kubernetes - Starting with 1.2
Kubernetes  - Starting with 1.2Kubernetes  - Starting with 1.2
Kubernetes - Starting with 1.2
 
Scaling search-clusters-solr-k8s-2020-amrit-sarkar
Scaling search-clusters-solr-k8s-2020-amrit-sarkarScaling search-clusters-solr-k8s-2020-amrit-sarkar
Scaling search-clusters-solr-k8s-2020-amrit-sarkar
 
An Introduction to Project riff, a FaaS Built on Top of Knative - Eric Bottard
An Introduction to Project riff, a FaaS Built on Top of Knative - Eric BottardAn Introduction to Project riff, a FaaS Built on Top of Knative - Eric Bottard
An Introduction to Project riff, a FaaS Built on Top of Knative - Eric Bottard
 
Kubernetes Architecture and Introduction – Paris Kubernetes Meetup
Kubernetes Architecture and Introduction – Paris Kubernetes MeetupKubernetes Architecture and Introduction – Paris Kubernetes Meetup
Kubernetes Architecture and Introduction – Paris Kubernetes Meetup
 
KubeCon EU 2018 – Sig API Machinery Deep Dive
KubeCon EU 2018 – Sig API Machinery Deep DiveKubeCon EU 2018 – Sig API Machinery Deep Dive
KubeCon EU 2018 – Sig API Machinery Deep Dive
 
JDD2015: Kubernetes - Beyond the basics - Paul Bakker
JDD2015: Kubernetes - Beyond the basics - Paul BakkerJDD2015: Kubernetes - Beyond the basics - Paul Bakker
JDD2015: Kubernetes - Beyond the basics - Paul Bakker
 
Building the TribefireOperator
Building the TribefireOperatorBuilding the TribefireOperator
Building the TribefireOperator
 
Amazon Web Services and Docker: from developing to production
Amazon Web Services and Docker: from developing to productionAmazon Web Services and Docker: from developing to production
Amazon Web Services and Docker: from developing to production
 
Kubernetes @ Nanit by Chen Fisher
Kubernetes @ Nanit by Chen FisherKubernetes @ Nanit by Chen Fisher
Kubernetes @ Nanit by Chen Fisher
 
Kubernetes Architecture and Introduction
Kubernetes Architecture and IntroductionKubernetes Architecture and Introduction
Kubernetes Architecture and Introduction
 
Docker kubernetes fundamental(pod_service)_190307
Docker kubernetes fundamental(pod_service)_190307Docker kubernetes fundamental(pod_service)_190307
Docker kubernetes fundamental(pod_service)_190307
 
KNATIVE - DEPLOY, AND MANAGE MODERN CONTAINER-BASED SERVERLESS WORKLOADS
KNATIVE - DEPLOY, AND MANAGE MODERN CONTAINER-BASED SERVERLESS WORKLOADSKNATIVE - DEPLOY, AND MANAGE MODERN CONTAINER-BASED SERVERLESS WORKLOADS
KNATIVE - DEPLOY, AND MANAGE MODERN CONTAINER-BASED SERVERLESS WORKLOADS
 
Shakr - Container CI/CD with Google Cloud Platform
Shakr - Container CI/CD with Google Cloud PlatformShakr - Container CI/CD with Google Cloud Platform
Shakr - Container CI/CD with Google Cloud Platform
 

Plus de Stefan Schimanski

Plus de Stefan Schimanski (11)

Cutting the Kubernetes Monorepo in pieces
Cutting the Kubernetes Monorepo in piecesCutting the Kubernetes Monorepo in pieces
Cutting the Kubernetes Monorepo in pieces
 
Kubernetes API code-base tour
Kubernetes API code-base tourKubernetes API code-base tour
Kubernetes API code-base tour
 
Extending Kubernetes – Admission webhooks
Extending Kubernetes – Admission webhooksExtending Kubernetes – Admission webhooks
Extending Kubernetes – Admission webhooks
 
Cutting the Kubernetes Monorepo in pieces – never learnt more about git
Cutting the Kubernetes Monorepo in pieces – never learnt more about gitCutting the Kubernetes Monorepo in pieces – never learnt more about git
Cutting the Kubernetes Monorepo in pieces – never learnt more about git
 
Git deep dive – chopping Kubernetes
Git deep dive – chopping KubernetesGit deep dive – chopping Kubernetes
Git deep dive – chopping Kubernetes
 
Extend and build on Kubernetes
Extend and build on KubernetesExtend and build on Kubernetes
Extend and build on Kubernetes
 
Kubernetes API - deep dive into the kube-apiserver
Kubernetes API - deep dive into the kube-apiserverKubernetes API - deep dive into the kube-apiserver
Kubernetes API - deep dive into the kube-apiserver
 
Elastic etcd
Elastic etcdElastic etcd
Elastic etcd
 
Kubernetes on Top of Mesos on Top of DCOS
Kubernetes on Top of Mesos on Top of DCOSKubernetes on Top of Mesos on Top of DCOS
Kubernetes on Top of Mesos on Top of DCOS
 
Cluster Networking with Docker
Cluster Networking with DockerCluster Networking with Docker
Cluster Networking with Docker
 
Beyond static configuration
Beyond static configurationBeyond static configuration
Beyond static configuration
 

Dernier

Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Dernier (20)

MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 

Extending kubernetes with CustomResourceDefinitions

  • 1. Extending Kubernetes with CustomResourceDefinitions Stefan Schimanski sttts@redhat.com / sttts @ GitHub / @the_sttts CONTAINERdays 2018
  • 2.
  • 5. $ kube-apiserver --secure-port 0 --etcd-servers http://127.0.0.1:2379 --service-cluster-ip-range 10.0.0.0/16 --storage-backend etcd2 --storage-media-type application/json $ etcd $ kubectl config set-cluster local --server=http://127.0.0.1:8080 $ kubectl config set-context local --cluster=local $ kubectl config use-context local $ kubectl get namespaces --v=7 $ kubectl get namespace default -o json $ kubectl annotate namespace default meetup=hello $ curl http://127.0.0.1:8080/api/v1/namespaces/default $ etcdctl ls --recursive $ etcdctl get /registry/namespaces/default $ etcdctl -o extended get /registry/namespaces/default
  • 6. $ http GET http://127.0.0.1:8080/api/v1/namespaces/default { "apiVersion": "v1", "kind": "Namespace", "metadata": { "annotations": { "meetup": “hallo" }, "creationTimestamp": "2017-03-10T07:51:39Z", "name": "default", "resourceVersion": “73", }, "spec": { "finalizers": ["kubernetes“] }, "status": { "phase": "Active“ } } $ http GET http://127.0.0.1:8080/api/v1/namespaces/default | jq ".metadata.annotations["meetup"] = "$(date)"" | http PUT http://127.0.0.1:8080/api/v1/namespaces/default HTTP/1.1 200 OK Content-Length: 341 Content-Type: application/json Date: Fri, 10 Mar 2017 08:28:01 GMT
  • 7. /apis/batch/v2alpha1/jobs group version resource HTTP paths: { “apiVersion“: “v2alpha1“, “kind“: “Job“, “metadata“: { “name“: “backup“ }, “spec“: { ... } } http POST as JSON or Proto /namespaces/<name>/ Possible (logical) verbs: • GET • CREATE (= POST) • UPDATE (= PUT) • LIST (GET on root path) • DELETE • PATCH • WATCH (?watch=true)
  • 8. Custom Resources (CRs) & Custom Resource Definitions (CRDs) apiextensions/v1beta1
  • 9. Custom Resource hamburg-sensor.yaml apiVersion: containerdays.io/v1 kind: Sensor metadata: name: hamburg namespace: germany spec: unit: Celcius status: lastUpdated: 2010-03-26T15:13:42.05Z temperature: 28 We want to store these
  • 10. apiextensions-apiserver inside kube-apiserver https://github.com/kubernetes/apiextensions-apiserver In every Kubernetes 1.7+ cluster. kube-apiserver kube-aggregator kube resources apiextensions- apiserver 404 etcd "delegation" "aggregation"
  • 11. Custom Resource hamburg-sensor.yaml apiVersion: containerdays.io/v1 kind: Sensor metadata: name: hamburg namespace: germany spec: unit: Celcius status: lastUpdated: 2010-03-26T15:13:42.05Z temperature: 28 We want to store these
  • 12. Custom Resource Definition (CRD) apiextensions/v1beta1 apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: sensors.containerdays.io spec: group: containerdays.io version: v1 names: kind: Sensor plural: sensors scope: Namespaced mustmatch Defines how CRs are stored
  • 13. Custom Resource Definition (CRD) apiextensions/v1beta1 apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: sensors.containerdays.io spec: group: containerdays.io version: v1 names: kind: Sensor plural: sensors scope: Namespaced $ kubectl create –f sensors-crd.yaml a moment ... status: acceptedNames: kind: Sensor listKind: SensorList plural: sensors singular: sensor conditions: - type: NamesAccepted message: no conflicts found reason: NoConflicts status: "True“ - type: Established message: the initial names have been accepted reason: InitialNamesAccepted status: "True“ mustmatch
  • 14. $ kubectl get sensors –v=7 • I0429 21:17:53.042783 66743 round_trippers.go:383] GET https://localhost:6443/apis • I0429 21:17:53.135811 66743 round_trippers.go:383] GET https://localhost:6443/apis/containerdays.io/v1 • I0429 21:17:53.138353 66743 round_trippers.go:383] GET https://localhost:6443/apis/containerdays.io/v1/namespaces/default/sensors No resources found. sensors → kind Sensor resource sensors discovery LIST API group containerdays.io/v1 We call this "REST mapping"
  • 15. $ http localhost:8080/apis/ { "groups": [{ "name": "containerdays.io", "preferredVersion": {"groupVersion": "containerdays.io/v1", "version": "v1“}, "versions": [{"groupVersion": "containerdays.io/v1", "version": "v1"}] }, ...] } $ http localhost:8080/apis/containerdays.io/v1 { "apiVersion": "v1", "groupVersion": "containerdays.io/v1", "kind": "APIResourceList", "resources": [{ "kind": "Sensor", "name": "sensors", "namespaced": true, "verbs": ["create", "delete", "deletecollection", "get", "list", "patch", "update", "watch“ ] }, ...] } resource name ⇒ /apis/containerdays.io/v1/sensors /namespaces/<name>/
  • 16. $ kubectl get sensors –v=7 • I0429 21:17:53.042783 66743 round_trippers.go:383] GET https://localhost:6443/apis • I0429 21:17:53.135811 66743 round_trippers.go:383] GET https://localhost:6443/apis/containerdays.io/v1 • I0429 21:17:53.138353 66743 round_trippers.go:383] GET https://localhost:6443/apis/containerdays.io/v1/namespaces/default/sensors No resources found. sensors → kind Sensor resource sensors discovery LIST API group containerdays.io/v1 We call this "REST mapping"
  • 17. $ kubectl create –f sensors-crd.yaml $ kubectl create –f hamburg-sensor.yaml apiVersion: containerdays.io/v1 kind: Sensor metadata: name: hamburg namespace: germany spec: unit: Celcius status: lastUpdate: 2010-03-26T15:13:42.05Z temperature: 28 apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: sensors.containerdays.io spec: group: containerdays.io version: v1 names: kind: Sensor plural: sensors scope: Namespaced 1 2 Create the CRD Create CustomResources
  • 18. $ kubectl create –f sensors-crd.yaml $ kubectl create –f hamburg-sensor.yaml apiVersion: containerdays.io/v1 kind: Sensor metadata: name: hamburg namespace: germany spec: unit: Celcius status: lastUpdate: 2010-03-26T15:13:42.05Z temperature: 28 apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: sensors.containerdays.io spec: group: containerdays.io version: v1 names: kind: Sensor plural: sensors scope: Namespaced 1 2 Create the CRD Create CustomResources Follow spec+status pattern.
  • 19. $ kubectl get sensors –w --no-headers brussels <none> {"apiVersion":"containerdays.io/v1","kind":"Sensor",... hamburg <none> {"apiVersion":"containerdays.io/v1","kind":"Sensor",... $ curl -f 'http://127.0.0.1:8080/apis/containerdays.io/v1/namespaces/default/sensors?watch=true&resourceVersion=434‘ {"type":"DELETED","object":{"apiVersion":"containerdays.io/v1","kind":"Sensor","metadata":{"name":"brussels","namespace ":"hamburg","selfLink":"/apis/containerdays.io/v1/namespaces/belgium/sensors/brussels","uid":"8f5312c0-29c8-11e7-88f9- 4c3275978b79","resourceVersion":"435","creationTimestamp":"2017-04-25T15:05:03Z"},"spec":{...}}} {"type":"ADDED","object":{"apiVersion":"containerdays.io/v1","kind":"Sensor","metadata":{"name":"hamburg","namespace ":"germany","selfLink":"/apis/containerdays.io/v1/namespaces/germany/sensors/berlin","uid":"b4318cb5-29c8-11e7-88f9- 4c3275978b79","resourceVersion":"436","creationTimestamp":"2017-04-25T15:06:05Z"},"spec":{...}}} Watch, i.e. event stream
  • 20. Validation • The standard: OpenAPI v3 schema • based on JSON Schema apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: sensors.containerdays.io spec: group: containerdays.io version: v1 names: ... validation: openAPIV3Schema: <see next slide>
  • 21. spec: unit: Celclius status: lastUpdate: 2010-03-26T... temperatur: true properties: spec: properties: unit: anyOf: [{"pattern": "^Celclius$"}, …] default: "Celcius"} required: ["unit"] status: properties: lastUpdate: {"type": "string", "pattern": "^[0-9]+-...$"}, temperature: {"type": "number", "minimum": -273.15}, required: [] OpenAPIv3Schema a quantor (anyOf, oneOf, allOf exist) note: enum is forbidden (why?) regular expression probably in 1.12+ Custom Resource Helpful tools: kubernetes/kube-openapi#37 tamalsaha/kube-openapi-generator Some other tool from prometheus-operator? Rancher has another one, speak to @lemonjet
  • 22. Controllers where is the business logic?
  • 23. $ while true; do http GET http://127.0.0.1:8080/api/v1/namespaces/default | jq ".metadata.annotations["meetup"] = "$(date)"" | http --check-status PUT http://127.0.0.1:8080/api/v1/namespaces/default || break done ⟲ 1. read object (preferably event driven with watches) 2. change object, update the world 3. update object on apiserver 4. repeat
  • 24. $ while true; do http GET http://127.0.0.1:8080/api/v1/namespaces/default | {jq ".metadata.annotations["meetup"] = "$RANDOM""; sleep 1;} | http --check-status PUT http://127.0.0.1:8080/api/v1/namespaces/default || break done HTTP/1.1 409 Conflict Content-Length: 310 Content-Type: application/json Date: Fri, 10 Mar 2017 08:27:58 GMT { "apiVersion": "v1", "code": 409, "details": { "kind": "namespaces", "name": "default“ }, "kind": "Status", "message": "Operation cannot be fulfilled on namespaces "default": the object has been modified; please apply your changes to the latest version and try again", "metadata": {}, "reason": "Conflict", "status": "Failure“ } „optimistic concurrency“
  • 25. $ while true; do http GET http://127.0.0.1:8080/api/v1/namespaces/default | jq ".metadata.annotations["meetup"] = "$(date)"" | http --check-status PUT http://127.0.0.1:8080/api/v1/namespaces/default || break done ⟲ 1. read object (preferably event driven with watches) 2. change object, update the world 3. update object on apiserver 4. repeat expect version conflicts, remember: optimistic concurrency
  • 26. $ kubectl get namespaces --watch --no-headers | while read NS STATUS TIME ; do # do whatever you like here, e.g. change the namespace echo "$NS changed“ done ⟲ W atch=nohot looping $ curl -f 'http://127.0.0.1:8080/api/v1/namespaces?watch=true&resourceVersion=4711‘ {"type":"ADDED","object":{"kind":"Namespace","apiVersion":"v1","metadata":{"name ... {"type":“MODIFIED","object":{"kind":"Namespace","apiVersion":"v1","metadata":{"name ... {"type":“DELETED","object":{"kind":"Namespace","apiVersion":"v1","metadata":{"name ...
  • 28. "CRDs are limited" • no version conversion (only one version possible per CRD) • in 1.11 multiple versions, but no conversion • in 1.12+ conversions come, but slowly • no defaulting (PR exists) • no validation (beta in 1.9, Google Summer of Code project) • no subresources (scale, status) (beta in 1.11) • no admission (since 1.7: admission webhooks + initializers) • alpha CRDs are beta • no custom printing in kubectl (in 1.11: custom printer columns)
  • 29. Outlook – Custom Resources • Kubernetes 1.11 • Server Side Printing Columns – “kubectl get” customization – #60991 • β : Multiple versions without conversion – design proposal • β: Subresources – ⍺ since 1.10 – #62786 • OpenAPI additionalProperties allowed now (mutually exclusive with properties) • Kubernetes 1.12+ • ⍺: Multiple versions with declarative field renames • ⍺: Graceful Deletion – being discussed – #63162 • ⍺: Pruning – in validation spec unspecified fields are removed – blocker for GA • ⍺: Defaulting – defaults from OpenAPI validation schema are applied • Strict create mode? Discuss: #5889 – my favorite CRD UX issue Related: CRD OpenAPI validation spec not served by kube-apiserver
  • 30.
  • 32. Zoom into apiextensions-apiserver kube-apiserver kube- aggregator kube resources apiextensions-apiserver 404 etcd "delegation" "aggregation" authn/z CR handlers CR handlers CR handlers ⟲Naming Controller ⟲CRD Finalizer request conversion& defaulting storage conversion & defaulting REST logic result conversion validation admission decoding encode GET CREATE LIST UPDATE DELETE WATCH mutating webhooks validating webhooks NoOps json.Unmarshal
  • 33. /apis/extensions/v1alpha1/jobs/backup /apis/batch/v2alpha1/jobs/backup /apis/batch/v1/jobs/backup { “apiVersion“: “v1alpha1“, “kind“: “Job“, “metadata“: { “name“: “backup“ }, “spec“: { ... } } { “apiVersion“: “v2alpha1“, “kind“: “Job“, “metadata“: { “name“: “backup“ }, “spec“: { ... } } { “apiVersion“: “v1“, “kind“: “Job“, “metadata“: { “name“: “backup“ }, “spec“: { ... } } lossless conversion * I omitted the namespace in /apis/batch/v1/jobs/namespaces/default/backup
  • 34. { “apiVersion“: “v1alpha1“, “kind“: “Job“, “metadata“: { “name“: “backup“ }, “spec“: { ... } } { “apiVersion“: “v2alpha1“, “kind“: “Job“, “metadata“: { “name“: “backup“ }, “spec“: { ... } } { “apiVersion“: “v1 “, “kind“: “Job“, “metadata“: { “name“: “backup“ }, “spec“: { ... } } lossless conversion etcd { “apiVersion“: “v1 “, “kind“: “Job“, “metadata“: { “name“: “backup“ }, “spec“: { ... } } Protobuf or JSON storage version encoding