はじめに
先月あたりにAmazon Linux 2023
が登場しましたが、Ansible
が実行できるSystems Manager Run Command
のAWS-ApplyAnsiblePlaybooks
がまだAmazon Linux 2023
に対応していなかったため、Amazon Linux 2023
でも動かせるようにしたいと思います。
Systems Manager Run CommandによるAnsibleの実行
過去記事で何度か紹介しているため、詳しくは以下を参照。
- Amazon S3からのスクリプトの実行をやってみた。
- AnsibleをAWS Systems Managerから実行するCI/CDを構築する。(その1:Systems ManagerからのAnsible実行)
Systems Manager Run Commandについて
Systems Manager Run Command
は予め準備されている「ドキュメント」と呼ばれる定義ファイルに従って、指定したインスタンスに対してコマンド等を実行する機能となります。
Ansible
を実行するAWS公式のAWS-ApplyAnsiblePlaybooks
ドキュメントもドキュメント内の設定を見ると分かる通り、やっていることはAnsible
のインストールとplaybook
の実行、あとはAWSマネジメントコンソールからの操作時に表示する設定が書かれているだけなので、このドキュメントをカスタマイズして、Amazon Linux 2023
でも使えるようにします。
なぜAmazon Linux 2023のインスタンスに対して実行できないか?
実際に実行してみれば分かりますが、AWS-ApplyAnsiblePlaybooks
ドキュメントに書かれている条件式がAmazon Linux 2023
に対応していないからとなります。
以下ドキュメントからの条件式部分抜粋ですが、インスタンスのOS判定のため、/etc/system-release
というファイルの中身を見てOSを判定し、OS毎にAnsible
のインストール方法を変えています。
"runCommand": [
"#!/bin/bash",
"if [[ \"{{InstallDependencies}}\" == True ]] ; then",
" echo \"Installing and or updating required tools: Ansible, wget unzip ....\" >&2",
" if [ -f \"/etc/system-release\" ] ; then",
" if cat /etc/system-release|grep -i 'Amazon Linux release 2' ; then ",
" sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm",
" sudo yum install -y ansible",
" sudo yum -y install unzip",
" elif cat /etc/system-release|grep -i 'Amazon Linux AMI' ; then ",
" sudo pip install ansible --upgrade",
" sudo yum -y install unzip",
" elif cat /etc/system-release|grep -i 'Red Hat Enterprise Linux' ; then ",
" sudo yum -y install python3-pip",
" sudo pip3 install ansible",
" sudo yum -y install unzip",
" else",
" echo \"There was a problem installing or updating the required tools for the document. You can review the log files to help you correct the problem.\" >&2",
" exit 1",
" fi",
ちなみにAmazon Linux 2023
の/etc/system-release
には以下のような文言が記載されております。
Amazon Linux release 2023 (Amazon Linux)
Amazon Linux 2023
のインスタンスで実行した場合、Amazon Linux 2用のAmazon Linux release 2
に引っかかるため、epel
リポジトリインストールしてAnsible
をインストールする流れとなりますが、Amazon Linux 2023
のリポジトリにはepel
リポジトリが無いことからAnsible
のインストールに失敗してしまうことが原因となります。
カスタムドキュメント作成
以下よりAmazon Linux 2023
対応したカスタムドキュメントを作成していこうと思います。
「AWS Systems Manager」の左ペインから「ドキュメント」を選択し、「AWS-ApplyAnsiblePlaybooks」を選びます。
右上の「アクション」から「ドキュメントのクローン作成」を選択するとクローンが作成できるため、以下のように入力。
尚、名前については先頭がAWS
で始まる名前は予約されており、指定できないので、今回はCustom-ApplyAnsiblePlaybooksAL2023
といった名前にしました。
項目 | 設定 | 備考 |
---|---|---|
名前 | Custom-ApplyAnsiblePlaybooksAL2023 | 適当な名前を入力 |
ターゲットタイプ | 空欄 | |
ドキュメントタイプ | コマンドドキュメント | クローン作成の場合は指定不可 |
コンテンツ | JSON | コンテンツの中身については後述 |
ドキュメントのタグ | 任意 |
Amazon Linux 2023対応版コンテンツの作成
先に対応版のドキュメント全容を紹介。
{
"schemaVersion": "2.2",
"description": "Use this document to run Ansible Playbooks on Systems Manager managed instances. For more information, see https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-state-manager-ansible.html.",
"parameters": {
"SourceType": {
"description": "(Optional) Specify the source type.",
"type": "String",
"allowedValues": [
"GitHub",
"S3"
]
},
"SourceInfo": {
"description": "(Optional) Specify the information required to access the resource from the specified source type. If source type is GitHub, then you can specify any of the following: 'owner', 'repository', 'path', 'getOptions', 'tokenInfo'. Example GitHub parameters: {\"owner\":\"awslabs\",\"repository\":\"amazon-ssm\",\"path\":\"Compliance/InSpec/PortCheck\",\"getOptions\":\"branch:master\"}. If source type is S3, then you can specify 'path'. Important: If you specify S3, then the IAM instance profile on your managed instances must be configured with read access to Amazon S3.",
"type": "StringMap",
"displayType": "textarea",
"default": {}
},
"InstallDependencies": {
"type": "String",
"description": "(Required) If set to True, Systems Manager installs Ansible and its dependencies, including Python, from the PyPI repo. If set to False, then verify that Ansible and its dependencies are installed on the target instances. If they aren’t, the SSM document fails to run.",
"allowedValues": [
"True",
"False"
],
"default": "True"
},
"PlaybookFile": {
"type": "String",
"description": "(Optional) The Playbook file to run (including relative path). If the main Playbook file is located in the ./automation directory, then specify automation/playbook.yml.",
"default": "hello-world-playbook.yml",
"allowedPattern": "[(a-z_A-Z0-9\\-\\.)/]+(.yml|.yaml)$"
},
"ExtraVariables": {
"type": "String",
"description": "(Optional) Additional variables to pass to Ansible at runtime. Enter key/value pairs separated by a space. For example: color=red flavor=cherry",
"default": "SSM=True",
"displayType": "textarea",
"allowedPattern": "^$|^\\w+\\=(([^\\s|:();&]+)|('[^|:();&]+'))(\\s+\\w+\\=(([^\\s|:();&]+)|('[^|:();&]+')))*$"
},
"Check": {
"type": "String",
"description": "(Optional) Use this parameter to run a check of the Ansible execution. The system doesn’t make any changes to your systems. Instead, any module that supports check mode reports the changes it would make rather than making them. Modules that don’t support check mode take no action and don’t report changes that would be made.",
"allowedValues": [
"True",
"False"
],
"default": "False"
},
"Verbose": {
"type": "String",
"description": "(Optional) Set the verbosity level for logging Playbook executions. Specify -v for low verbosity, -vv or –vvv for medium verbosity, and -vvvv for debug level.",
"allowedValues": [
"-v",
"-vv",
"-vvv",
"-vvvv"
],
"default": "-v"
},
"TimeoutSeconds": {
"type": "String",
"description": "(Optional) The time in seconds for a command to be completed before it is considered to have failed.",
"default": "3600"
}
},
"mainSteps": [
{
"action": "aws:downloadContent",
"name": "downloadContent",
"inputs": {
"SourceType": "{{ SourceType }}",
"SourceInfo": "{{ SourceInfo }}"
}
},
{
"action": "aws:runShellScript",
"name": "runShellScript",
"inputs": {
"timeoutSeconds": "{{ TimeoutSeconds }}",
"runCommand": [
"#!/bin/bash",
"if [[ \"{{InstallDependencies}}\" == True ]] ; then",
" echo \"Installing and or updating required tools: Ansible, wget unzip ....\" >&2",
" if [ -f \"/etc/system-release\" ] ; then",
" if cat /etc/system-release|grep -i 'Amazon Linux release 2023' ; then ",
" sudo yum -y install python3-pip",
" sudo pip3 install ansible",
" sudo yum -y install unzip",
" elif cat /etc/system-release|grep -i 'Amazon Linux release 2' ; then ",
" sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm",
" sudo yum install -y ansible",
" sudo yum -y install unzip",
" elif cat /etc/system-release|grep -i 'Amazon Linux AMI' ; then ",
" sudo pip install ansible --upgrade",
" sudo yum -y install unzip",
" elif cat /etc/system-release|grep -i 'Red Hat Enterprise Linux' ; then ",
" sudo yum -y install python3-pip",
" sudo pip3 install ansible",
" sudo yum -y install unzip",
" else",
" echo \"There was a problem installing or updating the required tools for the document. You can review the log files to help you correct the problem.\" >&2",
" exit 1",
" fi",
" elif cat /etc/issue|grep -i Ubuntu ; then ",
" UBUNTU_VERSION=$(cat /etc/issue | grep -i ubuntu | awk '{print $2}' | awk -F'.' '{print $1}')",
" sudo apt-get update",
" if [ $(($UBUNTU_VERSION > 18)) == 1 ]; then",
" sudo DEBIAN_FRONTEND=noninteractive apt-get install python3-pip -y",
" sudo pip3 install ansible --upgrade",
" else",
" sudo DEBIAN_FRONTEND=noninteractive apt-get install python-pip -y",
" sudo pip install ansible --upgrade",
" fi",
" sudo DEBIAN_FRONTEND=noninteractive apt-get install unzip -y",
" else",
" echo \"There was a problem installing or updating the required tools for the document. You can review the log files to help you correct the problem.\" >&2",
" exit 1",
" fi",
"fi",
"echo \"Running Ansible in `pwd`\"",
"#this section locates files and unzips them",
"for zip in $(find -iname '*.zip'); do",
" unzip -o $zip",
"done",
"PlaybookFile=\"{{PlaybookFile}}\"",
"if [ ! -f \"${PlaybookFile}\" ] ; then",
" echo \"The specified Playbook file doesn't exist in the downloaded bundle. Please review the relative path and file name.\" >&2",
" exit 2",
"fi",
"if [[ \"{{Check}}\" == True ]] ; then",
" ansible-playbook -i \"localhost,\" --check -c local -e \"{{ExtraVariables}}\" \"{{Verbose}}\" \"${PlaybookFile}\"",
"else",
" ansible-playbook -i \"localhost,\" -c local -e \"{{ExtraVariables}}\" \"{{Verbose}}\" \"${PlaybookFile}\"",
"fi"
]
}
}
]
}
追加修正した箇所はOS判定の部分で、先にAmazon Linux 2
の判定に引っかからないよう、if文の先頭にAmazon Linux release 2023
を追加し、else ifでAmazon Linux 2
の判定とするようにしています。
また、Amazon Linux 2023
にAnsible
をインストールする方法としては、Red Hat Enterprise Linux
の手順がそのまま利用できたので、 そのままコピペしています。
以下追加修正箇所抜粋。
" if [ -f \"/etc/system-release\" ] ; then",
" if cat /etc/system-release|grep -i 'Amazon Linux release 2023' ; then ",
" sudo yum -y install python3-pip",
" sudo pip3 install ansible",
" sudo yum -y install unzip",
" elif cat /etc/system-release|grep -i 'Amazon Linux release 2' ; then ",
" sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm",
" sudo yum install -y ansible",
" sudo yum -y install unzip",
上記を見て分かる通りAmazon Linux 2
とは異なりpip
によるインストールとなることから、yum・dnf
による管理では無くなるためご注意ください。
また、今回はRed Hat Enterprise Linux
の判定部分をそのままコピペしてきたので修正していませんが、気になる方はyum
の部分をdnf
に変更しても問題ありません。(yum
もdnf
にリンクされているので内部的には変わりませんが)
カスタムドキュメントの実行
やることは通常のRun Command
を実行する場合と変わらず、ドキュメント指定する際に先程作成したカスタムドキュメントを指定するだけです。
条件式以外はAWS公式のドキュメントと変えていないので、AWS-ApplyAnsiblePlaybooks
と同じように指定すれば実行できます。
おわりに
まだ登場して間もないため、対応していないサービスも多いですが、各サービスともに順次Amazon Linux 2023
に対応していくと思うので、今回のような対応を行わなくてもすぐにAWS公式で対応してくれるかと思います。
Amazon Linux 2023
でもいち早くAnsible
のドキュメントを使いたいという方はAWS公式で対応するまでの暫定対処として参考にしてもらえればと思います。