作者: 饶维波
本文记录通过ChatGPT生成cloud-init制作AppDynamics在AWS上 AMI安装镜像的过程,形成操作文档作为参考指南。
任务简介和总体思路
任务简介
Cisco AppDynamics 提供功能强大、易于使用的应用程序性能管理(APM)解决方案,端到端监控亚马逊云的应用程序,包括微服务和 Docker,通过 CloudWatch 集成为 EC2、DynamoDB、Lambda 等提供支持。AppDynamics可比较和验证云迁移前后的从客户到业务的优化,从而加速客户上云,因而深受用户喜爱。
为了提升用户在亚马逊云科技云端安装部署AppDynamics软件的效率,我们需要制作一个打包好的安装镜像,叫做Amazon Machine Images (AMI)。用户使用AMI镜像启动虚拟机即可进入AppDynamics的设置界面,这能帮助用户节省大量软件下载、安装调试的时间,极大改善用户的安装体验。
本次任务的目标是需要完成AppDynamics AMI的制作,且为了便于后续维护,维护的工作主要包括操作系统层面的安全漏洞修复、AppDynamics软件版本的升级,尽量使用自动化,节省人的时间精力的同时,避免人为错误。
任务关键点是需要编写一个自动化脚本,考虑为Shell脚本或者cloud-init脚本。
总体思路
首先需要考虑安装镜像的目标状态是什么?我们设想用户通过镜像创建EC2虚拟机实例,可以直接进入Enterprise Console的界面,并已预设了用户名密码。
那我们可否启动一个EC2实例,并且在上面完成Enterprise Console的安装,然后生成快照做成AMI镜像?咨询了一下安装过AppDynamics的同事,他表示他宁愿选择重新安装,因为每个用户的需求是不同的。因此,我们只需要把需要安装的软件包下载到EC2实例,并设置好安装参数,等用户对AMI镜像进行实例化(基于AMI创建虚拟机)时,再进行Enterprise Console的安装。
AWS对于AMI镜像有要求,即不允许使用静态设定的密码,建议使用EC2的instance-id作为密码。
那么,我们的任务就基本清晰了,以下是任务清单
- 启动EC2实例,安装所需要的依赖包,以确保AppDynamics软件包能正常安装
- 设置用户权限
- 将AppDynamics的软件包拷贝到EC2实例
- 生成默认的安装参数,并设置系统启动脚本,该脚本只执行一次,在AMI实例化时执行安装,并启动Enterprise Console
- 按照AWS的安全合规要求进行处理,包括设置SSH参数,清除SSH Key,不留后门等要求。
- 关机后,基于EC2实例的快照制作镜像
- 最后是对镜像进行验证
上面最关键的点是自动化脚本的编写,在这里,笔者使用ChatGPT来辅助生成代码。
通过与ChatGPT对话,让其生成代码
与ChatGPT的对话
经多次对话后,整理内容如下:
请你帮助生成一个Cloud-init代码,自动执行以下内容。
在AWS Console启动AWS Linux 2 AMI,并在启动时执行以下动作:
1、安装libaio, numactl, tzdata, ncurses-libs-5.x
2、在/etc/security/limits.conf 中添加以下配置
1 2 3 4 5
| root hard nofile 65535 root soft nofile 65535 root hard nproc 8192 root soft nproc 8192
|
3、你已经会安装Cisco AppDynamics Enterprise Console 21.6.1版本,现在我将安装文件拷贝到了s3://ciscoappd/platform-setup-x64-linux-21.6.1.26487.sh。请创建/opt/appdynamics目录,将Cisco AppDynamics Enterprise Console的安装文件s3://ciscoappd/platform-setup-x64-linux-21.6.1.26487.sh拷贝至该目录,并将其设置为可执行;
4、在/opt/appdynamics目录,生成初始文件response.varfile.bak,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12
| serverHostName=HOST_NAME sys.languageId=en disableEULA=true platformAdmin.port=9191 platformAdmin.databasePort=3377 platformAdmin.dataDir=/opt/appdynamics/platform/mysql/data platformAdmin.databasePassword=ENTER_PASSWORD platformAdmin.databaseRootPassword=ENTER_PASSWORD platformAdmin.adminPassword=ENTER_PASSWORD platformAdmin.useHttps$Boolean=false sys.installationDir=/opt/appdynamics/platform
|
上面的工作完成之后,再执行以下工作。
5、请生成一个开机启动脚本,要求如下:
5.1 该脚本不在本EC2实例中执行,将其设置为开机后延迟30秒之后再执行,脚本仅需执行一次;
5.2 将/opt/appdynamics/response.varfile.bak 复制为 opt/appdynamics/response.varfile
5.2 将/opt/appdynamics/response.varfile中的ENTER_PASSWORD替换为EC2 meta-data中的instance-id
5.3 将/opt/appdynamics/response.varfile中的HOST_NAME设置为EC2 meta-data中的hostname
5.4 静默安装Enterprise Console /opt/appdynamics/platform-setup-x64-linux-21.6.1.26487.sh -q -varfile /opt/appdynamics/response.varfile
一些对话经验:
- ChatGPT所掌握的数据截止到2021年9月,比如您问他卡塔尔世界杯的结果,他是不知道的。在经过多次与ChatGPT对话,它告诉我他能安装的AppDynamics最新版本是21.6.1,如果我请它直接安装23.1.1.18,它给出的代码有误。于是我请它按照21.6.1版本来安装,在上面的对话中可以看出有这部分的内容。
- 如果一次提问的需求过于复杂,它在生成代码时,会因意外中断,因此,要注意控制一次对话的长度和问题的复杂度。上面列出的对话内容是多次对话整理出来的。
- 如果它理解不对,可以直接指正它,吧需求提的更具体,比如请使用‘write_files’和‘runcmd’生成代码。如果不加限制,它可能会给出整段代码全部都用 echo 语句来实现,相比结构化的代码,不易理解。
生成的cloud-init代码
通过继续追问,让其帮忙生成Systemd的服务配置文件,要求只运行一次,再经过多次调试和修改,最终形成以下cloud-init代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| packages: - libaio - numactl - tzdata - ncurses-libs-5.x
write_files: - path: /etc/security/limits.conf content: | root hard nofile 65535 root soft nofile 65535 root hard nproc 8192 root soft nproc 8192
- path: /opt/appdynamics/response.varfile.bak content: | serverHostName=HOST_NAME sys.languageId=en disableEULA=true platformAdmin.port=9191 platformAdmin.databasePort=3377 platformAdmin.dataDir=/opt/appdynamics/platform/mysql/data platformAdmin.databasePassword=ENTER_PASSWORD platformAdmin.databaseRootPassword=ENTER_PASSWORD platformAdmin.adminPassword=ENTER_PASSWORD platformAdmin.useHttps$Boolean=false sys.installationDir=/opt/appdynamics/platform
- path: /etc/systemd/system/appd.console.service permissions: '0644' content: | [Unit] Description=AppDynamics Enterprise Console After=network.target
[Service] Type=forking ExecStart=/opt/appdynamics/platform/platform-admin/bin/platform-admin.sh start-platform-admin ExecStop=/opt/appdynamics/platform/platform-admin/bin/platform-admin.sh stop-platform-admin User=root Restart=always
[Install] WantedBy=multi-user.target
- path: /etc/systemd/system/appd.console.install.service permissions: '0644' content: | [Unit] Description=AppDynamics Enterprise Console Installation After=network.target
[Service] Type=oneshot RemainAfterExit=no ExecStart=/bin/sh -c 'sleep 5 && cp /opt/appdynamics/response.varfile.bak /opt/appdynamics/response.varfile && sed -i \"s/ENTER_PASSWORD/`curl http://169.254.169.254/latest/meta-data/instance-id`/g\" /opt/appdynamics/response.varfile && sed -i \"s/HOST_NAME/`curl http://169.254.169.254/latest/meta-data/hostname`/g\" /opt/appdynamics/response.varfile && /opt/appdynamics/platform-setup-x64-linux-23.1.1.18.sh -q -varfile /opt/appdynamics/response.varfile && systemctl daemon-reload && systemctl enable appd.console.service && systemctl start appd.console.service'
[Install] WantedBy=multi-user.target
runcmd: - aws s3 cp s3://ciscoappdnx/platform-setup-x64-linux-23.1.1.18.sh /opt/appdynamics/ --region cn-northwest-1 - chmod +x /opt/appdynamics/platform-setup-x64-linux-23.1.1.18.sh - systemctl daemon-reload - systemctl enable appd.console.install.service - sed -i 's/#PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config - rm -rf /root/.ssh/authorized_keys - rm -rf /home/ec2-user/.ssh/authorized_keys - shred -u /etc/ssh/*_key /etc/ssh/*_key.pub
|
将上述代码复制粘贴到创建EC2实例的 user-data 这一栏中,即可完成软件的拷贝和开机脚本的生成。
上述的代码是经过多次调测才形成的,其中有两处要注意:
1 2 3 4 5 6 7 8 9 10
| 1. aws s3 cp 命令,在最后要加上 **‘region’** 参数,否则会报fatal error: An error occurred (400) when calling the HeadObject operation: Bad Request。这一点ChatGPT没有注意到,需要提醒它,当然它学的很快。 2. ExecStart=/bin/sh -c 'sleep 5 && cp /opt/appdynamics/response.varfile.bak /opt/appdynamics/response.varfile && sed -i \"s/ENTER_PASSWORD/`curl http://169.254.169.254/latest/meta-data/instance-id`/g\" /opt/appdynamics/response.varfile && sed -i \"s/HOST_NAME/`curl http://169.254.169.254/latest/meta-data/hostname`/g\" /opt/appdynamics/response.varfile && /opt/appdynamics/platform-setup-x64-linux-23.1.1.18.sh -q -varfile /opt/appdynamics/response.varfile && systemctl daemon-reload && systemctl enable appd.console.service && systemctl start appd.console.service' 这条命令是很复杂的,一个命令一个命令串行执行,其中还包括了转义字符,如果不是ChatGPT生成,我个人很难完成这个命令。该命令顺序执行以下内容,只有前面的命令执行成功,才会继续执行下一条命令: 1. 等待5秒钟再启动,主要是让EC2的网络和其他关联服务充分就绪; 2. 将response.varfile.bak拷贝至response.varfile 3. 使用sed命令将ENTER_PASSWORD替换为instance-id,instance-id由curl命令获取,更新response.varfile 4. 使用sed命令将HOST_NAME替换为hostname,hostname由curl命令获取,更新response.varfile 5. 执行静默安装脚本,经测算安装需要大约10分钟 6. 重新加载systemd,并创建appd.console.service 7. 最后是执行appd.console.service启动Console Service
|
通过SSM连接到EC2实例(注意设置EC2的IAM Role,具备SSM和S3的访问权限),通过以下命令进行调测。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| sudo su cd /opt/appdynamics ls -al
cat /etc/security/limits.conf cat /etc/systemd/system/appd.console.service cat /etc/systemd/system/appd.console.install.service cat /etc/ssh/sshd_config | grep PermitRootLogin
ls -al /etc/ssh ls -al /root/.ssh ls -al /home/ec2-user/.ssh
cat /var/log/cloud-init-output.log
|
在AWS上制作安装镜像AMI文件
创建一个EC2实例
前提条件:VPC、公有子网均已设置好。
以下是操作步骤截图及相关说明
1、在EC2服务界面中点击Launch instance
2、填写EC2实例的Name,选择Amazon Linux
3、选择实例类型c5.xlarge,不需要Key pair,选择公有子网,并自动分配公网IP地址。
4、设置Security Group ,设置磁盘大小500G
Security Group的设置如下
5、分配IAM 角色
IAM角色具体设置如下,设置SSM权限和S3的访问权限
6、将上述cloud-init 代码输入user-data中,并点击 Launch instance
检查EC2实例的设置
1、通过SSM连接EC2实例,如果未设置SSM的权限,则不能使用该方式管理EC2
2、执行命令检查EC2的设置是否符合预期
以下是文本格式的输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| [root@ip-172-31-13-10 appdynamics] root hard nofile 65535 root soft nofile 65535 root hard nproc 8192 root soft nproc 8192
[root@ip-172-31-13-10 appdynamics] [Unit] Description=AppDynamics Enterprise Console After=network.target
[Service] Type=forking ExecStart=/opt/appdynamics/platform/platform-admin/bin/platform-admin.sh start-platform-admin ExecStop=/opt/appdynamics/platform/platform-admin/bin/platform-admin.sh stop-platform-admin User=root Restart=always
[Install] WantedBy=multi-user.target
[root@ip-172-31-13-10 appdynamics] [Unit] Description=AppDynamics Enterprise Console Installation After=network.target
[Service] Type=oneshot RemainAfterExit=no ExecStart=/bin/sh -c 'sleep 5 && cp /opt/appdynamics/response.varfile.bak /opt/appdynamics/response.varfile && sed -i \"s/ENTER_PASSWORD/`curl http://169.254.169.254/latest/meta-data/instance-id`/g\" /opt/appdynamics/response.varfile && sed -i \"s/HOST_NAME/`curl http://169.254.169.254/latest/meta-data/hostname`/g\" /opt/appdynamics/response.varfile && /opt/appdynamics/platform-setup-x64-linux-23.1.1.18.sh -q -varfile/opt/appdynamics/response.varfile && systemctl daemon-reload && systemctl enable appd.console.service && systemctl start appd.console.service'
[Install] WantedBy=multi-user.target
|
可以看出是符合预期的,执行 history -c 清除历史记录。
生成AMI镜像
1、将该EC2关机
2、确认关机后,点击制作Image
3、填入Image的参数,点击Create Image
验证AMI
使用AMI启动EC2实例
1、等待AMI状态变Available后,点击Launch instance from AMI
2、进入EC2启动的设置页面,进行必要的设置
除了user-data维持空白,其他设置可与创建AMI的EC2一致。
3、EC2创建后,转到EC2的信息页面
4、测试Enterprise Console的Web界面
大概10分钟后,可以通过以下地址访问
1 2 3
| http://ec2-69-230-211-253.cn-northwest-1.compute.amazonaws.com.cn/:9191 username: admin password: 从信息页面中拷贝instance-id,如上图为i-06b75d367808d02af
|
5、使用SSM连接EC2,检查相关服务是否正常
总结
本文整理了在AWS上制作AppDynamics的AMI镜像的过程,笔者使用了ChatGPT帮助生成自动化脚本,极大的提高了效率。
本文中的cloud-init代码已发布到Github,如下:
https://github.com/weiborao/appd-console-install-cloud-init/blob/main/appd-install-cloud-init-CN.yaml
非常感谢各位耐心的阅读,