Docker ぐらいならなんとかわかるけど、 Kubernetes (k8s) は全然わかっていない人向けに、プロキシ環境下の MicroK8s 上で AWX をインストールする手順と、その周囲情報を説明していく。
AWX とは
AWX とは、 Ansible Automation Controller (旧称: Ansible Tower) と呼ばれる Ansible の構成コードの実行を管理する WebUI を持ったツールの OSS版だ。
Ansible とは IaC (Infrastracture as Code) ができる CUI ツールであり、構成先に Python さえ入っていれば、そこに ssh するだけで実行できるのが特徴だ。
AWX はこれを Git などのソースコード管理ツールと連携しながら、 Web UI 上で実行・管理・記録できるツールとなる。
Ansible Automation Controller と比べると、 Red Hat によるサポートや LTS はなく、 ローリングリリースモデルを採用していて更新が激しい。
このため、エンタープライズ用途には基本的には向かないものの、元々そんなに破壊的変更が頻繁にあるタイプのツールではないため、小規模に使う程度ならかなり実用的になっている。
(但し 2024年9月現在、次回のメジャー更新の v25 あたりで、認可・認証の内部構成が大きく変わる予定ではある 1)
Kubernetes と MicroK8s
AWX を運用環境にインストールするには、 Kubernetes が必須となっている。
Kubernetes (多くは K8s と略される) は、コンテナ管理ツールのひとつで、コンテナオーケストレーションツールとも呼ばれる。
コンテナ管理といえば、 Docker が非常に有名だ。
Docker はどちらかというと開発者よりのツールで、一つのコンテナないし、 Docker Compose を使って一つのホスト(マシン)内に閉じた複数のコンテナの管理に特化している。
一方、多少規模のあるサービスをコンテナで運用する場合、複数ホストにまたがっていくつものコンテナを協調動作させる場合が多い。
Kubernetes であれば複数のホストに跨がって複数のコンテナを協調操作させる運用管理ができる。
例えば・・・
- 異なるホストで動作しているコンテナを、同じ仮想ネットワークにあるかのように扱う
- 負荷に応じてコンテナをスケーリングする
- コンテナ起動やダウン時の自己修復や負荷分散のロジック等を自分で作り込む
といった事ができる。
Kubernates では、コンテナインスタンスのグループを表す "pod" や、ホストマシンを示す "node" といった概念を「リソース」と呼ばれる設計図のようなもので管理する。
API コマンドや yaml ファイルにて、コンテナの「在るべき状態 (Desired State)」を「pod リソース」や「node リソース」として定義する。
すると、定義した条件に合致するようにコンテナなどが作成され、その作成されたモノを「オブジェクト」と呼ぶ。
ちょうど、一般的なプログラミング言語で言う「クラスとインスタンス」が、「リソースとオブジェクト」の関係にあたるイメージだ。
また、 Kubernetes は Google が実装しているソフトウェアの名前であると同時に、インタフェースの仕様がバージョン毎にしっかり定義されていて、 GKE, EKS, OpenShift, K3s, Minikube, MicroK8s 等々、様々な互換実装が存在する。
これらは各クラウドベンダーに併せた仕様となっていたり、複雑すぎる仕様を一部簡素化して使いやすくなっていたりと、特徴は様々だ。
こうした互換実装のうち、今回は特に Ubuntu と相性がよい MicroK8s の利用を例に解説する。
AWX Operator とは
AWX Operator とは、 K8s の Custom Resource Definitions (CRD) を介して、 Kubernetes クラスター上での AWX のデプロイを管理するツールだ。
CRD とは、 Kubernates 上に独自のリソースを定義する為の機能だ。
例えば、 AWX Operator を使わず Kubernates 上で AWX を動作させようとした場合、Web サービスや DB, ワーカーといった、複数のコンテナ等を一つ一つ個別にリソースを作成しなくてはならず、面倒だ。
そこで、一旦 AWX Operator を MicroK8s など Kubernetes (や、その互換実装) にインストールすると、以降 「AWX
というリソース」を作成できる API が Kubernetes 上に登録される。
その後改めて AWX Operator の記法で AWX
リソースを Kubernetes 上に作成すると、そこで設定したオプションに従って、自動的に適切な Pod や Service, PersistentVolumeClaim リソースなどが登録される仕組みだ。
これにより、個別のコンテナ (Pod) の記述をせずとも AWX を動かせる。
ref: 8. Using Operator — Automation Controller Administration Guide
このような特定のアプリに必要なリソース一式を管理する CRD を、一般的に オペレーターパターン と呼んでいて、 ○○ Operator と名付けられる事が多い。
https://operatorhub.io/ には、 AWX Operator の他にも様々な Operator が登録されている。 (実はここには AWX Operator が登録されていないけど)
導入手順
各ソフトウェアの関係性についてざっくり理解したところで、それぞれのツールのインストールしていく。
Ansible Tower のガイドでは、最低 2GB, 推奨 4GB の RAM が必要となっているが、 MicroK8s との組み合わせで動かすなら少なくとも 4~5GB RAM がないと正常に動かない。
この手順では、説明の簡略化のため MicroK8s と AWX をシングルノードでインストールしているが、マルチノードでの運用ももちろん可能だ。
以降の手順では、 Ubuntu 24.04 で試した例となるが、 snapd がインストールされた環境ならどこでも大体同じはずだ。
MicroK8s のインストール
プロキシ環境下の MicroK8s のインストール方法は、 MicroK8s - Installing behind a proxy のページに記載されている。
Ubuntu での MicroK8s のインストールには、 snap
コマンド (Snapcraft) を使うので、まずは snap に対してプロキシの設定を行う。
sudo snap set system proxy.http=http://proxy.example.com:8080
sudo snap set system proxy.https=http://proxy.example.com:8080
その後、改めて snap
コマンドで MicroK8s をインストールする。
ユーザーには MicroK8s を実行する権限を与えるグループを設する。
また、 snap 内の MicroK8s 環境下にあるコンテナエンジンにプロキシの設定を行う。
このとき、 Kubernetes の API がコンテナ内から自信や他の node に対して通信する関係上、ホスト OS の IPアドレス はプロキシ経由にならないように NO_PROXY
環境変数も設定しておく。 2 3
sudo snap install microk8s --classic --channel=latest/stable
sudo usermod -a -G microk8s $USER
mkdir -p ~/.kube
chmod 0700 ~/.kube
sudo sed -i -E "/HTTPS_PROXY/,/^$/ s%^$%HTTPS_PROXY=http://proxy.example.com:8080\nNO_PROXY=`hostname -I | sed -E 's/^ +| +$//g;s/ +/,/g'`,127.0.0.1,10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,127.0.0.0/8,.svc,localhost\n%" "`snap run --shell microk8s -c 'echo ${SNAP_DATA}'`/args/containerd-env"
sudo snap restart microk8s
なお、 sudo sed
から始まる行で何をやっているのかわかりにくいが、 /var/snap/microk8s/current/args/containerd-env
にあたるパスの (snap 環境上の) ファイルに対して、 HTTPS_PROXY
という文字が登場後最初の空行に、 HTTPS_PROXY
と NO_PROXY
の設定を加える編集をしている。
最後、 Snap と Git の相性が悪くて内部的に Git が動く MicroK8s コマンドを実行するとエラーになる問題 4 を回避するワークアラウンド実行しておく。
cat << EOF >> ~/.bash_aliases
alias kubectl='GIT_EXEC_PATH=/snap/microk8s/current/usr/lib/git-core/ microk8s kubectl'
alias helm='GIT_EXEC_PATH=/snap/microk8s/current/usr/lib/git-core/ microk8s helm'
EOF
一端シェルに再ログインした後、以下を実行して
microk8s status --wait-ready
以下のような正常なステータスを MicroK8s が返せば、インストールは完了だ。
microk8s is running
high-availability: no
datastore master nodes: 127.0.0.1:19001
datastore standby nodes: none
addons:
enabled:
dns # (core) CoreDNS
...
AWX Operator のインストール
Basic install - Ansible AWX Operator Documentation の手順に従って、 AWX Operator をデフォルト値でインストールする。
基本的に書かれた手順通りだが、 kustomization.yaml
の resources の指定の表記が古い 5 ので、そこだけ直している。
export http_proxy=http://proxy.example.com:8080; export https_proxy=$http_proxy
mkdir ~/operator
mkdir ~/awx
cd ~/operator
cat << EOF > ./kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/ansible/awx-operator//config/default?ref=2.19.1
namespace: awx
EOF
kubectl apply -k .
kubectl apply
の実行結果として、以下のように CRD を構成するリソースが登録される。
namespace/awx created
customresourcedefinition.apiextensions.k8s.io/awxbackups.awx.ansible.com created
customresourcedefinition.apiextensions.k8s.io/awxmeshingresses.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
service/awx-operator-controller-manager-metrics-service created
deployment.apps/awx-operator-controller-manager created
AWX のインストール
AWX Operator のインストールに成功したら、いよいよ AWX 本体をインストールする。
構成を簡略するため、 PersistentVolume (永続化ボリューム) をローカルにバインドマウントさせる。
そのためのフォルダと権限を割り当てておく。
sudo mkdir -p /var/lib/k8s-data/postgresql
sudo mkdir /var/lib/k8s-data/postgresql/data
sudo chmod u=rwx,g=,o= /var/lib/k8s-data/postgresql/data
sudo chown 26:26 /var/lib/k8s-data/postgresql/data # gid:uid=26:26(postgres)
再び kustomization.yaml
を使って AWX リソースを記述しよう。
AWX リソースの spec:
部分の記述方法に付いての詳細は、 Ansible AWX Operator Documentation の User Guide や Advanced Configuration の章を参照してくれ。
# awx のインストール
cd ~/awx
cat << EOF > ./kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- awx-demo.yml
namespace: awx
EOF
cat << EOF > ./awx-demo.yml
---
# define PV local volume: see https://qiita.com/ysakashita/items/67a452e76260b1211920
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: sc-awx-local-for-postgres
# annotations:
# storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
# 現在のノード名に紐づけられた PV を作成する
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv-awx-local-for-postgres
spec:
storageClassName: sc-awx-local-for-postgres
capacity:
storage: 4Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
local:
path: /var/lib/k8s-data/postgresql
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- $HOSTNAME
---
# awx spec
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx-demo
spec:
service_type: nodeport
nodeport_port: 30080
postgres_storage_requirements:
requests:
storage: 4Gi
postgres_storage_class: sc-awx-local-for-postgres
extra_settings:
# set proxy thru extra_settings https://ansible.readthedocs.io/projects/awx-operator/en/latest/user-guide/advanced-configuration/extra-settings.html
- setting: AWX_TASK_ENV
value: '{ "HTTPS_PROXY": "http://proxy.example.com:8080", "HTTP_PROXY": "http://proxy.example.com:8080", "NO_PROXY": "127.0.0.1,10.0.0.0/8,172.16.0.0/16,192.168.0.0/16,127.0.0.0/8,.svc,localhost" }'
EOF
kubectl apply -k .
kubectl apply
の実行結果として、以下のように StorageClass, PersistentVolume, AWX のリソースが登録される。
storageclass.storage.k8s.io/sc-awx-local-for-postgres created
persistentvolume/pv-awx-local-for-postgres created
awx.awx.ansible.com/awx-demo created
これで問題なければ、 AWX Operator が自動的に service や pod のオブジェクトを作成していく。
まずは awx-operator-controller, postgres の pod オブジェクトがだんだんプロビジョニングされていき、しばらくすれば以下のように pod や service の実行が出揃うはずだ。
$ kubectl --namespace=awx get pod,svc,pv,pvc
NAME READY STATUS RESTARTS AGE
pod/awx-demo-migration-24.6.1-4h6bt 1/1 Running 0 24s
pod/awx-demo-postgres-15-0 1/1 Running 0 2m21s
pod/awx-demo-task-68cdf8df6-dvtjv 0/4 Init:0/2 0 82s
pod/awx-demo-web-7db69f498-wwp5r 3/3 Running 0 85s
pod/awx-operator-controller-manager-bb695bf5d-55p8x 2/2 Running 0 3m59s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/awx-demo-postgres-15 ClusterIP None <none> 5432/TCP 2m21s
service/awx-demo-service NodePort 10.152.183.95 <none> 80:30080/TCP 89s
service/awx-operator-controller-manager-metrics-service ClusterIP 10.152.183.184 <none> 8443/TCP 3m59s
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
persistentvolume/pv-awx-local-for-postgres 4Gi RWO Retain Bound awx/postgres-15-awx-demo-postgres-15-0 sc-awx-local-for-postgres <unset> 2m58s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/postgres-15-awx-demo-postgres-15-0 Bound pv-awx-local-for-postgres 4Gi RWO sc-awx-local-for-postgres <unset> 2m21s
pod/awx-demo-migration-*
の pod が実行中の間は、 K8s 実行中ホストの :30080
ポートにアクセスしても、以下のようにマイグレーション中の表示が続く。
マイグレーション pod が Completed になれば、ログインページが表示されるようになるはずだ。
$ kubectl --namespace=awx get pod
NAME READY STATUS RESTARTS AGE
awx-demo-migration-24.6.1-4h6bt 0/1 Completed 0 13m
awx-demo-postgres-15-0 1/1 Running 0 15m
awx-demo-task-68cdf8df6-dvtjv 4/4 Running 0 14m
awx-demo-web-7db69f498-wwp5r 3/3 Running 0 14m
awx-operator-controller-manager-bb695bf5d-55p8x 2/2 Running 0 16m
admin アカウントのパスワードは、自動生成されて <resourcename>-admin-password
の secret に登録される ので以下のコマンドで調べる。
kubectl --namespace=awx get secret awx-demo-admin-password -n awx -o 'jsonpath={.data.password}' | base64 --decode; echo
ユーザー名: admin
, パスワードは↑で調べた文字列を使ってログインしよう。
これで AWX のインストールは完了だ。
試しに AWX 上で、 Ansible Galaxy を (collections/requirements.yml
にて) 参照している playbook を実行すると、自動的に Galaxy からダウンロードして実行できる。
このことから、 playbook の実行に必要な情報の DL にも、プロキシが設定されている事がわかるだろう。
メモ
手順としては以上だが、その他細かい補足。
名前空間の既定値
kubectl
のコマンドに、名前空間を指定する --namespace=awx
, -n awx
を設定するのが面倒なら、以下のコマンドで規定値の名前空間がを変更する事でその後 --namespace
のオプション指定が不要になる。
kubectl config set-context --current --namespace=awx
kubectl logs
等のコマンドでエラー
kubectl logs
でエラーが出る場合、可能性として2つ考えられる。
一つはプロキシを経由してノードにアクセスしようとしてしまう場合。
この場合は、プロキシを経由しないようになんとかしよう。 no_proxy にノードの現在のアドレスをピンポイントで追加するとか、 https_proxy 環境変数に空を渡すとか。
もう一つは IP アドレスが変わったせいで、証明書が無効になる場合。
Hyper-V 内の VM で Default Switch を使っていると、再起動などによってよく発生する。
この場合は、microk8s refresh-certs コマンドで証明書を作り直そう。
$ kubectl logs -n awx awx-demo-web-85f7f56c8c-vmjq5
Error from server: Get "https://172.30.197.198:10250/containerLogs/awx/awx-demo-web-85f7f56c8c-vmjq5/awx-demo-web": tls: failed to verify certificate: x509: certificate is valid for 172.21.22.32, 192.168.193.163, not 172.30.197.198
$ sudo microk8s refresh-certs -e server.crt # <- 多分こちらは不要
$ sudo microk8s refresh-certs -e ca.crt
$ kubectl logs -n awx awx-demo-web-85f7f56c8c-vmjq5
2024-06-25 20:50:20,378 INFO RPC interface 'supervisor' initialized
-
Transitioning authentication and authorization (RBAC) to the new AWX architecture - Project Discussions - Ansible ↩
-
この関係で、 Hyper-V 下の環境など再起動の度にホストマシンの IP アドレスが変わってしまう状況下の場合、そのたびにこの設定をやり直す必要がある。 ↩
-
各ノードの IPアドレス にプロキシサーバー経由で接続できるなら、
NO_PROXY
を設定しておく必要はない。 ↩ -
半年近く前に対処例を書いた Issue を報告した が、全く対策されていない。 ↩
-
https://github.com/kubernetes-sigs/kustomize/blob/master/examples/remoteBuild.md#remote-directories ↩