APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

【AP Tech Blog Week】AWX on Amazon EKS with Fargate

目次

本記事はAP Tech Blog Weekのものになります。

techblog.ap-com.co.jp

はじめに

こんにちは、クラウド事業部の梅本です。

以前、AmazonEKS on AWS Fargate で記事を投稿しました。

techblog.ap-com.co.jp

今回はその EKS 上に AWX のデプロイを試していきます。

AWX は Web 画面、REST API 等の機能を持つ Ansible 実行環境です。GitHub との連携もできるため、色々試してみようと思い、環境を用意するために今回は EKS 上に構築を試してみようとなった次第です。

github.com

環境情報

  • Kubernetes:1.29
  • AWX:24.2.0
  • コマンド実行環境:AWS CloudShell
    • eksctl:0.175.0
    • helm:v3.14.4

ツールインストール

まずは CloudShell に、必要なツール(eksctlhelm)をインストールします。

# Install eksctl
$ ARCH=amd64
$ PLATFORM=$(uname -s)_$ARCH
$ curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz"
$ tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz
$ sudo mv /tmp/eksctl /usr/local/bin
$ eksctl version
0.175.0

# Install helm
$ curl -sLO "https://get.helm.sh/helm-v3.14.4-linux-amd64.tar.gz"
$ tar -xzf helm-v3.14.4-linux-amd64.tar.gz -C /tmp && rm helm-v3.14.4-linux-amd64.tar.gz
$ sudo mv /tmp/linux-amd64/helm /usr/local/bin/
$ helm version
version.BuildInfo{Version:"v3.14.4", GitCommit:"81c902a123462fd4052bc5e9aa9c513c4c8fc142", GitTreeState:"clean", GoVersion:"go1.21.9"}

EKS 構築

早速EKSを構築します。eksctl で1コマンドです!15~20分ほどで完了となります。

# Create EKS Cluster
$ eksctl create cluster --name ume-cluster --region ap-northeast-1 --fargate --with-oidc

2024-04-21 14:16:37 []  eksctl version 0.175.0
...
2024-04-21 14:30:57 []  EKS cluster "ume-cluster" in "ap-northeast-1" region is ready

AWX Operator デプロイ

次に AWX のデプロイ作業を自動で行ってもらえる AWX Operator を EKS にデプロイします。AWX のデプロイ方法は複数ありますが、今回は AWX Operator を利用することにします。AWX Operator を利用することで、YAML ファイル1つでデプロイ、設定の適用を行うことができます。

まずは、EKS にコンテナがデプロイできるように Fargate プロファイルを追加します。eksctl で構築した EKS では、default Namespace に Pod が起動できる Fargate となります。

今回は AWX、AWX Operator 共に awx Namespace にデプロイするため、その設定を追加します。

$ eksctl create fargateprofile \
--cluster ume-cluster \
--name awx-fargate-profile \
--namespace awx

2024-04-21 14:35:09 []  creating Fargate profile "awx-fargate-profile" on EKS cluster "ume-cluster"
2024-04-21 14:35:27 []  created Fargate profile "awx-fargate-profile" on EKS cluster "ume-cluster"

AWX Operator のデプロイ準備ができたので、早速デプロイしていきます。AWX Operator のデプロイはツールインストールで導入した helm を利用します。

# Add AWX Operator repo to helm
$ helm repo add awx-operator https://ansible.github.io/awx-operator/
$ helm repo update

# Install awx-operator
$ helm install -n awx --create-namespace awx-operator awx-operator/awx-operator

NAME: awx-operator
LAST DEPLOYED: Sun Apr 21 14:35:52 2024
NAMESPACE: awx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWX Operator installed with Helm Chart version 2.15.0

EFS 構築

AWX デプロイに AWX Operator を利用しますが、もう1つ準備を行います。AWX では PostgreSQL が EKS 上にデプロイされます。デプロイに際し PV が必要なのですが、Fargate では EKS デフォルトの PV である EBS が利用できないため、Amazon EFS を構築して PV を割り当てるようにします。

EFS および、この後に出てくる LoadBalancer については以下の AWS の記事を参考にさせて頂きました。

aws.amazon.com

# Define env vars
$ AWS_REGION=ap-northeast-1
$ ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
$ EKS_CLUSTER=ume-cluster

$ VPC_ID=$(aws eks describe-cluster --name $EKS_CLUSTER --query "cluster.resourcesVpcConfig.vpcId" --region $AWS_REGION --output text)
$ CIDR_BLOCK=$(aws ec2 describe-vpcs --vpc-ids $VPC_ID --query "Vpcs[].CidrBlock" --region $AWS_REGION --output text)

# Create EFS
$ EFS_FS_ID=$(aws efs create-file-system \
--creation-token ume-cluster-on-fargate \
--encrypted \
--performance-mode generalPurpose \
--throughput-mode bursting \
--tags Key=Name,Value=UmeClusterVolume \
--region $AWS_REGION \
--output text \
--query "FileSystemId")

# Create Access point
# uid/gid を postgres ユーザの番号に設定
$ EFS_AP=$(aws efs create-access-point \
--file-system-id $EFS_FS_ID \
--posix-user Uid=26,Gid=26 \
--root-directory "Path=/postgres,CreationInfo={OwnerUid=26,OwnerGid=26,Permissions=777}" \
--region $AWS_REGION \
--query 'AccessPointId' \
--output text)

# Create Security Group
$ EFS_SG_ID=$(aws ec2 create-security-group \
--description umecluster-on-Fargate \
--group-name umecluster-on-fargate \
--vpc-id $VPC_ID \
--region $AWS_REGION \
--query 'GroupId' --output text)

# Add Security Group Rule for EFS
$ aws ec2 authorize-security-group-ingress \
--group-id $EFS_SG_ID \
--protocol tcp \
--port 2049 \
--cidr $CIDR_BLOCK

# Create mount target 
$ for subnet in $(aws eks describe-fargate-profile \
  --output text --cluster-name $EKS_CLUSTER\
  --fargate-profile-name fp-default  \
  --region $AWS_REGION  \
  --query "fargateProfile.subnets"); \
do (aws efs create-mount-target \
  --file-system-id $EFS_FS_ID \
  --subnet-id $subnet \
  --security-group $EFS_SG_ID \
  --region $AWS_REGION); \
done

EFS の準備が出来たので、今度は EKS 上に StorageClass と PV を作成します。

# Create StorageClass for EFS
$ echo "
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
  annotations:
    storageclass.kubernetes.io/is-default-class: 'true'
provisioner: efs.csi.aws.com
" | kubectl apply -f -

storageclass.storage.k8s.io/efs-sc created

# デフォルトの StorageClass に設定されているデフォルト設定の Annotation を削除
$ kubectl annotate sc gp2 storageclass.kubernetes.io/is-default-class-

storageclass.storage.k8s.io/gp2 annotated

$ kubectl get sc
NAME               PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
efs-sc (default)   efs.csi.aws.com         Delete          Immediate              false                  56s
gp2                kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  26m

# Create PV for PostgreSQL
$ echo "
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-15-awx-postgres-15-0
spec:
  capacity:
    storage: 8Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: efs-sc
  csi:
    driver: efs.csi.aws.com
    volumeHandle: $EFS_FS_ID::$EFS_AP
  claimRef:
    namespace: awx
    name: postgres-15-awx-postgres-15-0
" | kubectl apply -f -

persistentvolume/postgres-15-awx-postgres-15-0 created

AWX デプロイ

準備ができたので AWX をデプロイしていきましょう。

何度か試して分かったのですが、デフォルトのリソース設定ですとコンテナのスペックが低すぎて処理に時間がかかりました。このため、XXXX_resource_requirements を指定して、コンテナのスペックを上げています。

# Deploy AWX
$ echo "
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: awx
  namespace: awx
spec:
  service_type: ClusterIP
  task_resource_requirements:
    requests:
      cpu: 500m
      memory: 1Gi
  web_resource_requirements:
    requests:
      cpu: 500m
      memory: 1Gi
  postgres_resource_requirements:
    requests:
      cpu: 500m
      memory: 1Gi
  ee_resource_requirements:
    requests:
      cpu: 500m
      memory: 1Gi
  redis_resource_requirements:
    requests:
      cpu: 500m
      memory: 1Gi
  rsyslog_resource_requirements:
    requests:
      cpu: 500m
      memory: 1Gi
  init_container_resource_requirements:
    requests:
      cpu: 500m
      memory: 1Gi
" | kubectl apply -f -

awx.awx.ansible.com/awx created

$ kubectl get po
NAME                                               READY   STATUS    RESTARTS   AGE
awx-operator-controller-manager-XXXXXXXXXX-XXXXX   2/2     Running   0          16m
awx-postgres-15-0                                  0/1     Pending   0          63s

$ kubectl describe po awx-postgres-15-0
Name:                 awx-postgres-15-0
Namespace:            awx
...
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  76s   fargate-scheduler  Pod not supported on Fargate: volumes not supported: postgres-15 not supported because: PVC postgres-15-awx-postgres-15-0 not bound

PostgreSQLが待てど暮らせど起動してこない・・・Events には PVC の Warningがでていますが、PVC は作成した PV に Boundしています・・・

レプリカ 0 ⇒ 1 で Pod の再作成を行うと正常に起動しました。

# Pod 再起動
$ kubectl scale sts awx-postgres-15 --replicas 0
statefulset.apps/awx-postgres-15 scaled
$ kubectl scale sts awx-postgres-15 --replicas 1
statefulset.apps/awx-postgres-15 scaled

# PostgreSQL が正常に起動し、他コンテナも起動
$ kubectl get po
NAME                                               READY   STATUS     RESTARTS   AGE
awx-migration-24.2.0-xxxxx                         1/1     Running    0          107s
awx-operator-controller-manager-xxxxxxxxxx-xxxxx   2/2     Running    0          28m
awx-postgres-15-0                                  1/1     Running    0          11m
awx-task-xxxxxxxx-xxxxx                            0/4     Init:0/2   0          7m50s
awx-web-xxxxxxxxxx-xxxxx                           3/3     Running    0          7m57s

awx-migration-24.2.0-xxxxx は Job のため、処理が終わる(Completed)のを待ちます。ここで 15~20 分ほど待ちました。

# Completed 後の Migration Pod のログ
$ kubectl logs -f awx-migration-24.2.0-xxxxx
Operations to perform:
  Apply all migrations: auth, conf, contenttypes, dab_resource_registry, main, oauth2_provider, sessions, sites, social_django, sso
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0001_initial... OK
  Applying main.0001_initial... OK
...
  Applying main.0189_inbound_hop_nodes... OK
  Applying main.0190_alter_inventorysource_source_and_more... OK
  Applying sites.0001_initial... OK
  Applying sites.0002_alter_domain_unique... OK
  Applying social_django.0001_initial... OK
...
  Applying social_django.0015_rename_extra_data_new_usersocialauth_extra_data... OK
  Applying sso.0001_initial... OK
  Applying sso.0002_expand_provider_options... OK
  Applying sso.0003_convert_saml_string_to_list... OK

これですべての AWX の Pod が起動しました。

$ kubectl get po
NAME                                               READY   STATUS      RESTARTS   AGE
awx-migration-24.2.0-xxxxx                         0/1     Completed   0          18m
awx-operator-controller-manager-xxxxxxxxxx-xxxxx   2/2     Running     0          45m
awx-postgres-15-0                                  1/1     Running     0          27m
awx-task-xxxxxxxx-xxxxx                            4/4     Running     0          24m
awx-web-xxxxxxxxxx-xxxxx                           3/3     Running     0          24m

AWS LoadBalancer Controller デプロイ

AWX はデプロイできたのですが、インターネットからアクセスする方法がまだ構築できていません。今回は AWS LoadBalancer Controller をデプロイして、ALB からアクセスできるようにします。Ingress を作成するだけで、AWS LoadBalancer Controller がインターネットからのアクセスに必要な ALB の作成や設定が自動的に行われます。

# AWS LoadBalancer Controller で利用する IAM Policy をダウンロード
$ curl -S https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json -o iam-policy.json

# Create IAM Policy
$ aws iam create-policy \
  --policy-name AWSLoadBalancerControllerIAMPolicyUme \
  --policy-document file://iam-policy.json

# Create ServiceAccount
$ eksctl create iamserviceaccount \
  --cluster=$EKS_CLUSTER \
  --region $AWS_REGION \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --override-existing-serviceaccounts \
  --attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicyUme \
  --approve

...
2024-04-21 15:26:26 []  created serviceaccount "kube-system/aws-load-balancer-controller"

# Add eks repo to helm
$ helm repo add eks https://aws.github.io/eks-charts
$ helm repo update

# Deploy CRDs
$ curl -s "https://raw.githubusercontent.com/aws/eks-charts/master/stable/aws-load-balancer-controller/crds/crds.yaml" -o crds.yaml
$ kubectl apply -f crds.yaml

# Deploy AWS LoadBalancer Controller
$ helm install aws-load-balancer-controller \
eks/aws-load-balancer-controller \
--namespace kube-system \
--set clusterName=$EKS_CLUSTER \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set vpcId=$VPC_ID \
--set region=$AWS_REGION

NAME: aws-load-balancer-controller
LAST DEPLOYED: Sun Apr 21 15:32:30 2024
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!

$ kubectl get po -n kube-system
NAME                                            READY   STATUS    RESTARTS   AGE
aws-load-balancer-controller-6c95d95f95-fbtcz   1/1     Running   0          5m22s
aws-load-balancer-controller-6c95d95f95-xlxld   1/1     Running   0          5m22s
coredns-bd9d5dd9f-5rnz7                         1/1     Running   0          68m
coredns-bd9d5dd9f-dhrwg                         1/1     Running   0          68m

Controller の準備が出来たので、ingress を使って、LoadBalancer を作成していきます。

# Create Ingress
$ echo "
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/scheme: "internet-facing"
    alb.ingress.kubernetes.io/healthcheck-path: "/"
    alb.ingress.kubernetes.io/success-codes: "200,201,302"
    alb.ingress.kubernetes.io/target-type: "ip"
  name: awx-ingress
  namespace: awx
spec:
  ingressClassName: alb
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: awx-service
            port:
              number: 80
" | kubectl apply -f -

ingress.networking.k8s.io/awx-ingress created

$ kubectl get ing
NAME          CLASS   HOSTS   ADDRESS                                                                   PORTS   AGE
awx-ingress   alb     *       k8s-awx-awxingre-xxxxxxxxxx-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com   80      29s

無事に LoadBalancer が作成されました。

最後に確認した ingress の ADDRESS が LoadBalancer へのアクセス先となります。

アクセス確認

インターネットからのアクセス方法も確立できたので早速アクセス、ログインを試してみます。

アクセス先は前章でも確認した ADDRESS となります。

ログインの際に必要となる admin ユーザのパスワードを確認します。

$ kubectl get secrets awx-admin-password -o jsonpath="{.data.password}" | base64 -d
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

確認したパスワードで admin ユーザとしてログインします。

ログイン画面

ダッシュボード画面

おわりに

色々と四苦八苦しましたが、何とかデプロイすることができました。関連サービスである EFS や ALB(AWS LoadBalancer Controller)との連携もスムーズに行うことが出来ました。

今回は構築だけとなりましたが、当初の目的である AWX と GitHub の連携等も今後も試していきたいと思います!

お知らせ

APCはAWS Advanced Tier Services(アドバンストティアサービスパートナー)認定を受けております。

その中で私達クラウド事業部はAWSなどのクラウド技術を活用したSI/SESのご支援をしております。

www.ap-com.co.jp

また、AWSの運用自動化ツールも展開しております。

www.ap-com.co.jp

一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。

www.ap-com.co.jp

本記事の投稿者: t-umemoto
コンテナや k8s をメインにインフラ系のご支援を担当しています。
AWS は現在学び直し中! 普段は QiitaZenn に k8s を中心とした記事を投稿しております。よろしければ。