序文
社外からVPN接続するための環境を自営のネットワーク機器で構築したが、インターネットからのアクセスなのでVPN接続のパスワードやアカウントロックアウトなんかのポリシーを少しきつめに設定したところ、アカウントのリセット依頼が頻繁に来るようになってしまった。
利用者のセルフサービスで何とかできないかと思って、前から何かで検証してみようと思っていたAWXでセルフサービス化できないかPoCをやってみることにした。
今回の問題解決だけならポリシーを調整すればよくて、AWXを使って云々するのは費用対効果的には割に合わないのだけど、前から何かでAWXを使ってみたかったので作ってみた。
本記事は、実験のためにPC内の閉じた環境でAWXを初期状態で触れるようにするまでの手順を書いたものである。
環境
手元PCの仮想化環境上で構築した。
- 仮想化ホスト環境
- OSエディション:Windows 10 Pro
- OSバージョン:21H2
- OSビルド:19044.1826
- プロセッサ:AMD Ryzen 5 Pro 4650U with Radeon Graphics 2.10GHz
- 実装RAM:8GB
- 仮想化:Hyper-V
- AWX実行環境(ゲストOS)
- OS: AlmaLinux 9.0
- プロセッサ数:1個
- メモリ:3GB (Hyper-Vの動的メモリは無効)
- その他仮想マシン設定をデフォルトから変えたところ
- 世代:第2世代
- セキュアブート:無効
- ネットワークアダプター:Default Switch
この設定ではPCの外からはAWX実行環境にアクセスできないので、あくまでPC内での検証用途のものである。
構築手順
OSインストール
インストールメディアを↓から入手する。今回は AlmaLinux-9.0-x86_64-minimal.iso をダウンロードする。
https://mirrors.almalinux.org/isos/x86_64/9.0.html
Hyper-Vマネージャで、仮想マシンを適当に新規作成する。このとき、少なくとも以下を設定する。
- 世代の指定:第2世代 (第1世代だとダメということはないけど、今回はこちらを使った)
- メモリの割り当て:3GB以上、動的メモリの使用のチェックを外す →何度か試して、最低3GBあれば何とか動きそうだった。実運用環境だともっと増やした方がよさそう。
- ネットワークの構成:Default Switchを選択 →仮想マシンからインターネットにWebアクセス(リポジトリアクセスのため)できれば他の設定でもよい
- セキュアブート:無効 →第2世代を選んだ場合にのみ存在する設定項目。仮想マシン新規作成ウィザードでは設定できないので、ウィザード完了後に仮想マシンの設定を開いて変更する。有効だと、OSインストールメディアからの起動に失敗する。
メモリが3GB以上空いた状態にしてから仮想マシンを起動し、インストーラーを実行する。最小構成でインストールするので、「インストールの概要」で以下の点のみ変更してインストールを開始する。
- インストール先:自動構成でよいので、選択してそのまま完了
- ネットワークとホスト名:Default SwitchでIPアドレスはDHCP配布されるので、ホスト名だけ任意に設定する。今回は"awx1"と設定する。
- ユーザーの作成:任意にユーザーを作成し「このユーザーを管理者にする」をONにする
インストールが終わってOS再起動したら、「ユーザーの作成」で作成したユーザーでログインできることを確認する。SSHでログインするときの接続先については、ホストOS内(Hyper-VのDefault Switch配下)からはawx1.mshome.net
で接続可能(外部からは接続不可)。
ついでにsudo visudo
でsudoersを開いて、後続作業でパスワード無しでsudoできるようにするために#%wheel ALL=(ALL) NOPASSWD: ALL
の行のコメントを外して(先頭の"#"を削除して)変更を保存する。
K3sインストール
最近のAWXはKubernetes環境へのインストーラーしか提供していないので、まずはKubernetes環境を構築する。AWX公式のドキュメントにはテスト用にMinikubeを使う手順が掲載されているけど、社内システムとして本運用で使えそうなものにしたかったのでK3sを使うことにした。
インストールは、AlmaLinuxにSSHでログインし、以下のコマンド(出力は省略)だけでインストールできる。
$ sudo dnf -y install tar git
$ sudo systemctl disable firewalld --now
$ sudo update-crypto-policies --set DEFAULT:SHA1
$ curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644
$ sudo update-crypto-policies --set DEFAULT
sudo update-crypto-policies --set DEFAULT:SHA1
については、一時的にSHA1を暗号化ポリシーに追加するためのものである。
RHEL8系のときはこれをしなくてもうまくいったけど、RHEL9系からSHA1がデフォルトの暗号化ポリシーから外されていて、デフォルトのままだとK3sのリポジトリのGPG鍵署名の検証に失敗するので実行している。
今後K3sリポジトリのGPG鍵署名がSHA2対応されれば不要になるかも。
インストール後にsudo update-crypto-policies --set DEFAULT
で元に戻している。
firewalldは必要な通信許可だけ設定する方が望ましいが、今回は手抜きでdisableにした。
AWXインストール
まず、事前準備としてkustomizeをインストールする。
最初のコマンドでカレントディレクトリにkustomizeの実行ファイルができるので、お好みでPATHの通っているところに置く。
$ curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
$ sudo chown root.root kustomize
$ sudo mv kustomize /usr/local/bin/
次に、作業用のディレクトリを作成して、そこに移動する。
$ mkdir awx-operator
$ cd awx-operator
必要なマニフェストファイルを作成する。
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
admin_user: admin
admin_password_secret: awx-admin-password
service_type: nodeport
ingress_type: ingress
ingress_tls_secret: awx-secret-tls
hostname: awx1.mshome.net
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: awx
generatorOptions:
disableNameSuffixHash: true
secretGenerator:
- name: awx-secret-tls
type: kubernetes.io/tls
files:
- tls.crt
- tls.key
- name: awx-admin-password
type: Opaque
literals:
- password=write-your-password
resources:
- github.com/ansible/awx-operator/config/default?ref=0.21.0
#- awx.yaml
images:
- name: quay.io/ansible/awx-operator
newTag: 0.21.0
write-your-password
は設定したいパスワードに任意に書き換える。
#- awx.yaml
は後でコメントを外して使うためのもの。
newTag
は https://github.com/ansible/awx-operator/releases を見て、存在するTagを何か選ぶ。今回0.21.0なのは、構築してみようとした時点でそれが最新版だったため。
AWXのWebサーバに設定する証明書(自己署名)を作成する。
$ openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -out tls.crt -keyout tls.key -subj "/CN=awx1.mshome.net/O=awx1.mshome.net" -addext "subjectAltName = DNS:awx1.mshome.net"
awx-operatorのリソースを作成する。
$ kustomize build . | kubectl apply -f -
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/awx-admin-password created
secret/awx-secret-tls created
service/awx-operator-controller-manager-metrics-service created
deployment.apps/awx-operator-controller-manager created
awx-operatorのポッドのREADY が 2/2 になるまで待つ
$ kubectl get pods -n awx
NAME READY STATUS RESTARTS AGE
awx-operator-controller-manager-59fbc545c4-rtl8v 2/2 Running 0 4m23s
次にawxのリソースを作成する。
kustomization.yamlのresourcesにawx.yamlを追加して(コメント状態で追加していたので、コメントを外して)からkustomize buildを実行する。
$ sed -i -e 's/#- awx.yaml/- awx.yaml/' kustomization.yaml # ここではsedで編集しているけど、viなどのエディタで編集してもよい
$ kustomize build . | kubectl apply -f -
namespace/awx unchanged
customresourcedefinition.apiextensions.k8s.io/awxbackups.awx.ansible.com unchanged
customresourcedefinition.apiextensions.k8s.io/awxrestores.awx.ansible.com unchanged
customresourcedefinition.apiextensions.k8s.io/awxs.awx.ansible.com unchanged
serviceaccount/awx-operator-controller-manager unchanged
role.rbac.authorization.k8s.io/awx-operator-awx-manager-role configured
role.rbac.authorization.k8s.io/awx-operator-leader-election-role unchanged
clusterrole.rbac.authorization.k8s.io/awx-operator-metrics-reader unchanged
clusterrole.rbac.authorization.k8s.io/awx-operator-proxy-role unchanged
rolebinding.rbac.authorization.k8s.io/awx-operator-awx-manager-rolebinding unchanged
rolebinding.rbac.authorization.k8s.io/awx-operator-leader-election-rolebinding unchanged
clusterrolebinding.rbac.authorization.k8s.io/awx-operator-proxy-rolebinding unchanged
configmap/awx-operator-awx-manager-config unchanged
secret/awx-admin-password unchanged
secret/awx-secret-tls configured
service/awx-operator-controller-manager-metrics-service unchanged
deployment.apps/awx-operator-controller-manager unchanged
awx.awx.ansible.com/awx created
kubectl get svc -n awx
を実行して、awx-serviceが出ていればサービスが起動できている。
$ kubectl get svc -n awx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
awx-operator-controller-manager-metrics-service ClusterIP 10.43.95.222 <none> 8443/TCP 12m
awx-postgres ClusterIP None <none> 5432/TCP 106s
awx-service NodePort 10.43.242.40 <none> 80:30080/TCP 52s
ただし、内部で初期化処理が走っているためか、AWXのGUIにアクセスできるまでにここから5分~10分くらいかかるので、しばらく待ってからWebブラウザでLinuxサーバーにHTTPS接続する。準備が終わっていないと404エラーや503エラーになるので、その時はもう少し待ってから接続すればよい。
証明書は自己署名証明書なのでブラウザの警告画面が出るが、無視して進むとログイン画面が表示される。
ユーザー名はadminで、パスワードはawx.yamlに書いたものを入力すると管理者権限でログインできる。
以上で構築完了。
自動実行スクリプト
OSインストール後の今回手順は、以下のスクリプトで自動実行できる。
#/bin/bash
# 実行コマンドを表示する & エラー時はその場で終了する設定で動かすようにしてエラー時に状況が分かりやすいようにする
set -x
set -e
# 構築したい環境に応じて以下の変数は適宜編集する
awx_operator_tag=0.21.0
controller_fqdn=awx1.mshome.net
awx_admin_password=write-your-password
# k3s インストール
sudo dnf -y install tar git
sudo systemctl disable firewalld --now
sudo update-crypto-policies --set DEFAULT:SHA1
curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644
sudo update-crypto-policies --set DEFAULT
# kustomize インストール
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
sudo chown root.root kustomize
sudo mv kustomize /usr/local/bin/
# AWX インストール
cd ~
mkdir awx-operator
cd awx-operator
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -out tls.crt -keyout tls.key -subj "/CN=${controller_fqdn}/O=${controller_fqdn}" -addext "subjectAltName = DNS:${controller_fqdn}"
cat << EOS > awx.yaml
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
admin_user: admin
admin_password_secret: awx-admin-password
service_type: nodeport
ingress_type: ingress
ingress_tls_secret: awx-secret-tls
hostname: ${controller_fqdn}
EOS
cat << EOS > kustomization.yaml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: awx
generatorOptions:
disableNameSuffixHash: true
secretGenerator:
- name: awx-secret-tls
type: kubernetes.io/tls
files:
- tls.crt
- tls.key
- name: awx-admin-password
type: Opaque
literals:
- password=${awx_admin_password}
resources:
- github.com/ansible/awx-operator/config/default?ref=${awx_operator_tag}
#- awx.yaml
images:
- name: quay.io/ansible/awx-operator
newTag: ${awx_operator_tag}
EOS
kustomize build . | kubectl apply -f -
# awx-operator-controller-manager が READY 2/2 になるまで待つ
while [ -z "$(kubectl get pods -n awx | grep "^awx-operator-controller-manager.*\s2/2")" ]; do sleep 30; done
kubectl get pods -n awx
sed -i -e 's/#- awx.yaml/- awx.yaml/' kustomization.yaml
kustomize build . | kubectl apply -f -
# kubectl get svc で awx-service が表示されるまで待つ
while [ -z "$(kubectl get svc -n awx | grep "awx-service")" ]; do sleep 30; done
kubectl get svc -n awx