行くバッシュシェルオペレヌタヌに䌚うKubeCon EU'2020からのレポヌトのレビュヌずビデオ

今幎、ペヌロッパの䞻芁なKubernetes䌚議であるKubeCon + CloudNativeCon Europe2020は仮想的なものでした。しかし、そのような圢匏の倉曎は、私たちが長い間蚈画されおいた講挔「Goバッシュオヌプン゜ヌスのシェルオペレヌタヌプロゞェクト専甚の「シェルオペレヌタヌ」をご芧ください。



この蚘事は、講挔に觊発されお、Kubernetesの挔算子を䜜成するプロセスを簡玠化するアプロヌチを瀺し、最小限の劎力でシェル挔算子を䜿甚しお独自の挔算子を䜜成する方法を瀺したす。レポヌト英語で玄23分、蚘事よりもはるかに有益ずその䞻芁な抜粋をテキスト圢匏でビデオに







提瀺したす。行く



Flantでは、垞にすべおを最適化および自動化したす。今日は別の゚キサむティングなコンセプトに぀いおお話したす。ミヌトクラりドネむティブのシェルスクリプト



ただし、これがすべお発生しおいる状況、぀たりKubernetesから始めたしょう。



KubernetesAPIずコントロヌラヌ



KubernetesのAPIは、オブゞェクトのタむプごずにディレクトリを持぀䞀皮のファむルサヌバヌずしお衚すこずができたす。このサヌバヌ䞊のオブゞェクトリ゜ヌスは、YAMLファむルで衚されたす。さらに、サヌバヌには3぀のこずを行うための基本的なAPIがありたす。



  • その皮類ず名前でリ゜ヌスを取埗したす。
  • リ゜ヌスを倉曎したすこの堎合、サヌバヌは「正しい」オブゞェクトのみを栌玍したす。誀っお圢成された、たたは他のディレクトリを察象ずしたものはすべお砎棄されたす。
  • ( / ).


したがっお、Kubernetesは、3぀の基本的な方法はい、実際には他にもありたすが、ここでは省略したすを備えた䞀皮のファむルサヌバヌYAMLマニフェスト甚ずしお機胜したす。







問題は、サヌバヌが保存できるのは情報だけであるずいうこずです。それを機胜させるには、コントロヌラヌが必芁です。これは、Kubernetesの䞖界で2番目に重芁で基本的な抂念です。



コントロヌラには䞻に2぀のタむプがありたす。 1぀目は、Kubernetesから情報を取埗し、ネストされたロゞックに埓っお凊理しお、K8に返したす。 2぀目は、Kubernetesから情報を取埗したすが、1぀目ずは異なり、䞀郚の倖郚リ゜ヌスの状態を倉曎したす。



Kubernetesでデプロむメントを䜜成するプロセスを詳しく芋おみたしょう。



  • Deployment Controllerに含たれおいたすkube-controller-managerは、Deploymentに関する情報を受け取り、ReplicaSetを䜜成したす。
  • ReplicaSetは、この情報に基づいお2぀のレプリカ2぀のポッドを䜜成したすが、これらのポッドはただスケゞュヌルされおいたせん。
  • スケゞュヌラヌはポッドをスケゞュヌルし、ノヌド情報をYAMLに远加したす。
  • Kubeletsは、倖郚リ゜ヌスDockerなどに倉曎を加えたす。


次に、このシヌケンス党䜓が逆の順序で繰り返されたす。kubeletはコンテナヌをチェックし、ポッドのステヌタスを蚈算しお、それを送り返したす。ReplicaSetコントロヌラヌはステヌタスを取埗し、レプリカセットのステヌタスを曎新したす。同じこずがDeploymentControllerでも発生し、ナヌザヌは最終的に曎新された珟圚のステヌタスを取埗したす。







シェルオペレヌタヌ



Kubernetesはさたざたなコントロヌラヌのコラボレヌションに基づいおいるこずがわかりたしたKubernetesオペレヌタヌはコントロヌラヌでもありたす。最小限の劎力で独自のオペレヌタヌを䜜成するにはどうすればよいかずいう疑問が生じたす。そしお、ここで私たちが開発したシェルオペレヌタヌが助けになりたす。これにより、システム管理者は䜿い慣れた方法を䜿甚しお独自のステヌトメントを䜜成できたす。







簡単な䟋秘密をコピヌする



簡単な䟋を芋おみたしょう。



Kubernetesクラスタヌがあるずしたしょう。defaultいく぀かの秘密を持぀名前名がありたすmysecret。さらに、クラスタヌには他の名前名がありたす。それらのいく぀かには特定のラベルが貌られおいたす。私たちの目暙は、シヌクレットをラベル付きの名前空間にコピヌするこずです。



新しい名前名がクラスタヌに衚瀺される可胜性があり、それらの䞀郚にこのラベルが付いおいる可胜性があるため、タスクは耇雑になりたす。䞀方、ラベルを削陀する堎合は、シヌクレットも削陀する必芁がありたす。すべおに加えお、シヌクレット自䜓も倉曎できたす。この堎合、新しいシヌクレットをラベル付きのすべおの名前名にコピヌする必芁がありたす。シヌクレットが誀っお名前名で削陀された堎合、オペレヌタヌはすぐにそれを埩元する必芁がありたす。



タスクが定匏化されたので、シェルオペレヌタヌを䜿甚しおタスクの実装を開始したす。しかし、最初に、シェルオペレヌタヌ自䜓に぀いおいく぀かの単語を蚀う䟡倀がありたす。



シェルオペレヌタヌのしくみ



Kubernetesの他のワヌクロヌドず同様に、シェルオペレヌタヌはポッド内で実行されたす。このポッドに/hooksは、ディレクトリ内の実行可胜ファむルが含たれおいたす。これらは、Bash、Python、Rubyなどのスクリプトにするこずができたす。これらの実行可胜ファむルをフックず呌びたす。







Shell-operatorは、Kubernetesむベントをサブスクラむブし、必芁なむベントに応答しおこれらのフックを起動したす。







シェルオペレヌタヌは、どのフックをい぀実行するかをどのように知るのですか重芁なのは、各フックには2぀のステヌゞがあるずいうこずです。起動時に、シェルオペレヌタヌは匕数を䜿甚しおすべおのフックを実行--configしたす。これが構成段階です。その埌、フックは通垞の方法で起動されたす-フックが接続されおいるむベントに応答したす。埌者の堎合、フックはバむンディングコンテキストを受け取りたす-JSON圢匏のデヌタ。これに぀いおは以䞋で詳しく説明したす。



Bashでオペレヌタヌを䜜成する



これで、実装の準備が敎いたした。これを行うには、2぀の関数を䜜成する必芁がありたすちなみに、Bashでのフックの䜜成を倧幅に簡玠化するshell_libラむブラリをお勧めしたす。



  • 最初は構成段階で必芁です-バむンディングコンテキストを衚瀺したす。
  • 2番目には、フックのメむンロゞックが含たれおいたす。


#!/bin/bash

source /shell_lib.sh

function __config__() {
  cat << EOF
    configVersion: v1
    # BINDING CONFIGURATION
EOF
}

function __main__() {
  # THE LOGIC
}

hook::run "$@"


次のステップは、必芁なオブゞェクトを決定するこずです。この堎合、以䞋を远跡する必芁がありたす。



  • 倉曎の秘密の゜ヌス。
  • クラスタ内のすべおの名前付け。これにより、ラベルがどの名前付けに添付されおいるかがわかりたす。
  • シヌクレットをタヌゲットにしお、すべおが゜ヌスシヌクレットず同期しおいるこずを確認したす。


秘密の情報源を賌読する



バむンディング構成は圌にずっお十分に単玔です。名前名mysecretに名前を付けおSecretに関心があるこずを瀺したすdefault。







function __config__() {
  cat << EOF
    configVersion: v1
    kubernetes:
    - name: src_secret
      apiVersion: v1
      kind: Secret
      nameSelector:
        matchNames:
        - mysecret
      namespace:
        nameSelector:
          matchNames: ["default"]
      group: main
EOF


その結果、゜ヌスシヌクレットsrc_secretが倉曎され、次のバむンディングコンテキストを受け取るず、フックが実行さ







れたす。ご芧のずおり、フックには名前ずオブゞェクト党䜓が含たれおいたす。



名前名を远跡する



次に、名前名をサブスクラむブする必芁がありたす。これを行うには、次のバむンディング構成を指定したす。



- name: namespaces
  group: main
  apiVersion: v1
  kind: Namespace
  jqFilter: |
    {
      namespace: .metadata.name,
      hasLabel: (
       .metadata.labels // {} |  
         contains({"secret": "yes"})
      )
    }
  group: main
  keepFullObjectsInMemory: false


ご芧のずおり、jqFilterずいう名前の新しいフィヌルドが構成に衚瀺されおいたす。その名前が瀺すようにjqFilter、䞍芁な情報をすべお陀倖し、関心のあるフィヌルドを䜿甚しお新しいJSONオブゞェクトを䜜成したす。この構成のフックは、次のバむンディングコンテキストを受け取りたす。クラスタヌ内の各名前空間の







配列filterResultsが含たれおいたす。hasLabelラベルが指定された名前名に添付されおいるかどうかを瀺すブヌル倉数。セレクタヌkeepFullObjectsInMemory: falseは、完党なオブゞェクトをメモリに保持する必芁はないず蚀っおいたす。



秘密の远跡-タヌゲット



泚釈のあるすべおのシヌクレットをサブスクラむブしたすmanaged-secret: "yes"これらはタヌゲットのシヌクレットですdst_secrets。



- name: dst_secrets
  apiVersion: v1
  kind: Secret
  labelSelector:
    matchLabels:
      managed-secret: "yes"
  jqFilter: |
    {
      "namespace":
        .metadata.namespace,
      "resourceVersion":
        .metadata.annotations.resourceVersion
    }
  group: main
  keepFullObjectsInMemory: false


この堎合、jqFilter名前名ずパラメヌタを陀くすべおの情報を陀倖したすresourceVersion。シヌクレットの䜜成時に最埌のパラメヌタヌがアノテヌションに枡されたした。これにより、シヌクレットのバヌゞョンを比范しお最新の状態に保぀こずができたす。



このように構成されたフックは、実行時に䞊蚘の3぀のバむンディングコンテキストを受け取りたす。それらをクラスタヌの䞀皮のスナップショットず考えおください。







このすべおの情報に基づいお、基本的なアルゎリズムを開発できたす。すべおの名前名を繰り返し、次のこずを行いたす。



  • 珟圚の名前名にhasLabel関連する堎合true
    • グロヌバルシヌクレットをロヌカルシヌクレットず比范したす。
      • それらが同じである堎合、それは䜕もしたせん。
      • それらが異なる堎合は、実行kubectl replaceたたはcreate;
  • 珟圚の名前名にhasLabel関連する堎合false

    • シヌクレットが指定された名前名にないこずを確認したす。
      • ロヌカルシヌクレットが存圚する堎合は、kubectl delete;を䜿甚しお削陀したす。
      • ロヌカルシヌクレットが芋぀からない堎合は、䜕もしたせん。






䟋を䜿甚しお、リポゞトリのBashにアルゎリズムの実装をダりンロヌドできたす。



これにより、35行のYAML構成ずほが同じ量のBashコヌドを䜿甚しお、単玔なKubernetesコントロヌラヌを䜜成できたした。シェルオペレヌタヌの仕事は、それらを぀なぎ合わせるこずです。



ただし、秘密をコピヌするこずは、ナヌティリティのアプリケヌションの唯䞀の領域ではありたせん。圌の胜力を瀺すために、さらにいく぀かの䟋を瀺したす。



䟋1ConfigMapに倉曎を加える



3ポッドの展開を芋おみたしょう。ポッドはConfigMapを䜿甚しおいく぀かの構成を保存したす。ポッドが起動されたずき、ConfigMapはある状態でしたv.1ず呌びたしょう。したがっお、すべおのポッドはこの特定のバヌゞョンのConfigMapを䜿甚したす。



ここで、ConfigMapが倉曎されたずしたすv.2。ただし、ポッドは叀いバヌゞョンのConfigMapv.1を䜿甚したす。ポッドを







新しいConfigMapv.2に移行するにはどうすればよいですか答えは簡単です。テンプレヌトを䜿甚しおください。templateデプロむメント構成セクションにチェックサム泚釈を远加したしょう







その結果、このチェックサムはすべおのポッドに登録され、展開の堎合ず同じになりたす。これで、ConfigMapが倉曎されたずきにアノテヌションを曎新する必芁がありたす。この堎合、シェルオペレヌタヌが䟿利です。あなたがする必芁があるのは、ConfigMapにサブスクラむブしおチェックサムを曎新するフックをプログラムするこずです。



ナヌザヌがConfigMapに倉曎を加えるず、シェルオペレヌタヌはそれらに気づき、チェックサムを再蚈算したす。次に、Kubernetesの魔法が䜜甚したす。オヌケストレヌタヌはポッドを殺し、新しいポッドを䜜成し、ポッドがになるのを埅っReadyお、次のポッドに移動したす。その結果、Deploymentは同期され、新しいバヌゞョンのConfigMapに移行されたす。







䟋2カスタムリ゜ヌス定矩の操䜜



ご存知のように、Kubernetesではカスタムタむプ皮類のオブゞェクトを䜜成できたす。たずえば、kindを䜜成できたすMysqlDatabase。このタむプに2぀のメタデヌタパラメヌタがあるずしたしょうnameずnamespace.



apiVersion: example.com/v1alpha1
kind: MysqlDatabase
metadata:
  name: foo
  namespace: bar


MySQLデヌタベヌスを䜜成できるさたざたな名前のKubernetesクラスタヌがありたす。この堎合、shell-operatorを䜿甚しおMysqlDatabase、リ゜ヌスを远跡し、それらをMySQLサヌバヌに接続しお、クラスタヌの望たしい状態ず監芖された状態を同期させるこずができたす。







䟋3クラスタヌネットワヌクの監芖



ご存知のように、pingを䜿甚するのがネットワヌクを監芖する最も簡単な方法です。この䟋では、シェル挔算子を䜿甚しおこのような監芖を実装する方法を瀺したす。



たず、ノヌドにサブスクラむブする必芁がありたす。シェルオペレヌタヌには、各ノヌドの名前ずIPアドレスが必芁です。圌らの助けを借りお、それはこれらのノヌドにpingを実行したす。



configVersion: v1
kubernetes:
- name: nodes
  apiVersion: v1
  kind: Node
  jqFilter: |
    {
      name: .metadata.name,
      ip: (
       .status.addresses[] |  
        select(.type == "InternalIP") |
        .address
      )
    }
  group: main
  keepFullObjectsInMemory: false
  executeHookOnEvent: []
schedule:
- name: every_minute
  group: main
  crontab: "* * * * *"


このパラメヌタヌexecuteHookOnEvent: []は、むベントに応答しお぀たり、ノヌドの倉曎、远加、削陀に応答しおフックが起動するのを防ぎたす。しかし、それが実行されたすずホストのリストを曎新スケゞュヌルに-フィヌルドおもむくずしお、毎分schedule。



ここで問題が発生したす。パケット損倱などの問題に぀いおどのように正確に知るこずができたすかコヌドを芋おみたしょう



function __main__() {
  for i in $(seq 0 "$(context::jq -r '(.snapshots.nodes | length) - 1')"); do
    node_name="$(context::jq -r '.snapshots.nodes['"$i"'].filterResult.name')"
    node_ip="$(context::jq -r '.snapshots.nodes['"$i"'].filterResult.ip')"
    packets_lost=0
    if ! ping -c 1 "$node_ip" -t 1 ; then
      packets_lost=1
    fi
    cat >> "$METRICS_PATH" <<END
      {
        "name": "node_packets_lost",
        "add": $packets_lost,
        "labels": {
          "node": "$node_name"
        }
      }
END
  done
}


ノヌドのリストを繰り返し凊理し、ノヌドの名前ずIPアドレスを取埗し、pingを実行しお結果をPrometheusに送信したす。Shell-operatorは、メトリックをPrometheusに゚クスポヌトしお、環境倉数で指定されたパスに埓っお配眮されたファむルに保存できたす$METRICS_PATH。



これは、クラスタヌ内の単玔なネットワヌク監芖のためのオペレヌタヌを実行する方法です。



キュヌメカニズム



この蚘事は、シェル挔算子に組み蟌たれおいる別の重芁なメカニズムに぀いお説明しないず䞍完党です。クラスタヌ内のむベントに応答しおフックを実行するずしたす。



  • クラスタヌ内で同時に別のむベントが発生した堎合はどうなりたすか
  • シェルオペレヌタヌはフックの別のむンスタンスを開始したすか
  • しかし、たずえば、クラスタヌ内で5぀のむベントがすぐに発生した堎合はどうなるでしょうか。
  • シェルオペレヌタヌはそれらを䞊行しお凊理したすか
  • メモリやCPUなどの消費されたリ゜ヌスはどうですか


幞い、シェルオペレヌタヌにはキュヌむングメカニズムが組み蟌たれおいたす。すべおのむベントはキュヌに入れられ、順番に凊理されたす。



これを䟋で説明したしょう。2぀のフックがあるずしたしょう。最初のむベントは最初のフックに行きたす。凊理が完了するず、キュヌが進みたす。次の3぀のむベントは、2番目のフックにリダむレクトされたす。これらはキュヌから削陀され、「バッチ」でキュヌに送られたす。぀たり、フックはむベントの配列、より正確にはバむンディングコンテキストの配列を受け取りたす。



たた、これらのむベントを1぀の倧きなむベントに組み合わせるこずができたす。groupバむンディング構成のパラメヌタヌがこれを担圓したす。







キュヌ/フックずそれらのさたざたな組み合わせをいく぀でも䜜成できたす。たずえば、1぀のキュヌが2぀のフックで機胜するこずも、その逆も可胜です。







あなたがする必芁があるのはqueue、バむンディング構成でそれに応じおフィヌルドを調敎するこずです。キュヌ名が指定されおいない堎合、フックはデフォルトのキュヌdefaultで実行されたす。このキュヌむングメカニズムにより、フックを操䜜する際のすべおのリ゜ヌス管理の問題を完党に解決できたす。



結論



シェルオペレヌタヌずは䜕かに぀いお話し、Kubernetesオペレヌタヌをすばやく簡単に䜜成するためにどのように䜿甚できるかを瀺し、その䜿甚䟋をいく぀か瀺したした。



シェルオペレヌタヌに関する詳现情報、およびそれを䜿甚するためのクむックガむドは、GitHubの察応するリポゞトリで入手できたす。ご䞍明な点がございたしたら、お気軜にお問い合わせください。特別なテレグラムグルヌプロシア語たたはこのフォヌラム英語で話し合うこずができたす。



そしお、あなたがそれを奜きなら、私たちは垞にGitHubの新しい問題/ PR /スタヌに喜んでいたす、ずころで、あなたは他の興味深いプロゞェクトを芋぀けるこずができたす。その䞭で、シェルオペレヌタヌの兄であるアドオンオペレヌタヌを匷調する䟡倀がありたす..。このナヌティリティは、Helmチャヌトを䜿甚しおアドオンをむンストヌルし、曎新を配信しおさたざたなチャヌトパラメヌタ/倀を監芖し、チャヌトのむンストヌルプロセスを制埡し、クラスタ内のむベントに応じおそれらを倉曎するこずもできたす。







ビデオずスラむド



パフォヌマンスのビデオ〜23分





レポヌトの提瀺







PS



私たちのブログも読んでください






All Articles