本エントリは、Ansible Advent Calendar 2023の14日目の記事です。煽られて(?)即席で書き上げました。
昨年共著で出版させていただいたAnsibleクックブックでは紙面の都合 * で掲載しなかった、kubernetesコネクションプラグインについて簡単に使い方の例を簡単に紹介します。
( * 本の趣旨が主に「『プレイブック』の紹介」だったため笑)
kubernetesコネクションプラグイン
まず「コネクションプラグイン」とは、Ansibleがマネージドノード(自動化対象のノード)へ接続する際のプロトコルなどの接続メソッドを指します。デフォルトはsshで、「AnsibleはSSHとPythonがあれば使える」のSSHの部分がこれに当たります。
Ansibleクックブックのコンテナの章「5-1-4 コネクションプラグイン」では「Dockerコネクションプラグイン」については簡単に解説しており、これは実行中のコンテナに対してSSHを使わずに docker exec
のようにコンテナ内のコマンドを直接実行する機能を使ってAnsibleを自動化処理を送り込むことができます。(コンテナ内にPythonインタプリタは必要)
kubernetesコネクションプラグインは、KubernetesのPodに対する接続を行うためのプラグインで、Pod(の中のコンテナ)に対してSSH接続を行わずにkubectl exec
のようにコマンドを直接実行する機能を使ってAnsibleの自動化処理を行います。(これもDockerのケース同様、コンテナ内にPythonインタプリタは必要)
なお、実行にはkubectl
コマンドが実行ノードに必要です。
基本
インベントリファイルで、ansible_connection
にコネクションプラグインの指定と、ansible_kubectl_kubeconfig
変数でKubernetesクラスタ接続用のKUBECONFIGファイルの指定を行います。
また、マネージドノードにはPod名を指定します。ネームスペースやコンテナ名(1Podに複数コンテナ構成の場合)も同様に指定します。
(以下はグループ変数でなくホスト変数としてネームスペース指定)
[pods] awx-demo-web-f88868474-7qxsl ansible_kubectl_namespace=awx ansible_kubectl_container=awx-demo-web [all:vars] ansible_connection=kubectl ansible_kubectl_kubeconfig=/home/zaki/local/src/ansible-sample/k8s-module/connection/k3s.yaml
インベントリは上記の通りで、例として以下のPlaybookを使ってコンテナ内のファイル一覧を取得してみます。
--- - hosts: all gather_facts: false tasks: - name: get filelist command: ls /var/lib/awx
実行結果は以下の通り、SSH接続せずにコンテナのファイル一覧を取得できました。
$ ansible-playbook -i inventory.ini command.yml -v Using /home/zaki/local/src/ansible-sample/k8s-module/connection/ansible.cfg as config file PLAY [all] ********************************************************************************************************** TASK [get filelist] ************************************************************************************************* changed: [awx-demo-web-f88868474-7qxsl] => changed=true ansible_facts: discovered_interpreter_python: /usr/bin/python3 cmd: - ls - /var/lib/awx delta: '0:00:00.002655' end: '2023-12-13 13:51:03.222642' msg: '' rc: 0 start: '2023-12-13 13:51:03.219987' stderr: '' stderr_lines: <omitted> stdout: |- awxfifo public rsyslog venv stdout_lines: <omitted> PLAY RECAP ********************************************************************************************************** awx-demo-web-f88868474-7qxsl : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
実際にkubectl exec
で確認した結果は以下の通り。
zaki@k3s-node1:~$ kubectl exec -it -n awx awx-demo-web-f88868474-7qxsl -c awx-demo-web -- bash bash-5.1$ ls /var/lib/awx/ awxfifo public rsyslog venv bash-5.1$
Pod名の指定 (12/14追記)
前述のインベントリファイルではマネージドノードのホスト名としてPod名を指定しましたが、ansible_kubectl_pod
変数を使っても指定できます。
こんな感じ
[pods] awx-web ansible_kubectl_pod=awx-demo-web-f88868474-7qxsl ansible_kubectl_container=awx-demo-web ansible_kubectl_namespace=awx
コンテキストの指定
よくあるパターンとして~/.kube/config
には複数クラスタの情報がストアされており、デフォルトにセットされているクラスタでなく特定のクラスタを指定したい場合…というよりCLIで使ってる状態に依存させたくない場合は、ansible_kubectl_context
でコンテキストを指定します。
[pods] awx-demo-web-f88868474-7qxsl ansible_kubectl_namespace=awx ansible_kubectl_container=awx-demo-web [all:vars] ansible_connection=kubectl ansible_kubectl_context=local-k3s ansible_kubectl_kubeconfig=/home/zaki/.kube/config
クラスタ名と現在のクラスタはkubectl config get-contexts
で確認可能です。
k8sインベントリプラグイン (コネクションプラグインとの組み合わせは動作未確認)
kubernetesコネクションプラグインを使った接続は、インベントリでPod名を固定で指定する必要があります。Deploymentなどから…というかStatefulSet以外から生成されるPodは名称がランダムになるため、インベントリファイルにスタティックに記述するには都合が悪い場合があります。
そういうときはダイナミックインベントリを使ってPod名を動的に取得できる……と思ってたんだけど、試してみると「Pod名のみ」でなく「Pod名コンテナ名」として取得してしまうため、kubernetesコネクションプラグインとのコンボは現状難しそう。。
接続のためのPod名は、hostvarsに ansible_kubectl_pod
としてセットされるので、「Pod名コンテナ名」を接続情報として利用できそう。コネクションプラグインの指定も含まれます。(12/14追記、動作未確認)
あー、未解決部分ちょっとわかった。
— zaki (@zaki_hmkc) December 14, 2023
kubernetesのインベントリプラグイン、hostとしてPod名が欲しかったところが「Pod名_コンテナ名」になってるけど、hostvarsの方にansible_kubectl_pod, ansible_kubectl_containerとかセットされてるから、そのまま使えましたわ
一応使い方を書いておくと、、、
基本
--- plugin: kubernetes.core.k8s connections: - kubeconfig: /home/zaki/local/src/ansible-sample/k8s-module/connection/work/kubeconfig.yaml context: default namespaces: - awx
このインベントリファイルを使ってansible-inventory --graph
を実行すると、「pod名_コンテナ名」の書式でnamespaceだけでなく、ラベルを使った様々なグループでKubernetesクラスタ上のPodとServiceの情報を得ることができます。
実行結果を抜粋するとこの通り。
$ ansible-inventory -i inventory.yaml --graph [WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details @all: |--@ungrouped: [...] |--@label_app.kubernetes.io/part-of_awx-demo: | |--awx-demo-postgres-13-0_postgres | |--awx-demo-task-585bb4c956-kb59d_awx-demo-ee | |--awx-demo-task-585bb4c956-kb59d_awx-demo-rsyslog | |--awx-demo-task-585bb4c956-kb59d_awx-demo-task | |--awx-demo-task-585bb4c956-kb59d_redis | |--awx-demo-web-f88868474-7qxsl_awx-demo-rsyslog | |--awx-demo-web-f88868474-7qxsl_awx-demo-web | |--awx-demo-web-f88868474-7qxsl_redis | |--awx-demo-postgres-13 | |--awx-demo-service [...] |--@label_app.kubernetes.io/name_awx-demo-web: | |--awx-demo-web-f88868474-7qxsl_awx-demo-rsyslog | |--awx-demo-web-f88868474-7qxsl_awx-demo-web | |--awx-demo-web-f88868474-7qxsl_redis [...]
ちなみにkubectl get pod -n awx --show-labels
を実行すると以下の通り。
awx-demo-web-f88868474-7qxsl
を得るにはapp.kubernetes.io/name=awx-demo-web
を目印に取得することができる。
$ kubectl get pod -n awx --show-labels NAME READY STATUS RESTARTS AGE LABELS awx-operator-controller-manager-6c55dc66bd-kjnln 2/2 Running 0 79m control-plane=controller-manager,pod-template-hash=6c55dc66bd awx-demo-postgres-13-0 1/1 Running 0 78m app.kubernetes.io/component=database,app.kubernetes.io/instance=postgres-13-awx-demo,app.kubernetes.io/managed-by=awx-operator,app.kubernetes.io/name=postgres-13,app.kubernetes.io/part-of=awx-demo,controller-revision-hash=awx-demo-postgres-13-85958bcbcd,statefulset.kubernetes.io/pod-name=awx-demo-postgres-13-0 awx-demo-task-585bb4c956-kb59d 4/4 Running 0 77m app.kubernetes.io/component=awx,app.kubernetes.io/managed-by=awx-operator,app.kubernetes.io/name=awx-demo-task,app.kubernetes.io/operator-version=2.7.2,app.kubernetes.io/part-of=awx-demo,app.kubernetes.io/version=23.4.0,pod-template-hash=585bb4c956 awx-demo-web-f88868474-7qxsl 3/3 Running 0 76m app.kubernetes.io/component=awx,app.kubernetes.io/managed-by=awx-operator,app.kubernetes.io/name=awx-demo-web,app.kubernetes.io/operator-version=2.7.2,app.kubernetes.io/part-of=awx-demo,app.kubernetes.io/version=23.4.0,pod-template-hash=f88868474
なお、実行にはkubernetes
Pythonパッケージが必要。(pip install kubernetes
でインストールする)
使いどころ
Kubernetesの基本としては、Podをデプロイしてその中身を後から変更する、というのはあまりよい使い方ではないですが、Podとしてデプロイしたアプリケーションに対するAPI操作をAnsibleで行うような場合に、ServiceやIngressを使って外部向けにHTTPS公開している経路ではなく、KubernetesのAPIサーバー経由でPod内のシェルを使って内部からHTTPアクセスする、という使い方ができます。
具体的には、AWXのようなwebアプリケーションをマネージドKubernetesで動かしている場合に、クラウドサービスのアプリケーションゲートウェイ経由のアクセスでなく、kubectl
を実行しているホストからawxモジュールを使ったAWX上のリソース作成を自動化したりできます。
Kubernetesのカレンダーとクロスポストできないかチェックしてみたけど、今日は空いてなかった…残念(笑)