ЁЯПл The SchoolтА║тШ╕я╕П KubernetesтА║ЁЯдЦ рдзрдбрд╛ 25 тАФ CRDs рдЖрдгрд┐ operators: office рд▓рд╛ рдирд╡реЗ рд╢рдмреНрдж рд╢рд┐рдХрд╡рдгреЗ
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯдЦ рдзрдбрд╛ 25 тАФ CRDs рдЖрдгрд┐ operators: office рд▓рд╛ рдирд╡реЗ рд╢рдмреНрдж рд╢рд┐рдХрд╡рдгреЗ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: рдзрдбрд╛ 25 / 26 ┬╖ рдорд╛рдЧреАрд▓: lesson-24-cluster-upgrades ┬╖ рдкреБрдвреАрд▓: lesson-26-observability


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдЖрдзреАрдЪреЗ рд╕рдЧрд│реЗ, рдЖрдгрд┐ рдЕрд░реНрдзреНрдпрд╛ cloud-native рдЬрдЧрд╛рдорд╛рдЧрдЪреА рд╡рд┐рд╕реНрддрд╛рд░-рдпрдВрддреНрд░рдгрд╛: CustomResourceDefinitions рдЖрдгрд┐ operator pattern.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рд╢рд╛рд│реЗрдЪреЗ office (L13) рдПрдХ рдард░рд▓реЗрд▓рд╛ рд╢рдмреНрджрдХреЛрд╢ рдмреЛрд▓рддреЗ: Pod, Deployment, ServiceтАж рдкрдг Kubernetes рдЪреА рд╕рд░реНрд╡рд╛рдд рдЦреЛрд▓ рдпреБрдХреНрддреА рд╣реА тАФ рддреБрдореНрд╣реА рддреНрдпрд╛рд▓рд╛ рдирд╡реЗ рд╢рдмреНрдж рд╢рд┐рдХрд╡реВ рд╢рдХрддрд╛ ЁЯУЦтЬи:

  1. рд╢рдмреНрдж рд╢рдмреНрджрдХреЛрд╢рд╛рдд рдЬреЛрдбрд╛ (рдПрдХ CRD): "рдЖрддрд╛ BackupPlan рдирд╛рд╡рд╛рдЪреА рдЧреЛрд╖реНрдЯ рдЖрд╣реЗ, рдЖрдгрд┐ рддрд┐рдЪреНрдпрд╛ fields рдЪрд╛ рдЕрд░реНрде рд╣рд╛ рдЖрд╣реЗ." рд▓рдЧреЗрдЪ kubectl get backupplans рдЪрд╛рд▓рддреЗ, рдЗрдЪреНрдЫрд╛ рдиреЛрдВрджрд╡рд╣реАрдд (etcd) рд╕рд╛рдард╡рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд, RBAC рддреНрдпрд╛рдВрдЪреНрдпрд╛рд╡рд░ рдлрд╛рдЯрдХ рд▓рд╛рд╡реВ рд╢рдХрддреЗ (L17)тАж рдЖрдгрд┐ рдмрд╛рдХреА рдХрд╛рд╣реАрдЪ рдШрдбрдд рдирд╛рд╣реА. рдХреЛрдгрд╛рд▓рд╛рдЪ рди рдХрд│рдгрд╛рд░рд╛ рд╢рдмреНрдж рдореНрд╣рдгрдЬреЗ рдлрдХреНрдд рдлрд╛рдИрд▓рдордзреНрдпреЗ рдареЗрд╡рд▓реЗрд▓реЗ рдХрд╛рдЧрдж.
  2. рддреНрдпрд╛ рд╢рдмреНрджрд╛рд╡рд░ рдХрд╛рдо рдХрд░рдгрд╛рд░рд╛ robot рдиреЗрдорд╛ (рдПрдХ controller): рддреЛ рдиреЛрдВрджрд╡рд╣реАрдд BackupPlan рдЗрдЪреНрдЫрд╛рдВрд╡рд░ рд▓рдХреНрд╖ рдареЗрд╡рддреЛ рдЖрдгрд┐ рд╡рд╛рд╕реНрддрд╡ рд╕рддрдд рддреНрдпрд╛рдВрдЪреНрдпрд╛рд╢реА рдЬреБрд│рд╡рдд рд░рд╛рд╣рддреЛ тАФ рдзрдбрд╛ 03 рдЪреНрдпрд╛ рд╡рд░реНрдЧ-monitor рд╕рд╛рд░рдЦрд╛рдЪ reconcile loop, рдлрдХреНрдд рддреБрдореНрд╣реА рд╢реЛрдзрд▓реЗрд▓реНрдпрд╛ рд╢рдмреНрджрд╛рд╕рд╛рдареА.

CRD + controller + рдЖрдд рдмрд╕рд╡рд▓реЗрд▓реЗ рдХреМрд╢рд▓реНрдп = operator тАФ рдПрдХ robot рдХрд░реНрдордЪрд╛рд░реА рдЬреЛ software рдПрдЦрд╛рджрд╛ рдорд╛рдирд╡реА рддрдЬреНрдЬреНрдЮ рдЪрд╛рд▓рд╡реЗрд▓ рддрд╕реЗ рдЪрд╛рд▓рд╡рддреЛ:

рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛рдпрдЪрд╛ pattern: Kubernetes рдордзреНрдпреЗ, рд╕рдЧрд│реЗ рдХрд╛рд╣реА тАФ рдЕрдВрдЧрднреВрдд рдЕрд╕реЛ рд╡рд╛ рд╢реЛрдзрд▓реЗрд▓реЗ тАФ рдиреЛрдВрджрд╡рд╣реАрддрд▓рд╛ рдПрдХ рд╢рдмреНрдж рдЖрдгрд┐ рддреЛ рдЦрд░рд╛ рдХрд░рдгрд╛рд░рд╛ рдПрдХ robot рдЕрд╕рддреЗ.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    crd["ЁЯУЦ CRD<br/>new word: BackupPlan<br/>+ its grammar (fields)"]
    api["ЁЯПв office / etcd<br/>stores BackupPlan wishes<br/>kubectl & RBAC just work"]
    cr["ЁЯУД your wish<br/>kind: BackupPlan<br/>nightly: true"]
    ctrl["ЁЯдЦ controller<br/>watches the word,<br/>reconciles forever (= L03 loop)"]
    real["тЬЕ reality<br/>CronJobs created,<br/>buckets configuredтАж"]
    crd -->|"1 teach"| api
    cr -->|"2 file a wish"| api
    ctrl -->|"3 reads wishes"| api
    ctrl -->|"4 makes true"| real

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

"рд╕рдЧрд│реЗ Kubernetes рдЪреНрдпрд╛ рд╢реЗрдЬрд╛рд░реА рди рдмрд╛рдВрдзрддрд╛ рддреНрдпрд╛рдЪреНрдпрд╛ рд╡рд░ рдХрд╛ рдмрд╛рдВрдзрддрд╛рдд" рдпрд╛рдЪреЗ рд╣реЗ рдЙрддреНрддрд░ рдЖрд╣реЗ: рдПрдХ рдиреЛрдВрджрд╡рд╣реА, рдПрдХ reconcile pattern, рдПрдХ CLI, рдПрдХ RBAC тАФ рдХреЛрдгреАрд╣реА рдХрдзреАрд╣реА рд╢реЛрдзрд▓реЗрд▓реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрдХрд▓реНрдкрдиреЗрд╕рд╛рдареА. CRDs рд╕рдордЬрд▓реНрдпрд╛рдореБрд│реЗ ArgoCD, cert-manager рдЖрдгрд┐ CloudNativePG рд╕рд╛рд░рдЦреА tools рдЬрд╛рджреВ рди рд░рд╛рд╣рддрд╛ "рдПрдХ рд╢рдмреНрдж рдЖрдгрд┐ рдПрдХ robot" рдмрдирддрд╛рдд тАФ рдЖрдгрд┐ рд╣реЗ рдорд╛рдирд╕рд┐рдХ рдореЙрдбреЗрд▓ рд╣реАрдЪ рдЦрд░реА рдкрджрд╡реА.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛ тАФ robot рд╢рд┐рд╡рд╛рдп рдПрдХ рд╢рдмреНрдж рд╢рд┐рдХрд╡рд╛, рдЖрдгрд┐ рд╢рд╛рдВрддрддрд╛ рдЕрдиреБрднрд╡рд╛

kubectl apply -f - <<'EOF'
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata: { name: backupplans.school.example.com }
spec:
  group: school.example.com
  scope: Namespaced
  names: { kind: BackupPlan, plural: backupplans, singular: backupplan }
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                nightly: { type: boolean }
EOF

kubectl apply -f - <<'EOF'
apiVersion: school.example.com/v1
kind: BackupPlan
metadata: { name: my-wish, namespace: school }
spec: { nightly: true }
EOF

kubectl -n school get backupplans          # your word, first-class citizen!
# ...and nothing else happens, ever тАФ no robot knows the word. THAT gap
# (wish stored тЙа wish fulfilled) is exactly what a controller fills. ЁЯдЦ

kubectl -n school delete backupplan my-wish
kubectl delete crd backupplans.school.example.com

ЁЯФз рдпрд╛ рдзрдбреНрдпрд╛рд╕рд╛рдареА kubectl

kubectl get crd ┬╖ kubectl explain ┬╖ kubectl api-resources | grep school

ЁЯФЧ рдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд: ЁЯдЦ ArgoCD рд╢рд╛рд│рд╛ L07 (Application рдореНрд╣рдгрдЬреЗ рдиреЗрдордХреЗ рд╣реЗрдЪ)

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ

CRD рдирдВрддрд░ kubectl get backupplans рдЪрд╛рд▓рддреЗ; kubectl explain backupplan рддреБрдордЪрд╛ schema рдЫрд╛рдкрддреЗ.

ЁЯз╣ рд╕рд╛рдлрд╕рдлрд╛рдИ

kubectl delete crd backupplans.school.io рддреЛ рд╢рдмреНрдж рдЖрдгрд┐ рддреНрдпрд╛рдЪреЗ рдкреНрд░рддреНрдпреЗрдХ object рдХрд╛рдвреВрди рдЯрд╛рдХрддреЛ

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

тПня╕П рдкреБрдвреЗ

рд╢реЗрд╡рдЯрдЪрд╛ рдзрдбрд╛: рд╣реЗ рд╕рдЧрд│реЗ рдЪрд╛рд▓рддрд╛рдирд╛ рддреБрдореНрд╣рд╛рд▓рд╛ рдЦрд░реЛрдЦрд░ рджрд┐рд╕рддреЗ рдХрд╛? рдкреНрд░рдЧрддрд┐рдкреБрд╕реНрддрдХреЗ, рджреИрдирдВрджрд┐рдиреА рдЖрдгрд┐ рдзреЛрдХреНрдпрд╛рдЪреНрдпрд╛ рдШрдВрдЯрд╛: observability.

git checkout lesson-26-observability

ЁЯдЦ Lesson 25 тАФ CRDs & operators: teaching the office new words

ЁЯУН You are here: Lesson 25 of 26 ┬╖ Previous: lesson-24-cluster-upgrades ┬╖ Next: lesson-26-observability


ЁЯУж What's in this branch

Everything before, plus the extension mechanism behind half the cloud-native world: CustomResourceDefinitions and the operator pattern.

ЁЯзТ Explain like I'm 5

The school office (L13) speaks a fixed dictionary: Pod, Deployment, ServiceтАж But here's Kubernetes' deepest trick тАФ you can teach it new words ЁЯУЦтЬи:

  1. Add the word to the dictionary (a CRD): "there is now a thing called BackupPlan, and here's what its fields mean." Instantly, kubectl get backupplans works, wishes get stored in the register (etcd), RBAC can gate them (L17)тАж and absolutely nothing else happens. A word with no one who understands it is just filed paperwork.
  2. Hire a robot who acts on the word (a controller): it watches the register for BackupPlan wishes and endlessly makes reality match тАФ the SAME reconcile loop as lesson 03's class monitor, just for a word you invented.

CRD + controller + baked-in expertise = an operator тАФ a robot employee that runs software the way a human expert would:

The pattern to remember: in Kubernetes, everything тАФ built-in or invented тАФ is a word in the register plus a robot who makes it true.

ЁЯЧ║я╕П Diagram

flowchart LR
    crd["ЁЯУЦ CRD<br/>new word: BackupPlan<br/>+ its grammar (fields)"]
    api["ЁЯПв office / etcd<br/>stores BackupPlan wishes<br/>kubectl & RBAC just work"]
    cr["ЁЯУД your wish<br/>kind: BackupPlan<br/>nightly: true"]
    ctrl["ЁЯдЦ controller<br/>watches the word,<br/>reconciles forever (= L03 loop)"]
    real["тЬЕ reality<br/>CronJobs created,<br/>buckets configuredтАж"]
    crd -->|"1 teach"| api
    cr -->|"2 file a wish"| api
    ctrl -->|"3 reads wishes"| api
    ctrl -->|"4 makes true"| real

тЭУ What

ЁЯдФ Why

This is the answer to "why does everyone build ON Kubernetes instead of NEXT to it": one register, one reconcile pattern, one CLI, one RBAC тАФ for every concept anyone ever invents. Understanding CRDs turns tools like ArgoCD, cert-manager and CloudNativePG from magic into "a word plus a robot" тАФ and that mental model is the real graduation.

ЁЯзк Try it тАФ teach a word with NO robot, and feel the silence

kubectl apply -f - <<'EOF'
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata: { name: backupplans.school.example.com }
spec:
  group: school.example.com
  scope: Namespaced
  names: { kind: BackupPlan, plural: backupplans, singular: backupplan }
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                nightly: { type: boolean }
EOF

kubectl apply -f - <<'EOF'
apiVersion: school.example.com/v1
kind: BackupPlan
metadata: { name: my-wish, namespace: school }
spec: { nightly: true }
EOF

kubectl -n school get backupplans          # your word, first-class citizen!
# ...and nothing else happens, ever тАФ no robot knows the word. THAT gap
# (wish stored тЙа wish fulfilled) is exactly what a controller fills. ЁЯдЦ

kubectl -n school delete backupplan my-wish
kubectl delete crd backupplans.school.example.com

ЁЯФз kubectl for this lesson

kubectl get crd ┬╖ kubectl explain ┬╖ kubectl api-resources | grep school

ЁЯФЧ Builds on: ЁЯдЦ ArgoCD school L07 (Application is exactly this)

тЬЕ Verify тАФ what you should see

kubectl get backupplans works after the CRD; kubectl explain backupplan prints your schema.

ЁЯз╣ Clean up

kubectl delete crd backupplans.school.io removes the word and every object of it

тЪая╕П Common mistakes

тПня╕П Next

The final lesson: can you actually SEE all of this running? Report cards, diaries and alarm bells: observability.

git checkout lesson-26-observability
тЖР Previouscluster upgradesNext тЖТobservability

This page is the lesson's README from the lesson-25-crds-operators branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.