デフォルトでは、ジョブの実行はAWXをデプロイしているKubernetesクラスタ上でpodがデプロイされて行われる。設定によって、podをデプロイするクラスタを、異なるクラスタ(AWXをデプロイしていないクラスタ)へ変更することができる。
本記事内では便宜上、AWXをデプロイしているクラスタを「ローカルクラスタ」、ジョブ実行のpodをデプロイするクラスタを「リモートクラスタ」と称する。(この記事内のローカルルール)
- 2022.08.25: エラーパターンを追記
リモートクラスタ設定
ローカルクラスタからの接続に必要なリソースを作成する。
以下も参照。
- Ansibleのk8sモジュールでKubernetesクラスタ上のリソースを操作する - zaki work log
- Kubernetes v1.24でServiceAccountのトークンを生成・取得する - zaki work log
アクセス用ServiceAccountの作成
ローカルクラスタからリモートクラスタへの接続用のServiceAccountを作成する。
AWXからはこのServiceAccountのトークンを使って認証してpodをデプロイする、という動作。
ServiceAccountに対するロールの設定は暫定(不要なものもついてる)ので、運用のときは必要最小限の権限にすることを検討すること。
NamespaceとServiceAccountの作成は以下の通り。
このNamespaceはジョブのpodをデプロイする場所になる。
[zaki@k8s-master ~]$ kubectl create namespace awx-exec namespace/awx-exec created [zaki@k8s-master ~]$ kubectl create serviceaccount awx-user -n awx-exec serviceaccount/awx-user created
Roleの作成と、ServiceAccountへのRoleBinding作成は以下。(ロールの割り当て)
[zaki@k8s-master ~]$ kubectl create role awx-role -n awx-exec --verb=* --resource=* role.rbac.authorization.k8s.io/awx-role created [zaki@k8s-master ~]$ kubectl create rolebinding awx-rolebind -n awx-exec --role=awx-role --serviceaccount=awx-exec:awx-user rolebinding.rbac.authorization.k8s.io/awx-rolebind created
CLIでやるとこのとおりだけど、マニフェストなら以下の通り。
--- apiVersion: v1 kind: Namespace metadata: name: awx-exec --- apiVersion: v1 kind: ServiceAccount metadata: name: awx-user namespace: awx-exec --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: awx-role namespace: awx-exec rules: - apiGroups: - "" resources: - '*' verbs: - '*' --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: awx-rolebind namespace: awx-exec roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: awx-role subjects: - kind: ServiceAccount name: awx-user namespace: awx-exec
アクセストークンの取得
Kubernetes v1.24以降は以下のコマンドで。
出力は1行になっていて、この内容をAWXに登録する。
[zaki@k8s-master ~]$ kubectl create token awx-user -n awx-exec eyJhbGciOiJ ......
v1.23以前のSecretリソース内のトークンを使う場合は、以下の「APIトークン指定」の項を参照。
AWXの設定
AWXでリモートクラスタでジョブを実行するための設定。
認証情報の作成
リモートクラスタへの接続情報は、「認証情報」で設定を作成する。
名前は適当に入力し、「認証情報タイプ」は「OpenShift または Kubernetes API Bearer トークン」を選択する。
追加の入力項目に、APIサーバーのアドレス、作成したServiceAccountのトークン、クラスタの証明書を入力する。
エンドポイントはAPIサーバーのアドレスを入力。kubectl
コマンドが使えるならkubectl cluster-info
でも確認できる。
[zaki@k8s-master ~]$ kubectl cluster-info Kubernetes control plane is running at https://k8s.example.org:6443 # <- これ CoreDNS is running at https://k8s.example.org:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
証明書は、kubeconfigファイル(デフォルトで$HOME/.kube/config
)からcluster
以下にあるcertificate-authority-data
の内容をbase64デコードするか、クラスタ上の各Namespaceにあるkube-root-ca.crt
ConfigMapから抜き出す。
ConfigMapから取得する場合は以下のコマンドを使えば簡単に取り出せる。(-o yaml
の結果の場合は行頭にスペースがあるので削る。スペースがあるとエラーになる)
[zaki@k8s-master ~]$ kubectl get cm kube-root-ca.crt -o jsonpath='{.data.ca\.crt}' -----BEGIN CERTIFICATE----- [snip] -----END CERTIFICATE-----
もしエンドポイントがIPアドレス形式だったり証明書の検証ができない場合は、下部の「SSLの検証」のチェックを外す。(その際証明書データは不要…と思う)
インスタンスグループの追加
ここから実行ノードの追加の設定。
メニューの「インスタンスグループ」で「追加」押下。
AAPの場合は「コンテナ―グループの追加」と「インスタンスグループの追加」の2択になるので、コンテナ―グループを選択。
新規コンテナグループの作成画面になるので、適当な名称を入力し、「Pod 仕様のカスタマイズ」をチェックする
Pod仕様のカスタマイズフィールドが表示されるので、以下を修正する。
- metadata.namespace: デプロイするNamespace名。前述の例の場合
awx-exec
- spec.serviceAccountName: トークン取得に使用したServiceAccount名。前述の例の場合
awx-user
これでリモートクラスタ自体の設定と、リモートクラスタへの接続情報の設定が完了。
ジョブの設定
ここから、リモートクラスタで実行したいジョブに、クラスタの指定を行う。
といってもジョブテンプレートの「インスタンスグループ」に追加設定するだけ。
🔍アイコンを押下し、先ほど作ったインスタンスグループを選択して、ジョブテンプレートを保存すればOK
実行
準備ができたらジョブテンプレートを普通に実行。
このとき、リモートクラスタの方で-w (watch)
を付加してpodの状態を見ておくと、ジョブのpodがデプロイ・実行される状況を確認できる。
初回はイメージのダウンロードが必要なので時間がかかるが、2度目からすぐ実行(Running状態)になる。
[zaki@k8s-master ~]$ kubectl get pod -n awx-exec -w NAME READY STATUS RESTARTS AGE automation-job-3-rgjqz 0/1 Pending 0 0s automation-job-3-rgjqz 0/1 Pending 0 0s automation-job-3-rgjqz 0/1 ContainerCreating 0 0s automation-job-3-rgjqz 0/1 ContainerCreating 0 0s automation-job-3-rgjqz 1/1 Running 0 2m31s automation-job-3-rgjqz 1/1 Terminating 0 2m39s ...
AWXのUIでもこの通りジョブの実行を確認できる。
エラーのパターン
設定不備などで発生するエラーの内容メモ。
トークンが不正
トークンの期限が切れていたり、誤っていると発生。
Error creating pod: Unauthorized
NamespaceやServiceAccountが存在しない
インスタンスグループの「Pod仕様のカスタマイズ」で入力したNamespaceやServiceAccountが存在しない場合は、トークン不正と同じUnauthorizedエラーが出力された。
Error creating pod: Unauthorized
証明書が不正
誤った証明書やSSL検証ができない場合に発生。
「SSLの検証」をオフにすれば回避できる
Error creating pod: Post "https://k8s.example.org:6443/api/v1/namespaces/awx-exec/pods": x509: certificate signed by unknown authority
ServiceAccountに権限が足りない
bindしたroleに、podをデプロイする権限がないと発生。
Error creating pod: pods is forbidden: User "system:serviceaccount:awx-exec:awx-user" cannot create resource "pods" in API group "" in the namespace "awx-exec"
実行環境のイメージの取得に失敗
実行環境として指定したイメージがリポジトリ上に無い場合や、認証が必要なリポジトリなのにその認証に失敗した場合などで発生。
Error creating pod: container failed to start, ImagePullBackOff
ImagePullBackOffの詳細は、Kubernetesクラスタ側で kubectl get event
を実行して詳細を確認できる。
例えばイメージのpullに認証が必要なのに認証できていない場合は以下。
7m47s Warning Failed pod/automation-job-28-jz6mk Failed to pull image "zakihmkc/priv-httpd:latest": rpc error: code = Unknown desc = failed to pull and unpack image "docker.io/zakihmkc/priv-httpd:latest": failed to resolve reference "docker.io/zakihmkc/priv-httpd:latest": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
環境
- AWX: 21.3.0
- on Kubernetes 1.24.3 (k3sで構築)
- AAP: 2.1.1 (Automation Controller 4.1.1)
- on RHEL8.6
- リモートクラスタ: Kubernetes 1.24.3 (kubeadmで構築)