이 선언적 접근 방식은 자동화 엔지니어로서의 작업을 용이하게 했습니다.

.ltag__user__id__404393 .follow-action-button {
배경색: #d7dee2 !important;
색상: #090277 !중요;
테두리 색상: #d7dee2 !important;
}



아미트 바트 팔로우



Software Engineer at Acquia || Ex MayaData ||CKA || Chaos Engineering || Contributer @LitmusChaos || Kubernetes || DevOps || GoLang



한동안 Ansible을 사용하여 Kubernetes와 관련된 모든 것을 자동화했습니다. 나를 짜증나게 하는 것 중 하나는 내 작업을 자동화하기 위해 Ansible YAML과 함께 bash, awk, sed, 루프 및 조건의 혼합이었습니다. 쿠버네티스 오퍼레이터 패턴이 제공하는 순수한 선언적 인텐트에 대해 자세히 알아보기 위해 시간을 투자하기로 결정한 때입니다. 이 글은 투자에 대한 저의 경험을 요약한 것입니다.

그렇다면 이 선언적 접근 방식은 무엇입니까?



이것은 확실히 쿠버네티스 내에서 기원한 것이 아닙니다. 사실 Jenkinsfile(예: Groovy 스크립트) 또는 Terraform을 작성했거나 YAML을 사용하여 애플리케이션의 구성을 표현했다면 이미 프로그래밍의 선언적 뉘앙스를 경험한 것입니다. 그러나 선언적이라는 쿠버네티스 방식은 약간의 소금으로 파악해야 합니다. 쿠버네티스는 팀이 인프라를 처리할 수 있도록 사용자 지정 리소스 및 지원 컨트롤러의 사용을 옹호해 왔습니다. html과 backing javascript를 책임을 명확하게 분리하고 사용자 인터페이스 스타일을 논리와 혼합하지 않도록 하는 비유로 생각할 수 있습니다. 올바르게 수행하면 html은 웹 페이지의 모양과 느낌을 정의하고 javascript는 동작 부분을 처리합니다. 아아, 조언과 모범 사례에 대한 관심은 거의 없습니다. 우리는 종종 html 사양에 내장된 많은 자바스크립트를 발견합니다. 논리가 선언으로 들어가는 다른 선언적 접근 방식에 대해서도 마찬가지입니다. 반면에 Kubernetes는 이러한 선언이 순수하게 유지되도록 옹호합니다. 따라서 포드 사양 내에서 템플릿이나 루프를 찾을 수 없습니다.

쿠버네티스 세계에서는 커스텀 리소스를 사용하여 부작용(읽기 논리)이 없는 선언적 의도를 표현합니다. 여기서 끝나지 않습니다. 이러한 사양은 원하는 상태를 정의하고 해당 컨트롤러는 원하는 상태를 현실로 만드는 책임이 있습니다. 쿠버네티스 제어 루프를 깊이 파고들기 위해 여기 있는 것이 아니므로 바로 본론으로 들어가겠습니다. Kubernetes를 다룰 때 필요한 것은 Kubernetes 클러스터에 우리의 의도를 전달하기 위한 CLI와 여러 YAML뿐입니다.

d-연산자 ​​소개



Kubernetes 리소스를 관리하기 위한 명령형 워크플로처럼 보이는 선언적 인텐트를 정의하기 위해 d-operators 실험을 시작했습니다. 전반적으로 저는 YAML 내에서 kubectl 및 기타 명령 기반 호출을 사용하는 것을 피하고 싶었습니다. D-operator는 내부적으로 metacontroller SDK를 사용합니다. 내 의도는 yaml 작성자가 yaml 파일을 사용하여 하나 이상의 Kubernetes 리소스(네이티브 및 사용자 지정)를 생성, 삭제, 업데이트, 어설션, 패치, 복제, 예약 등을 수행할 수 있도록 하는 것입니다. 이 yaml 파일은 다시 조정 및 기타 Kubernetes 내부를 처리하는 백업 Kubernetes 컨트롤러에 의해 관리됩니다.

말할 필요도 없이 이 프로젝트는 스크립트, kubectl, 루프, 조건, 템플릿 등으로 어수선한 yaml을 처리하는 대신 사양을 정의하기 위해 순수한 의도 기반 접근 방식을 따르기 위해 최선을 다합니다.

c̶o̶d̶e̶ YAML을 보여주세요



다음은 Kubernetes 포드와 관련하여 CRUD 작업을 실행하는 자동화된 방법입니다.

apiVersion: dope.metacontroller.io/v1
kind: Recipe
metadata:
  name: crud-ops-on-pod
  namespace: d-testing
  labels:
    d-testing.dope.metacontroller.io/enabled: "true"
spec:
  tasks:                       ### -----> Add multiple operations via tasks
  - name: apply-a-namespace    ### ----> This applies a Namespace
    apply:
      state:
        kind: Namespace
        apiVersion: v1
        metadata:
          name: my-ns
  - name: create-a-pod         ### -----> This creates a Pod
    create:
      state:
        kind: Pod
        apiVersion: v1
        metadata:
          name: my-pod
          namespace: my-ns
        spec:
          containers:
          - name: web
            image: nginx
  - name: delete-the-pod       ### -----> This deletes the Pod
    delete:
      state:
        kind: Pod
        apiVersion: v1
        metadata:
          name: my-pod
          namespace: my-ns
  - name: delete-the-namespace  ### ----> This deletes the Namespace
    delete:
      state:
        kind: Namespace
        apiVersion: v1
        metadata:
          name: my-ns

  - name: assert-presence-of-pod ### ----> Check presence of Pod
    assert:
      state:
        kind: Pod
        apiVersion: v1
        metadata:
          name: nginx
          namespace: test



결과



작업 자체에 대한 설명에서 위 yaml의 결과를 볼 수 있습니다.


Name:         crud-ops-on-pod
Namespace:    d-testing
Labels:       d-testing.dope.metacontroller.io/enabled=true
              job.dope.metacontroller.io/phase=Completed
Annotations:  <none>
API Version:  dope.metacontroller.io/v1
Kind:         Recipe
Metadata:
  Creation Timestamp:  2020-07-21T18:59:09Z
  Generation:          1
  Resource Version:    33101724
  Self Link:           /apis/metacontroller.app/v1/namespaces/d-testing/jobs/crud-ops-on-pod
  UID:                 2eb8f663-15cd-4836-bfd5-14b3ca4aefd3
Spec:
  Tasks:
    Apply:
      State:
        API Version:  v1
        Kind:         Namespace
        Metadata:
          Name:  my-ns
    Name:        apply-a-namespace
    Create:
      State:
        API Version:  v1
        Kind:         Pod
        Metadata:
          Name:       my-pod
          Namespace:  my-ns
        Spec:
          Containers:
            Image:  nginx
            Name:   web
    Name:           create-a-pod
    Delete:
      State:
        API Version:  v1
        Kind:         Pod
        Metadata:
          Name:       my-pod
          Namespace:  my-ns
    Name:             delete-the-pod
    Delete:
      State:
        API Version:  v1
        Kind:         Namespace
        Metadata:
          Name:  my-ns
    Name:        delete-the-namespace
    Assert:
      State:
        API Version:  v1
        Kind:         Pod
        Metadata:
          Name:       nginx
          Namespace:  test
    Name:             assert-presence-of-pod
Status:
  Failed Task Count:  0
  Message:            
  Phase:              Completed
  Reason:             
  Task Count:         5
  Task List Status:
    Apply - A - Namespace:
      Message:  Create resource  my-ns: GVK /v1, Kind=Namespace
      Phase:    Passed
      Step:     1
    Assert - Presence - Of - Pod:
      Message:  StateCheckEquals: Resource test nginx: GVK /v1, Kind=Pod: TaskName assert-presence-of-pod
      Phase:    Passed
      Step:     5
    Create - A - Pod:
      Message:  Create action: Resource my-ns my-pod: GVK /v1, Kind=Pod: TaskName create-a-pod
      Phase:    Passed
      Step:     2
    Crud - Ops - On - Pod - Lock:
      Internal:  true
      Message:   Create: Lock d-testing crud-ops-on-pod-lock: GVK /v1, Kind=ConfigMap
      Phase:     Passed
      Step:      0
    Crud - Ops - On - Pod - Unlock:
      Internal:  true
      Message:   Locked forever
      Phase:     Passed
      Step:      7
    Delete - The - Namespace:
      Message:  Delete: Resource  my-ns: GVK /v1, Kind=Namespace
      Phase:    Passed
      Step:     4
    Delete - The - Pod:
      Message:  Delete: Resource my-ns my-pod: GVK /v1, Kind=Pod
      Phase:    Passed
      Step:     3
    Job - Elapsed - Time:
      Elapsed Time In Seconds:  0.239145302
      Internal:                 true
      Phase:                    Passed
      Step:                     6
Events:                         <none>



결론



이 예제에서는 여러 Kubernetes 작업을 선언적 사양으로 변환하는 방법을 살펴보았습니다. 우리는 또한 yaml 내에서 kubectl 및 기타 명령형 논리를 피할 수 있었습니다. d-operators를 통해 달성할 수 있는 것에는 더 많은 것이 있지만 이 기사에서는 Kubernetes를 사용하여 처리 인프라를 재구성하는 접근 방식을 보여줍니다. 즉, Kubernetes에서 작동할 때 Kubernetes처럼 생각하는 것이 좋습니다(순수한 선언 읽기).

좋은 웹페이지 즐겨찾기