プラグインで kubectl を拡張する / Extend kubectl with plugins

プラグインで kubectl を拡張する / Extend kubectl with plugins

Kubernetes Meetup Tokyo #12 / https://k8sjp.connpass.com/event/90631/

---

このスライドで紹介しているプラグイン機構は、v1.12 で完全に削除され v1.12 から新たに導入された git-style のプラグイン機構に置き換わりました。詳しくは https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/ を参照してください。

9f9df80ab6551776b49c4ad9432ba1b7?s=128

Kazuki Suda

July 11, 2018
Tweet

Transcript

  1. Kubernetes Meetup Tokyo #12 2018/7/11 Kazuki Suda <ksuda@zlab.co.jp> @superbrothers プラグインで

    kubectl を拡張する
  2. None
  3. Kubernetes の拡張性

  4. Kubernetes の拡張性 ▶ ネットワークプラグイン + CNI (alpha) ▶ ストレージプラグイン +

    CSI (beta) ▶ デバイスプラグイン + NVIDIA GPU device plugin, etc ▶ コンテナランタイム + CRI, docker, containerd, cri-o, rktlet Infrastructure Controllers ▶ クラウドプロバイダ + cloud-controller-manager (beta) ▶ スケジューラ + カスタムスケジューラ ▶ Ingress (L7 LB) + Nginx, HAProxy, AWS, GCE, etc ▶ カスタムリソース + CustomResourceDefinitions + Extension API Servers ▶ Admission Control + ValidatingAdmissionWebhooks (beta) + MutatingAdmissionWebhooks (beta) + Initializers (alpha) ▶ 認証認可 + AuthN: TokenReview API + AuthZ: SubjectAccessReview API API
  5. Kubernetes の拡張性 ▶ kubectl + kubectl plugin (alpha) Command Line


    Interface
  6. kubectl plugin:
 プラグインで kubectl を拡張する

  7. kubectl plugin: Extend kubectl with plugins ▶ kubectl plugin 下に任意のコマンドを追加する拡張機能

    ▶ v1.7.0 で実装されたが、v1.8.0 またそれ以降での利⽤を推奨 ▶ $HOME/.kube/plugins 下に⼀つ以上の plugin.yaml とバイナリまたはスクリ プトを配置する + $KUBECTL_PLUGINS_PATH でパスを変更できる # Loads plugins from both /path/to/dir1 and /path/to/dir2 KUBECTL_PLUGINS_PATH=/path/to/dir1:/path/to/dir2 kubectl plugin -h
  8. name: "targaryen" # REQUIRED: the plugin command name, to be

    invoked under 'kubectl' shortDesc: "Dragonized plugin" # REQUIRED: the command short description, for help longDesc: "" # the command long description, for help example: "" # command example(s), for help command: "./dracarys" # REQUIRED: the command, binary, or script flags: # flags supported by the plugin - name: "heat" # REQUIRED for each flag: flag name shorthand: "h" # short version of the flag name desc: "Fire heat" # REQUIRED for each flag: flag description defValue: "extreme" # default value of the flag tree: # allows the declaration of subcommands - ... # subcommands support the same set of attributes plugin.yaml の記述
  9. $ kubectl plugin targaryen --help Dragonized plugin Options: --heat='extreme': Fire

    heat Usage: kubectl plugin targaryen [flags] [options] Use "kubectl options" for a list of global command-line options (applies to all commands).
  10. ▶ プラグイン名と同じ名前のサブディレクトリを作成する ▶ 依存するバイナリやスクリプトはサブディレクトリ下に配置する 推奨するディレクトリ構造 ~/.kube/plugins/ └── targaryen ├── plugin.yaml

    └── dracarys
  11. $ kubectl plugin flags | grep KUBECTL_ | sort KUBECTL_PLUGINS_CALLER=/usr/local/bin/kubectl

    KUBECTL_PLUGINS_CURRENT_NAMESPACE=default KUBECTL_PLUGINS_DESCRIPTOR_COMMAND=bash -c env KUBECTL_PLUGINS_DESCRIPTOR_EXAMPLE= KUBECTL_PLUGINS_DESCRIPTOR_LONG_DESC= KUBECTL_PLUGINS_DESCRIPTOR_NAME=flags KUBECTL_PLUGINS_DESCRIPTOR_SHORT_DESC=I echo all the flags that have been passed to my plugin as environment variables KUBECTL_PLUGINS_GLOBAL_FLAG_ALSOLOGTOSTDERR=false KUBECTL_PLUGINS_GLOBAL_FLAG_AS= KUBECTL_PLUGINS_GLOBAL_FLAG_AS_GROUP=[] KUBECTL_PLUGINS_GLOBAL_FLAG_CACHE_DIR=/Users/ksuda/.kube/http-cache KUBECTL_PLUGINS_GLOBAL_FLAG_CERTIFICATE_AUTHORITY= KUBECTL_PLUGINS_GLOBAL_FLAG_CLIENT_CERTIFICATE= KUBECTL_PLUGINS_GLOBAL_FLAG_CLIENT_KEY= KUBECTL_PLUGINS_GLOBAL_FLAG_CLUSTER= KUBECTL_PLUGINS_GLOBAL_FLAG_CONTEXT= KUBECTL_PLUGINS_GLOBAL_FLAG_INSECURE_SKIP_TLS_VERIFY=false KUBECTL_PLUGINS_GLOBAL_FLAG_KUBECONFIG= KUBECTL_PLUGINS_GLOBAL_FLAG_LOGTOSTDERR=true KUBECTL_PLUGINS_GLOBAL_FLAG_LOG_BACKTRACE_AT=:0 KUBECTL_PLUGINS_GLOBAL_FLAG_LOG_DIR= KUBECTL_PLUGINS_GLOBAL_FLAG_LOG_FLUSH_FREQUENCY=5s KUBECTL_PLUGINS_GLOBAL_FLAG_MATCH_SERVER_VERSION=false KUBECTL_PLUGINS_GLOBAL_FLAG_NAMESPACE= KUBECTL_PLUGINS_GLOBAL_FLAG_REQUEST_TIMEOUT=0 KUBECTL_PLUGINS_GLOBAL_FLAG_SERVER= KUBECTL_PLUGINS_GLOBAL_FLAG_STDERRTHRESHOLD=2 KUBECTL_PLUGINS_GLOBAL_FLAG_TOKEN= KUBECTL_PLUGINS_GLOBAL_FLAG_USER= KUBECTL_PLUGINS_GLOBAL_FLAG_V=0 KUBECTL_PLUGINS_GLOBAL_FLAG_VMODULE= KUBECTL_PLUGINS_LOCAL_FLAG_FOO= KUBECTL_PLUGINS_LOCAL_FLAG_HELP=false KUBECTL_PLUGINS_LOCAL_FLAG_OUTPUT= github.com/carolynvs/kubectl-flags-plugin
  12. k8s.io/kubectl/pkg/pluginutils // InitClientAndConfig uses the KUBECONFIG environment variable to create

    // a new rest client and config object based on the existing kubectl config // and options passed from the plugin framework via environment variables func InitClientAndConfig() (*restclient.Config, clientcmd.ClientConfig, error) { ...... configFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CONFIG") kubeConfigFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_KUBECONFIG") if len(configFile) > 0 { kubeconfig = configFile } else if len(kubeConfigFile) > 0 { kubeconfig = kubeConfigFile }
  13. import ( "k8s.io/client-go/kubernetes" "k8s.io/kubectl/pkg/pluginutils" ) func main() { ... restConfig,

    kubeConfig, err := pluginutils.InitClientAndConfig() if err != nil { log.Fatalf("Failed to init client and config: %v", err) } client := kubernetes.NewForConfigOrDie(restConfig) k8s.io/kubectl/pkg/pluginutils
  14. 予約済みのフラグ $ kubectl options The following options can be passed

    to any command: --alsologtostderr=false: log to standard error as well as files --as='': Username to impersonate for the operation --as-group=[]: Group to impersonate for the operation, this flag can be repeated to specify m --cache-dir='/Users/ksuda/.kube/http-cache': Default HTTP cache directory --certificate-authority='': Path to a cert file for the certificate authority --client-certificate='': Path to a client certificate file for TLS --client-key='': Path to a client key file for TLS --cluster='': The name of the kubeconfig cluster to use --context='': The name of the kubeconfig context to use --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for v --kubeconfig='': Path to the kubeconfig file to use for CLI requests. --log-backtrace-at=:0: when logging hits line file:N, emit a stack trace --log-dir='': If non-empty, write log files in this directory --log-flush-frequency=5s: Maximum number of seconds between log flushes --logtostderr=true: log to standard error instead of files --match-server-version=false: Require server version to match client version -n, --namespace='': If present, the namespace scope for this CLI request
  15. デモ: github.com/superbrothers/kubectl- view-kubeconfig-plugin

  16. $ kubectl plugin view-kubeconfig -h Show a kubeconfig setting to

    access the apiserver with a specified serviceaccount. Examples: # Show a kubeconfig setting of serviceaccount/default kubectl plugin view-kubeconfig default Usage: kubectl plugin view-kubeconfig [flags] [options] Use "kubectl options" for a list of global command-line options (applies to all commands). $ cat ~/.kube/view-kubeconfig/plugin.yaml name: "view-kubeconfig" shortDesc: "Show a kubeconfig setting to access the apiserver with a specified serviceaccount." example: "# Show a kubeconfig setting of serviceaccount/default\nkubectl plugin view-kubeconfig def command: "./view-kubeconfig"
  17. import ( "flag" "fmt" "log" "os" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" clientcmd

    "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/kubectl/pkg/pluginutils" // Initialize all known client auth plugins. _ "k8s.io/client-go/plugin/pkg/client/auth" ) func init() { // Initialize glog flags flag.CommandLine.Set("logtostderr", "true") flag.CommandLine.Set("v", os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_V")) }
  18. func main() { if len(os.Args) < 2 { log.Fatalf("Usage: kubectl

    plugin view-kubeconfig SERVICEACCOUNT") } serviceaccountName := os.Args[1] restConfig, kubeConfig, err := pluginutils.InitClientAndConfig() if err != nil { log.Fatalf("Failed to init client and config: %v", err) } client := kubernetes.NewForConfigOrDie(restConfig) namespace, _, _ := kubeConfig.Namespace()
  19. serviceaccount, err := client.CoreV1().ServiceAccounts(namespace).Get(serviceaccountName, metav1.GetOptions{}) if err != nil {

    log.Fatalf("Failed to get a serviceaccount: %v", err) } if len(serviceaccount.Secrets) < 1 { log.Fatalf("serviceaccount %s has no secrets", serviceaccount.GetName()) } secret, err := client.CoreV1().Secrets(namespace).Get(serviceaccount.Secrets[0].Name, metav1.GetOptions{}) if err != nil { log.Fatalf("Failed to get a secret: %v", err) } caCrt, ok := secret.Data["ca.crt"] if !ok { log.Fatalf("key 'ca.crt' not found in %s", secret.GetName()) } token, ok := secret.Data["token"] if !ok { log.Fatalf("key 'token' not found in %s", secret.GetName()) }
  20. デモ: github.com/superbrothers/kubectl- service-plugin

  21. $ kubectl plugin service -h Open the Kubernetes URL(s) for

    the specified service in your browser through a local proxy server using kubectl proxy. Examples: # Open service/kubernetes-dashboard in kube-system namespace. kubectl plugin service kubernetes-dashboard -n kube-system Usage: kubectl plugin service [flags] [options] Use "kubectl options" for a list of global command-line options (applies to all commands).]
  22. kubectl plugin の現在と将来

  23. kubectl plugin の現在と将来 ▶ Alpha Stability ⚠ (v1.11): 今後下位互換性のない⼤きな変更が⼊る ▶

    現在 kubectl plugin 下にコマンドが追加されるが、将来 kubectl 下になるかも
  24. より詳しく知るには

  25. より詳しく知るには ▶ https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/ ▶ Install the Service Catalog CLI as

    kubectl plugin + https://github.com/kubernetes-incubator/service-catalog $ svcat install plugin Plugin has been installed to ~/.kube/plugins/svcat. Run kubectl plugin svcat --help for help using the plugin.
  26. We’re Hiring! https://zlab.co.jp/ Kubernetes, Docker, Prometheus, Golang, CoreOS