Transitioning CentOS 7 AMIs to Rocky 8 and RHEL 8: Ensuring Stability, Security, and Future Readiness
With the end of life (EOL) of CentOS 7 in June, organizations running critical microservices on this platform are faced with an imperative need to migrate to a supported operating system. In response to this, I recently spearheaded a project to transition all microservices-based AMIs from CentOS 7 to Rocky 8 in non-production environments and RHEL 8 in production. This migration was crucial for maintaining system stability, security, and compliance while leveraging the benefits of modern operating systems. Here’s a detailed look at the migration process, the benefits, risks, and outcomes.
Why Migrate from CentOS 7?
CentOS 7 has been a reliable platform for years, but with its EOL, it no longer receives security updates or official support, posing significant risks to systems still running on it. Migrating to Rocky 8 in non-prod and RHEL 8 in prod ensures continued security updates, access to modern features, and compliance with industry standards.
The Migration Strategy
Non-Prod Environment: Rocky 8
- Why Rocky 8?: Rocky Linux is a community-supported enterprise operating system that is 100% binary-compatible with RHEL, making it an ideal choice for non-prod environments where cost efficiency and stability are crucial.
- Implementation: I used Packer to build AMIs on AWS, ensuring a smooth transition of microservices to Rocky 8. The Packer scripts were updated to reference Rocky 8 repositories, and extensive testing was performed to validate the compatibility and performance of the microservices.
Prod Environment: RHEL 8
- Why RHEL 8?: For production environments, RHEL 8 was selected due to its enterprise-grade support, security, and reliability, which are critical for maintaining uptime and service quality.
- Implementation: Similar to the non-prod environment, Packer was used to automate the creation of RHEL 8 AMIs. The migration involved rigorous testing in staging environments to ensure that all microservices performed optimally under RHEL 8.
1. Packer AMI Build Process
Packer was central to the migration process, allowing us to automate the creation of Rocky 8 and RHEL 8 AMIs. The Packer templates were updated to reference the appropriate base images and repositories.
Example Packer Template (CentOS 7 to Rocky 8):
{
"variables": {
"aws_region": "us-west-2",
"source_ami": "ami-xxxxxxxx", // CentOS 7 AMI
"ssh_username": "cloud-user"
},
"builders": [
{
"type": "amazon-ebs",
"region": "{{user `aws_region`}}",
"source_ami": "{{user `source_ami`}}",
"instance_type": "t2.micro",
"ssh_username": "{{user `ssh_username`}}",
"ami_name": "rocky8-microservice-{{timestamp}}"
}
],
"provisioners": [
{
"type": "shell",
"inline": [
"sudo yum update -y",
"sudo yum install -y epel-release",
"sudo yum install -y python3"
]
},
{
"type": "file",
"source": "scripts/",
"destination": "/tmp/scripts/"
},
{
"type": "shell",
"inline": [
"sudo /tmp/scripts/setup.sh"
]
}
]
}
2. Handling User Data and Systemd Services
One of the key requirements was to manage system services using systemd
to ensure that custom scripts and services would start correctly on system boot. The UserData
file played a crucial role in setting up these services.
Example UserData
File:
#!/bin/bash
# Create a systemd service for initializing microservices
cat <<EOF | sudo tee /etc/systemd/system/microservice-init.service
[Unit]
Description=Microservice Initialization Service
After=network.target
[Service]
ExecStart=/usr/local/bin/microservice_init.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# Enable and start the service
sudo systemctl enable microservice-init.service
sudo systemctl start microservice-init.service
Example microservice_init.sh
:
#!/bin/bash
# Initialize microservices environment
echo "Starting microservices initialization"
# Call Python scripts for setup
/usr/bin/python3 /opt/microservices/setup_env.py
# Call bash functions for system configuration
source /opt/microservices/functions.sh
setup_networking
configure_firewall
This approach ensured that all necessary initialization scripts, both in Python and Bash, were executed automatically upon system startup, thereby reducing manual intervention.
3. Linux User Management Challenges
During the migration, one of the challenges we faced was managing Linux user accounts, specifically handling the differences in default users between CentOS 7 and Rocky 8/RHEL 8. In CentOS 7, the default user was centos
, while in Rocky 8 and RHEL 8, the default user is cloud-user
. This required us to modify our user management scripts to ensure seamless operation across these environments.
#!/bin/bash
# Determine the OS and default user
if [ -f /etc/centos-release ]; then
DEFAULT_USER="centos"
elif [ -f /etc/rocky-release ] || [ -f /etc/redhat-release ]; then
DEFAULT_USER="cloud-user"
else
echo "Unsupported OS"
exit 1
fi
# Create 'appuser' if not exists and manage UID/GID conflicts
if ! id "appuser" &>/dev/null; then
sudo useradd -m -s /bin/bash appuser
else
echo "User appuser already exists"
fi
# Adjust permissions based on the default user
if [ "$DEFAULT_USER" == "centos" ]; then
sudo usermod -u 1002 -g 1002 appuser # Example UID/GID for centos-based systems
else
sudo usermod -u 1001 -g 1001 appuser # Example UID/GID for rocky/redhat-based systems
fi
# Ensure appuser has necessary permissions
sudo usermod -aG $DEFAULT_USER appuser
4. Migrating Python 2 Code to Python 3
Since CentOS 7 primarily used Python 2, the migration required updating legacy Python scripts to be compatible with Python 3. This included modifying syntax and handling differences in library functions.
Example Python 2 to Python 3 Migration:
Original Python 2 Script:
#!/usr/bin/env python
import urllib2
response = urllib2.urlopen('http://example.com')
print response.read()
Updated Python 3 Script:
#!/usr/bin/env python3
import urllib.request
response = urllib.request.urlopen('http://example.com')
print(response.read().decode('utf-8'))
This was critical, especially for scripts that were integral to the microservices’ operations.
5. Conditional Logic for Multi-OS Compatibility
We implemented conditional logic in scripts to ensure they would work across CentOS 7, Rocky 8, and RHEL 8 during the transition period. This was necessary for environments where systems were gradually being migrated.
Example Conditional Script:
#!/bin/bash
if [ -f /etc/centos-release ]; then
OS="CentOS"
elif [ -f /etc/rocky-release ]; then
OS="Rocky"
elif [ -f /etc/redhat-release ]; then
OS="RHEL"
else
OS="Unknown"
fi
echo "Operating System detected: $OS"
case $OS in
"CentOS")
sudo yum install -y package-for-centos
;;
"Rocky"|"RHEL")
sudo yum install -y package-for-rocky-rhel
;;
*)
echo "Unsupported OS"
exit 1
;;
esac
Risks and Outcomes
Risks:
- Compatibility Issues: There was a significant risk of compatibility issues with existing microservices due to differences in system libraries and Python versions.
- User Management Conflicts: Differences in user management across OS versions could lead to permission issues and system failures.
- Downtime During Transition: The migration process posed a risk of service downtime, which we mitigated by carefully scheduling maintenance windows and implementing rollback strategies.
Outcomes:
- Improved Security and Compliance: The migration to Rocky 8 and RHEL 8 brought enhanced security, ensuring compliance with industry standards.
- Optimized Performance: The microservices performed better on Rocky 8/RHEL 8, benefiting from updated kernels and system libraries.
- Future-Proofing: The migration has positioned our infrastructure to be scalable and ready for future technological advancements.
Conclusion
The migration from CentOS 7 to Rocky 8 in non-prod and RHEL 8 in prod was not just about addressing the EOL of CentOS 7 but also an opportunity to enhance our infrastructure's security, performance, and scalability. By leveraging Packer for AMI builds and addressing challenges like user management, Python 2 to 3 migration, and conditional scripting, we ensured a smooth and successful transition. This migration has future-proofed our environment, allowing us to continue delivering high-quality services to our users.
Comments
Post a Comment