zaki work log

作業ログやら生活ログやらなんやら

[Kustomize / secretGenerator] 初期パスワードを指定したAWXのインストールとSecret作成基礎

本記事は「Ansible Advent Calendar 2022」の8日目のエントリとなります。

AAP(旧Ansible Tower)のadminの初期パスワードはインストール時に使用するインベントリファイルで指定できるので簡単ですが、AWXのadminの初期パスワードはデフォルトではランダムな文字列がK8sクラスタ上のSecretリソースに出力され、その内容をbase64デコードして確認する必要があり、慣れないとアクセスがちょっと面倒。
そこで本記事では、AWXの初期パスワードをランダムなものでなくユーザーが指定したもので構築する方法についてと、KubernetesのSecretリソースの基礎的な作成方法について紹介します。

なお、デフォルトの動作のSecret情報は、デプロイするAWXリソース名(GitHubのドキュメント通りに作業するとawx-demoになってるkind: AWXのリソースの名前)がprefixに付与されており、以下のコマンドで取り出せます。

$ kubectl get secret -n <namespace> <AWX resource name>-admin-password -o jsonpath='{.data.password}' | base64 -d

jsonpathについてはこちらも参照

zaki-hmkc.hatenablog.com

パスワードの指定方法

AWX構築のリソースのパラメタにはadmin_password_secretがあります。
ここに「初期パスワードが記されたSecretリソースのリソース名」を指定することで、デフォルトの「AWX構築時にランダムなパスワードが設定されその内容が<awx resource name>-admin-passwordに出力される」という動作でなく、「admin_password_secretパラメタで指定したSecretリソース内の文字列を初期パスワードとしてAWXが構築される」という動作になります。

つまり事前にパスワードを設定したSecretリソースを作成しておき、そのSecretリソースの名前をadmin_password_secretにセットしてデプロイすればOK、ということ。

AWXリソースを作成するマニフェスト例として以下を想定。

apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: awx-demo
spec:
  service_type: nodeport
  ingress_type: ingress
  hostname: awx-demo.example.org

  admin_password_secret: my-awx-password   ## ☆ここで指定している「my-awx-password」という名前のSecretリソースで初期パスワードを設定する

パスワード情報を持つSecretリソースの作成

awx-operatorのインストール、初期のころはmakeコマンドを使用する形式でした(現在も使用可能)。この時は(たぶん)Secretリソースを別途作成してその名前をデプロイの際のAWXリソースのパラメタに指定する必要があり、割と面倒でした。
ですがawx-operatorバージョン0.20.0からKustomizeを使ったデプロイ方式になり、KustomizeのsecretGenerator機能で簡単にSecretリソースを作成できるので、任意の初期パスワードを設定した状態でAWXを簡単にデプロイできるようになっています。

kubectl.docs.kubernetes.io

kubectl.docs.kubernetes.io

ちなみにAWXのパスワードとして必要なSecretリソースの中身は、以下のようにpasswordというキーにパスワード文字列を指定する形式。

password: <初期パスワードに設定したい文字列>

secretGeneratorでSecretリソース作成

KustomizeのsecretGeneratorを使ってこれを作成するには、kustomization.yamlに以下を追記します。
これは初期パスワードを「curry_tabetai」にしたい場合。

secretGenerator:
- name: my-awx-password
  literals:
  - password=curry_tabetai
  options:
    disableNameSuffixHash: true

kustomization.yamlファイル内にインラインでキー=バリュー形式の設定値(要は辞書データ)を定義するにはliteralsフィールドを使用し、そこにnameフィールドで指定する名前のSecretリソースに埋め込む値をリストで記述します。(1つのSecretリソースに複数のキー=バリューの値を埋めるためにリスト形式を使用する)
また、KustomizeはSecretとConfigMapのデフォルトの動作として、ランダムなsuffixを付与して「変更時に参照しているPodも再作成させる」という動作になります。ただ今回はその動作は不要で、というよりは固定のSecretリソース名が必要なため、この動作を抑制します。そのための追加の記述がoptionsフィールドとそこで指定しているdisableNameSuffixHash: trueになります。このオプションはConfigMapの作成と共通で、以下の記事も参照。

zaki-hmkc.hatenablog.com

kustomization.yamlファイルにこの内容の記述を含めてawx-operatorをデプロイ(というかKustomizeを実行)すると以下の内容のSecretリソースが作成されます。

$ kubectl get secret -n awx
NAME              TYPE     DATA   AGE
my-awx-password   Opaque   1      19s
$ kubectl get secret -n awx my-awx-password -o yaml 
apiVersion: v1
data:
  password: Y3VycnlfdGFiZXRhaQ==
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"Y3VycnlfdGFiZXRhaQ=="},"kind":"Secret","metadata":{"annotations":{},"name":"my-awx-password","namespace":"awx"},"type":"Opaque"}
  creationTimestamp: "2022-12-05T10:43:01Z"
  name: my-awx-password
  namespace: awx
  resourceVersion: "747"
  uid: 5db1ea7e-670d-4a19-bad5-b3b49204e68e
type: Opaque

base64エンコードも自動。(デコードして内容を確認できる)

$ kubectl get secret -n awx my-awx-password -o jsonpath='{.data.password}' | base64 -d
curry_tabetai

これでAWXにブラウザでアクセスし、ユーザー名はデフォルトのadmin、パスワードはcurry_tabetaiを入力すればログインできます。
RESTの実行も以下の通り。

認証情報不足

$ curl --resolve awx-demo.example.org:80:127.0.0.1 http://awx-demo.example.org/api/v2/me/
{"detail":"Authentication credentials were not provided. To establish a login session, visit /api/login/."}

認証(basic)有り

$ curl --resolve awx-demo.example.org:80:127.0.0.1 http://awx-demo.example.org/api/v2/me/ -u admin:curry_tabetai
{"count":1,"next":null,"previous":null,"results":[{"id":1,"type":"user","url":"/api/v2/users/1/","related":{"teams":"/api/v2/users/1/teams/","organizations":"/api/v2/users/1/organizations/","admin_of_organizations":"/api/v2/users/1/admin_of_organizations/","projects":"/api/v2/users/1/projects/","credentials":"/api/v2/users/1/credentials/","roles":"/api/v2/users/1/roles/","activity_stream":"/api/v2/users/1/activity_stream/","access_list":"/api/v2/users/1/access_list/","tokens":"/api/v2/users/1/tokens/","authorized_tokens":"/api/v2/users/1/authorized_tokens/","personal_tokens":"/api/v2/users/1/personal_tokens/"},"summary_fields":{"user_capabilities":{"edit":true,"delete":false}},"created":"2022-12-05T10:49:48.749434Z","modified":"2022-12-05T13:50:30.930557Z","username":"admin","first_name":"","last_name":"","email":"test@example.com","is_superuser":true,"is_system_auditor":false,"ldap_dn":"","last_login":"2022-12-05T13:50:30.930557Z","external_account":null,"auth":[]}]}

ということで、作成するkustomization.yamlとAWXカスタムリソースのマニフェストに少し定義を追加するだけで簡単に初期パスワードを設定できるようになります。
プロジェクトなどで共通パスワードを設定したい場合はこれを使うと構築と初期設定が楽になります。

例で使用した全体のkustomization.yamlファイルの内容は以下のとおり。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - github.com/ansible/awx-operator/config/default?ref=1.1.1
  - awx-demo.yml

# Set the image tags to match the git version from above
images:
  - name: quay.io/ansible/awx-operator
    newTag: 1.1.1

# Specify a custom namespace in which to install AWX
namespace: awx

secretGenerator:
- name: my-awx-password
  literals:
  - password=curry_tabetai
  options:
    disableNameSuffixHash: true

Appendix

kubectl / secretGeneratorでSecretの作成いろいろ

Secretを作成する場合の自分用メモ。
ConfigMap作成とほぼ同じで、ConfigMapの場合はだいぶ前だけど以下でまとめてる。
Podからの参照方法についてもあわせて参照。

zaki-hmkc.hatenablog.com

リテラル(インライン記述)

前述のsecretGeneratorliteralsを使ったSecret作成は、kubectlだと以下と同等。

$ kubectl create secret generic my-awx-password --from-literal password=curry_tabetai

対象Secretに複数の値(キー=バリュー形式)をセットするには、--from=literalを値の分だけ繰り返す。

キー=バリュー形式の外部ファイルから

kustomization.yamlファイル内にSecretリソースの内容をベタ書きしたくない・CLIコマンドライン引数に直接指定したくないなどの場合に、以下の内容のpassword.iniファイルを用意しておいて、

password=curry_tabetai

kubectlコマンドで前述の例と同じ内容のSecretリソースを作成するには、以下を実行。

$ kubectl create secret generic my-awx-password --from-env-file password.ini 

これに相当する外部ファイルをソースにSecretリソースを作成するkustomization.yamlファイルの内容は以下の通り。

- name: my-awx-password
  envs:
  - password.ini

似ている機能にenvではなくfilesがあるが、filesは「ファイル名=ファイルの内容」のSecretリソースを作成する(後述)

外部ファイルを丸ごと埋め込む

Podでマウントしてファイルそのものを参照したい場合などは、kubectl create secret genericコマンドで--from-fileオプションを使用する。
これで「ファイル名=ファイルの内容」のSecretが作成される。

$ kubectl create secret generic sample-secret --from-file password.ini 

secretGeneratorで同じことを行うにはfilesを使用する。

- name: sample-secret
  files:
  - password.ini

コンテナレジストリ認証情報

認証が必要なレジストリのクレデンシャル情報を作成するときに使うkubectlコマンドは以下のような感じ。

$ kubectl create secret docker-registry regcred --from-file=.dockerconfigjson=$HOME/.docker/config.json 

kubernetes.io

これに相当するsecretGeneratorはレジストリ認証情報専用の機能はないが、前述のfilesと追加でtypeの指定で作成可能。

- name: regcred
  files:
  - .dockerconfigjson=path/to/.docker/config.json
  type: kubernetes.io/dockerconfigjson

注意点として、kustomization.yamlで指定できる外部ファイルは、kustomization.yamlファイルのあるディレクトリとそのサブディレクトリのみ。(上位のディレクトリは参照できない)

その他証明書ファイルSecretの作成(kubectl create secret tls ...)についてもsecretGeneratorに専用機能はないが、secretGeneratorのリファレンスに記述例があるので、ドキュメントみれば特に問題ないはず。

デプロイ時のkustomizeコマンドは不要 (2022.12.06時点)

awx-operatorのドキュメントにはkustomizeをインストールする手順になっていますが、実はAWXのデプロイの内容であれば現状kubectl内蔵のKustomizeで事足りるので、以下のようにkubectl apply -kコマンドでデプロイできます。

$ kubectl apply -k .
namespace/awx created
customresourcedefinition.apiextensions.k8s.io/awxbackups.awx.ansible.com created
customresourcedefinition.apiextensions.k8s.io/awxrestores.awx.ansible.com created
customresourcedefinition.apiextensions.k8s.io/awxs.awx.ansible.com created
serviceaccount/awx-operator-controller-manager created
role.rbac.authorization.k8s.io/awx-operator-awx-manager-role created
role.rbac.authorization.k8s.io/awx-operator-leader-election-role created
clusterrole.rbac.authorization.k8s.io/awx-operator-metrics-reader created
clusterrole.rbac.authorization.k8s.io/awx-operator-proxy-role created
rolebinding.rbac.authorization.k8s.io/awx-operator-awx-manager-rolebinding created
rolebinding.rbac.authorization.k8s.io/awx-operator-leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/awx-operator-proxy-rolebinding created
configmap/awx-operator-awx-manager-config created
secret/my-awx-password created
service/awx-operator-controller-manager-metrics-service created
deployment.apps/awx-operator-controller-manager created
awx.awx.ansible.com/awx-demo created

kubectl apply -kkustomizeコマンドについても下記参照。

zaki-hmkc.hatenablog.com

環境

確認したバージョンは以下の通り

$ kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.25.4
Kustomize Version: v4.5.7
Server Version: v1.24.3+k3s1
  • AWX: 21.10.0
  • awx-operator: 1.1.1