RHEL-Bereitstellungen installieren und automatisieren

Red Hat Enterprise LinuxRed Hat Enterprise LinuxBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab lernen Sie die Grundlagen der Bereitstellung und Automatisierung von Red Hat Enterprise Linux (RHEL) 9 Containern mit Docker. Moderne Cloud-native Bereitstellungen verlassen sich zunehmend auf containerisierte RHEL-Umgebungen anstelle von traditionellen virtuellen Maschinen. Sie beginnen mit der Untersuchung der Universal Base Images (UBI) von Red Hat, die RHEL-Umgebungen in Container-Format in Enterprise-Qualität bereitstellen.

Sie werden untersuchen, wie traditionelle Kickstart-Konzepte in die Container-Automatisierung übersetzt werden, benutzerdefinierte Dockerfiles erstellen, die Installationskonfigurationen widerspiegeln, und automatisierte Bereitstellungsskripte erstellen. Am Ende dieses Labs werden Sie verstehen, wie Sie RHEL-Container effizient bereitstellen und den Prozess für konsistente, wiederholbare Bereitstellungen in modernen Cloud-Umgebungen automatisieren können.

Erkunden von Red Hat Universal Base Images (UBI)

In diesem Schritt werden Sie die Universal Base Images (UBI) von Red Hat erkunden, die Container-Images in Enterprise-Qualität auf Basis von RHEL sind. Im Gegensatz zu traditionellen RHEL-Installationen, die vollständige virtuelle Maschinen erfordern, bieten UBI-Images RHEL-Umgebungen in leichten, portablen Containern. Diese Images sind frei weiterverteilbar und für moderne Cloud-native Anwendungen konzipiert.

Red Hat bietet verschiedene UBI-Varianten an, die für unterschiedliche Anwendungsfälle optimiert sind. Das Image redhat/ubi9 bietet eine vollständige RHEL-basierte Container-Umgebung mit dem Paketmanager dnf, was es für Anwendungen geeignet macht, die Softwareinstallation und Systemautomatisierung erfordern.

Zuerst wollen wir die Red Hat Container-Konfigurationsvorlage untersuchen, die für dieses Lab vorbereitet wurde. Diese Datei zeigt, wie traditionelle Kickstart-Konzepte in Container-Umgebungen übersetzt werden.

sudo cat /etc/labex/rhel-container-config.cfg

Sie sehen eine Ausgabe, die eine Dockerfile-ähnliche Konfiguration zeigt, die traditionelle Installationskonzepte widerspiegelt:

## RHEL Container Configuration Template
## Based on traditional Kickstart concepts adapted for containers

## Base image specification
FROM redhat/ubi9

## System locale and timezone
ENV LANG=en_US.UTF-8
ENV TZ=America/New_York

## User configuration
ENV CONTAINER_USER=labex
ENV ROOT_PASSWORD=redhat

## Package installation
## Packages: httpd, curl (container-appropriate equivalents)
RUN dnf install -y --allowerasing httpd curl && \
    dnf clean all

## Service configuration
EXPOSE 80

## Startup command
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

Lassen Sie uns nun die verfügbaren Red Hat UBI-Images erkunden. Überprüfen Sie zuerst, ob Docker läuft und zugänglich ist:

docker --version

Laden Sie das Red Hat UBI 9 Image herunter, das eine vollständige RHEL-basierte Container-Umgebung bereitstellt:

docker pull redhat/ubi9

Sie sollten eine ähnliche Ausgabe sehen wie:

Using default tag: latest
latest: Pulling from redhat/ubi9
Digest: sha256:...
Status: Downloaded newer image for redhat/ubi9:latest
docker.io/redhat/ubi9:latest

Listen Sie die heruntergeladenen Images auf, um zu bestätigen, dass der Pull erfolgreich war:

docker images redhat/ubi9

Die Ausgabe zeigt Details über das Image:

REPOSITORY      TAG       IMAGE ID       CREATED      SIZE
redhat/ubi9     latest    b1c2d3e4f5g6   5 days ago   216MB

Lassen Sie uns nun einen Basis-Container ausführen, um die RHEL-Umgebung zu erkunden:

docker run -it --rm redhat/ubi9 /bin/bash

Erkunden Sie innerhalb des Containers die RHEL-Umgebung, indem Sie die Betriebssystemversion überprüfen:

cat /etc/redhat-release

Sie sollten so etwas sehen wie:

Red Hat Enterprise Linux release 9.6 (Plow)

Überprüfen Sie den verfügbaren Paketmanager:

dnf --version

Verlassen Sie den Container, indem Sie Folgendes eingeben:

exit

Kopieren Sie die Vorlagenkonfiguration in Ihr Projektverzeichnis zur Anpassung:

sudo cp /etc/labex/rhel-container-config.cfg ~/project/rhel-container.dockerfile
sudo chown labex:labex ~/project/rhel-container.dockerfile

Überprüfen Sie, ob die Datei erfolgreich kopiert wurde:

ls -l ~/project/rhel-container.dockerfile

Sie haben nun erfolgreich Red Hat UBI-Images erkundet und sind bereit, im nächsten Schritt benutzerdefinierte Container-Konfigurationen zu erstellen.

Erstellen einer benutzerdefinierten RHEL-Containerkonfiguration

In diesem Schritt erstellen Sie ein benutzerdefiniertes Dockerfile basierend auf dem Red Hat UBI-Image. Dieser Prozess spiegelt wider, wie Sie eine Kickstart-Datei für automatisierte Installationen anpassen würden, jedoch angepasst für Container-Umgebungen. Das Dockerfile dient als Automatisierungsvorlage für die Erstellung konsistenter RHEL-Container-Bereitstellungen.

Stellen Sie zunächst sicher, dass Sie sich in Ihrem Projektverzeichnis befinden:

cd ~/project

Erstellen Sie ein neues, spezifischeres Dockerfile für unsere automatisierte RHEL-Container-Bereitstellung:

cp rhel-container.dockerfile rhel9-automated.dockerfile

Überprüfen Sie, ob beide Dateien existieren:

ls -l *.dockerfile

Sie sollten beide Dateien sehen:

-rw-r--r--. 1 labex labex 423 Jul 22 10:30 rhel-container.dockerfile
-rw-r--r--. 1 labex labex 423 Jul 22 10:35 rhel9-automated.dockerfile

Öffnen Sie nun das neue Dockerfile, um seine Struktur vor der Anpassung zu untersuchen:

nano rhel9-automated.dockerfile

In der Datei sehen Sie das Container-Äquivalent von Kickstart-Direktiven:

  • FROM-Direktive: Gibt das Basis-RHEL-Image an (entspricht dem Installationsmedium)
  • ENV-Direktiven: Setzen Umgebungsvariablen (entspricht der Systemkonfiguration)
  • RUN-Direktiven: Führen Befehle während des Image-Builds aus (entspricht der Paketinstallation)
  • EXPOSE und CMD: Konfigurieren Dienste und Start (entspricht der Dienstkonfiguration)

Verlassen Sie vorerst einfach den Editor, indem Sie Ctrl+X drücken, um mit dem Anpassungsschritt fortzufahren.

Das Verständnis dieser Struktur bereitet Sie auf den nächsten Schritt vor, in dem Sie die Container-Konfiguration anpassen, um spezifische Bereitstellungsanforderungen zu erfüllen, genau wie Sie eine Kickstart-Datei für automatisierte VM-Installationen anpassen würden.

Anpassen der Container-Konfiguration für die automatisierte Bereitstellung

In diesem Schritt ersetzen Sie den Inhalt der rhel9-automated.dockerfile durch eine benutzerdefinierte Konfiguration für die automatisierte RHEL-Container-Bereitstellung. Dieser Prozess ähnelt der Anpassung einer Kickstart-Datei, verwendet aber den deklarativen Ansatz von Docker, um die Container-Umgebung und -Dienste zu definieren.

Stellen Sie zunächst sicher, dass Sie sich im Projektverzeichnis befinden:

cd ~/project

Erstellen Sie nun das vollständige benutzerdefinierte Dockerfile, indem Sie den gesamten Inhalt von rhel9-automated.dockerfile ersetzen:

cat > rhel9-automated.dockerfile << 'EOF'
## RHEL 9 Automated Container Deployment
## Based on Red Hat Universal Base Image 9
FROM redhat/ubi9:latest

## Container metadata
LABEL maintainer="LabEx Admin"
LABEL description="Automated RHEL 9 container with web services"
LABEL version="1.0"

## System locale and timezone configuration
ENV LANG=en_US.UTF-8
ENV TZ=America/New_York
ENV CONTAINER_USER=labex
ENV CONTAINER_UID=1001

## Package installation and system configuration
RUN dnf update -y \
  && dnf install -y --allowerasing \
    httpd \
    curl \
    tar \
    gzip \
  && dnf clean all \
  && rm -rf /var/cache/dnf

## Create non-root user for security
RUN useradd -u ${CONTAINER_UID} -m -s /bin/bash ${CONTAINER_USER} \
  && echo "${CONTAINER_USER}:labex" | chpasswd

## Configure Apache for container environment
RUN sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf \
  && chown -R ${CONTAINER_USER}:${CONTAINER_USER} /var/log/httpd /var/run/httpd

## Create startup script
RUN echo '#!/bin/bash' > /start.sh \
  && echo 'echo "RHEL Container started on $(date)" > /var/www/html/index.html' >> /start.sh \
  && echo 'echo "<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>" >> /var/www/html/index.html' >> /start.sh \
  && echo 'exec /usr/sbin/httpd -D FOREGROUND' >> /start.sh \
  && chmod +x /start.sh

## Switch to non-root user
USER ${CONTAINER_USER}

## Expose port and define startup
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/ || exit 1

CMD ["/start.sh"]
EOF

Lassen Sie uns nun die Struktur dieses angepassten Dockerfiles untersuchen und verstehen, wie jeder Abschnitt demselben Zweck wie verschiedene Teile einer Kickstart-Konfiguration dient:

1. Basis-Image und Metadaten-Abschnitt:

## RHEL 9 Automated Container Deployment
## Based on Red Hat Universal Base Image 9
FROM redhat/ubi9:latest

## Container metadata
LABEL maintainer="LabEx Admin"
LABEL description="Automated RHEL 9 container with web services"
LABEL version="1.0"

Dieser Abschnitt entspricht der Angabe des Installationsmediums und grundlegender Systeminformationen in einer Kickstart-Datei. Die FROM-Direktive gibt unser Basis-RHEL-Image an, während LABEL-Direktiven Metadaten über den Container bereitstellen.

2. Umgebungskonfiguration:

## System locale and timezone configuration
ENV LANG=en_US.UTF-8
ENV TZ=America/New_York
ENV CONTAINER_USER=labex
ENV CONTAINER_UID=1001

Dies entspricht den Direktiven timezone und lang in Kickstart-Dateien. Wir legen das System-Locale, die Zeitzone fest und definieren Variablen für die Benutzererstellung.

3. Paketinstallation:

## Package installation and system configuration
RUN dnf update -y \
  && dnf install -y --allowerasing \
    httpd \
    curl \
    tar \
    gzip \
  && dnf clean all \
  && rm -rf /var/cache/dnf

Dieser Abschnitt führt dieselbe Funktion wie der Abschnitt %packages in Kickstart aus. Wir aktualisieren das System, installieren die erforderlichen Pakete mit --allowerasing, um Konflikte zu behandeln, und bereinigen die Paket-Caches, um die Image-Größe zu reduzieren.

4. Benutzer- und Sicherheitskonfiguration:

## Create non-root user for security
RUN useradd -u ${CONTAINER_UID} -m -s /bin/bash ${CONTAINER_USER} \
  && echo "${CONTAINER_USER}:labex" | chpasswd

## Configure Apache for container environment
RUN sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf \
  && chown -R ${CONTAINER_USER}:${CONTAINER_USER} /var/log/httpd /var/run/httpd

Dies spiegelt die user-Direktive und die Konfiguration nach der Installation in Kickstart wider. Wir erstellen einen Nicht-Root-Benutzer für die Sicherheit und konfigurieren Apache so, dass er auf Port 8080 ausgeführt wird (geeignet für Container-Umgebungen).

5. Startkonfiguration:

## Create startup script
RUN echo '#!/bin/bash' > /start.sh \
  && echo 'echo "RHEL Container started on $(date)" > /var/www/html/index.html' >> /start.sh \
  && echo 'echo "<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>" >> /var/www/html/index.html' >> /start.sh \
  && echo 'exec /usr/sbin/httpd -D FOREGROUND' >> /start.sh \
  && chmod +x /start.sh

## Switch to non-root user
USER ${CONTAINER_USER}

## Expose port and define startup
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/ || exit 1

CMD ["/start.sh"]

Dieser letzte Abschnitt entspricht dem Abschnitt %post und der Dienstkonfiguration in Kickstart. Wir erstellen ein Startskript, wechseln zum Nicht-Root-Benutzer, stellen den Webdienst-Port bereit, definieren Health Checks und geben den Startbefehl des Containers an.

Überprüfen Sie, ob das neue Dockerfile korrekt erstellt wurde:

cat rhel9-automated.dockerfile

Sie sollten den vollständigen Dockerfile-Inhalt sehen, der zeigt, wie traditionelle Kickstart-Automatisierungskonzepte in moderne containerbasierte RHEL-Bereitstellungen übersetzt werden.

Validieren der Container-Konfiguration und Erstellen des Images

In diesem Schritt validieren Sie Ihr benutzerdefiniertes Dockerfile und erstellen das RHEL-Container-Image. Dieser Prozess ähnelt der Validierung einer Kickstart-Datei mit ksvalidator, verwendet aber die in Docker integrierte Validierung während des Build-Prozesses. Docker überprüft die Syntax und versucht, jede Anweisung auszuführen, wodurch sofortiges Feedback zu allen Problemen gegeben wird.

Stellen Sie zunächst sicher, dass Sie sich in dem Projektverzeichnis befinden, in dem sich Ihr Dockerfile befindet:

cd ~/project

Bevor Sie mit dem Erstellen beginnen, führen wir eine grundlegende Syntaxprüfung durch, indem wir die Dockerfile-Struktur untersuchen. Docker bietet eine Möglichkeit, die grundlegende Syntax ohne Erstellung zu validieren:

docker build --no-cache --progress=plain -f rhel9-automated.dockerfile -t rhel9-test:validation . --target ""

Die effektivste Validierung ist jedoch die tatsächliche Erstellung des Images. Wenn Syntaxfehler oder Probleme mit den Befehlen vorliegen, meldet Docker diese während des Build-Prozesses. Beachten Sie, dass wir das Flag --allowerasing mit dnf install verwenden, um Paketkonflikte zwischen curl und curl-minimal zu behandeln, die im Basis-UBI9-Image vorhanden sind:

docker build -t rhel9-automated:latest -f rhel9-automated.dockerfile .

Sie sollten eine Ausgabe sehen, die jeden Schritt des Build-Prozesses zeigt:

[+] Building 45.2s (12/12) FINISHED
 => [internal] load build definition from rhel9-automated.dockerfile
 => => transferring dockerfile: 1.23kB
 => [internal] load .dockerignore
 => => transferring context: 2B
 => [internal] load metadata for docker.io/redhat/ubi9:latest
 => [1/8] FROM docker.io/redhat/ubi9:latest@sha256:...
 => [2/8] RUN dnf update -y &&     dnf install -y --allowerasing         httpd         curl         tar         gzip &&     dnf clean all &&     rm -rf /var/cache/dnf
 => [3/8] RUN useradd -u 1001 -m -s /bin/bash labex &&     echo "labex:labex" | chpasswd
 => [4/8] RUN sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf &&     chown -R labex:labex /var/log/httpd /var/run/httpd
 => [5/8] RUN echo '#!/bin/bash' > /start.sh &&     echo 'echo "RHEL Container started on $(date)" > /var/www/html/index.html' >> /start.sh &&     echo 'echo "<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>" >> /var/www/html/index.html' >> /start.sh &&     echo 'exec /usr/sbin/httpd -D FOREGROUND' >> /start.sh &&     chmod +x /start.sh
 => [6/8] USER labex
 => exporting to image
 => => exporting layers
 => => writing image sha256:a1b2c3d4e5f6...
 => => naming to docker.io/library/rhel9-automated:latest

Wenn der Build erfolgreich abgeschlossen wird, bedeutet dies, dass Ihre Dockerfile-Syntax korrekt ist und alle Befehle ordnungsgemäß ausgeführt wurden. Während des Build-Prozesses werden möglicherweise einige Warnmeldungen zu den Ländereinstellungen und der Abonnementverwaltung angezeigt – diese sind für UBI-Container normal und haben keine Auswirkungen auf die Funktionalität.

Überprüfen Sie, ob das Image erstellt wurde:

docker images rhel9-automated

Sie sollten Ihr neu erstelltes Image sehen:

REPOSITORY       TAG       IMAGE ID       CREATED          SIZE
rhel9-automated  latest    a1b2c3d4e5f6   2 minutes ago    280MB

Testen wir nun den Container, um sicherzustellen, dass er wie erwartet funktioniert. Führen Sie den Container im Detached-Modus aus:

docker run -d --name rhel9-test -p 8080:8080 rhel9-automated:latest

Überprüfen Sie, ob der Container ausgeführt wird:

docker ps

Sie sollten Ihren Container in der Liste sehen:

CONTAINER ID   IMAGE                     COMMAND      CREATED         STATUS         PORTS                    NAMES
a1b2c3d4e5f6   rhel9-automated:latest   "/start.sh"  30 seconds ago  Up 30 seconds  0.0.0.0:8080->8080/tcp   rhel9-test

Testen Sie den Webdienst, indem Sie eine Anfrage an den Container senden:

curl http://localhost:8080

Sie sollten die HTML-Ausgabe von Ihrem automatisierten RHEL-Container sehen:

RHEL Container started on Wed Jul 22 14:30:15 UTC 2024
<h1>RHEL 9 Container</h1><p>Deployed via automated configuration</p>

Zum Schluss bereinigen Sie, indem Sie den Testcontainer stoppen und entfernen:

docker stop rhel9-test
docker rm rhel9-test

Ihre RHEL-Container-Konfiguration wurde erfolgreich validiert und getestet, was die automatisierten Bereitstellungsfunktionen demonstriert.

Erstellen eines automatisierten Bereitstellungsskripts

In diesem Schritt erstellen Sie ein Automatisierungsskript, das demonstriert, wie RHEL-Container konsistent und wiederholt bereitgestellt werden können. Dieses Skript dient dem gleichen Zweck wie die Verwendung von Kickstart-Dateien für die VM-Automatisierung, ist aber für containerisierte RHEL-Bereitstellungen angepasst. Das Skript übernimmt die Image-Erstellung, die Container-Bereitstellung und grundlegende Integritätsprüfungen.

Stellen Sie zunächst sicher, dass Sie sich in Ihrem Projektverzeichnis befinden:

cd ~/project

Erstellen Sie ein Bereitstellungsautomatisierungsskript, das die Automatisierungsfunktionen nachahmt, die Sie mit Kickstart und virt-install erreichen würden:

nano deploy-rhel-container.sh

Fügen Sie den folgenden Inhalt hinzu, um ein umfassendes Bereitstellungsskript zu erstellen:

#!/bin/bash

## RHEL Container Automated Deployment Script
## This script demonstrates container-based RHEL deployment automation
## Similar to Kickstart automation for VMs, but for containers

set -e ## Exit on any error

## Configuration variables
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"

## Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## No Color

## Function to print colored output
print_status() {
  echo -e "${BLUE}[INFO]${NC} $1"
}

print_success() {
  echo -e "${GREEN}[SUCCESS]${NC} $1"
}

print_warning() {
  echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
  echo -e "${RED}[ERROR]${NC} $1"
}

## Function to check if Docker is running
check_docker() {
  print_status "Checking Docker availability..."
  if ! docker info > /dev/null 2>&1; then
    print_error "Docker is not running or not accessible"
    exit 1
  fi
  print_success "Docker is available"
}

## Function to build the image
build_image() {
  print_status "Building RHEL container image..."
  if [ ! -f "$DOCKERFILE" ]; then
    print_error "Dockerfile '$DOCKERFILE' not found"
    exit 1
  fi

  docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
  print_success "Image '${IMAGE_NAME}:${IMAGE_TAG}' built successfully"
}

## Function to stop and remove existing container
cleanup_existing() {
  print_status "Checking for existing container..."
  if docker ps -a | grep -q "$CONTAINER_NAME"; then
    print_warning "Stopping and removing existing container '$CONTAINER_NAME'"
    docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
    docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
  fi
}

## Function to deploy the container
deploy_container() {
  print_status "Deploying RHEL container..."
  docker run -d \
    --name "$CONTAINER_NAME" \
    -p "${HOST_PORT}:${CONTAINER_PORT}" \
    --restart unless-stopped \
    "${IMAGE_NAME}:${IMAGE_TAG}"

  print_success "Container '$CONTAINER_NAME' deployed successfully"
}

## Function to verify deployment
verify_deployment() {
  print_status "Verifying container deployment..."

  ## Wait for container to start
  sleep 5

  ## Check if container is running
  if ! docker ps | grep -q "$CONTAINER_NAME"; then
    print_error "Container is not running"
    docker logs "$CONTAINER_NAME"
    exit 1
  fi

  ## Check if web service is responding
  print_status "Testing web service..."
  for i in {1..10}; do
    if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
      print_success "Web service is responding"
      break
    fi
    if [ $i -eq 10 ]; then
      print_error "Web service is not responding after 10 attempts"
      exit 1
    fi
    sleep 2
  done
}

## Function to display deployment information
show_deployment_info() {
  print_success "=== RHEL Container Deployment Complete ==="
  echo "Container Name: $CONTAINER_NAME"
  echo "Image: ${IMAGE_NAME}:${IMAGE_TAG}"
  echo "Port Mapping: ${HOST_PORT}:${CONTAINER_PORT}"
  echo "Access URL: http://localhost:${HOST_PORT}"
  echo ""
  print_status "Container Status:"
  docker ps | grep "$CONTAINER_NAME"
  echo ""
  print_status "Sample Content:"
  curl -s "http://localhost:${HOST_PORT}" | head -2
}

## Main deployment process
main() {
  echo "=== RHEL Container Automated Deployment ==="
  echo "This script automates RHEL container deployment"
  echo "Similar to Kickstart automation for traditional installations"
  echo ""

  check_docker
  build_image
  cleanup_existing
  deploy_container
  verify_deployment
  show_deployment_info

  print_success "Automated RHEL container deployment completed successfully!"
}

## Handle script arguments
case "${1:-deploy}" in
  "deploy" | "")
    main
    ;;
  "cleanup")
    print_status "Cleaning up deployment..."
    cleanup_existing
    docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
    print_success "Cleanup completed"
    ;;
  "status")
    docker ps | grep "$CONTAINER_NAME" || print_warning "Container not running"
    ;;
  *)
    echo "Usage: $0 [deploy|cleanup|status]"
    echo "  deploy  - Build and deploy RHEL container (default)"
    echo "  cleanup - Stop container and remove image"
    echo "  status  - Show container status"
    exit 1
    ;;
esac

Speichern Sie die Datei und beenden Sie nano (Ctrl+X, dann Y, dann Enter).

Verstehen der Struktur des Bereitstellungsskripts

Bevor Sie das Skript ausführen, wollen wir verstehen, wie dieses Automatisierungsskript funktioniert. Dieser Abschnitt bietet eine detaillierte Erklärung jeder Komponente, wodurch es für Anfänger einfacher wird, Shell-Skripting und Container-Automatisierungskonzepte zu verstehen.

Skript-Header und Fehlerbehandlung

#!/bin/bash
set -e ## Exit on any error
  • #!/bin/bash: Dies wird als "Shebang" bezeichnet – es weist das System an, die Bash-Shell zum Ausführen dieses Skripts zu verwenden
  • set -e: Dadurch wird das Skript sofort beendet, wenn ein Befehl fehlschlägt, wodurch sichergestellt wird, dass das Skript beim ersten Fehler anhält, anstatt mit einem potenziell fehlerhaften Zustand fortzufahren

Konfigurationsvariablen

## Configuration variables
IMAGE_NAME="rhel9-automated"
IMAGE_TAG="latest"
CONTAINER_NAME="rhel9-production"
HOST_PORT="8080"
CONTAINER_PORT="8080"
DOCKERFILE="rhel9-automated.dockerfile"

Diese Variablen definieren alle Schlüsselparameter für unsere Bereitstellung. Indem wir sie oben platzieren, können wir die Bereitstellungskonfiguration einfach ändern, ohne die Skriptlogik zu ändern. Dies ähnelt der Verwendung von Konfigurationsparametern in Kickstart-Dateien.

Benutzerfreundliches Ausgabesystem

## Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' ## No Color

## Function to print colored output
print_status() {
  echo -e "${BLUE}[INFO]${NC} $1"
}

Dies erstellt ein professionelles Protokollierungssystem mit farbiger Ausgabe:

  • \033[0;31m: ANSI-Escape-Codes für Farben (31 = Rot, 32 = Grün usw.)
  • echo -e: Das Flag -e aktiviert die Interpretation von Backslash-Escapes für Farben
  • $1: Bezieht sich auf das erste Argument, das an die Funktion übergeben wird

Kernfunktionen der Bereitstellung

1. Docker-Umgebungsprüfung

check_docker() {
  print_status "Checking Docker availability..."
  if ! docker info > /dev/null 2>&1; then
    print_error "Docker is not running or not accessible"
    exit 1
  fi
  print_success "Docker is available"
}
  • docker info > /dev/null 2>&1: Führt docker info aus und leitet sowohl die Ausgabe (>) als auch die Fehler (2>&1) an /dev/null um (verwirft sie)
  • !: Negiert das Ergebnis – wenn docker info fehlschlägt (gibt einen Wert ungleich Null zurück), wird die Bedingung wahr
  • Dies entspricht der Überprüfung, ob Virtualisierung in traditionellen VM-Bereitstellungen verfügbar ist

2. Image-Erstellungsfunktion

build_image() {
  print_status "Building RHEL container image..."
  if [ ! -f "$DOCKERFILE" ]; then
    print_error "Dockerfile '$DOCKERFILE' not found"
    exit 1
  fi

  docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE" .
  print_success "Image '${IMAGE_NAME}:${IMAGE_TAG}' built successfully"
}
  • [ ! -f "$DOCKERFILE" ]: Testet, ob das Dockerfile NICHT existiert (! negiert, -f testet auf Dateiexistenz)
  • docker build -t: Erstellt ein Container-Image mit einem Tag (Name:Version)
  • Dies ersetzt den traditionellen Installationsprozess von ISO-Medien

3. Bereinigungsfunktion

cleanup_existing() {
  print_status "Checking for existing container..."
  if docker ps -a | grep -q "$CONTAINER_NAME"; then
    print_warning "Stopping and removing existing container '$CONTAINER_NAME'"
    docker stop "$CONTAINER_NAME" > /dev/null 2>&1 || true
    docker rm "$CONTAINER_NAME" > /dev/null 2>&1 || true
  fi
}
  • docker ps -a | grep -q: Listet alle Container auf und sucht stillschweigend nach unserem Containernamen
  • || true: Stellt sicher, dass der Befehl immer erfolgreich ist (gibt 0 zurück), auch wenn der Container nicht existiert
  • Dies verhindert Konflikte mit bestehenden Bereitstellungen

4. Container-Bereitstellung

deploy_container() {
  print_status "Deploying RHEL container..."
  docker run -d \
    --name "$CONTAINER_NAME" \
    -p "${HOST_PORT}:${CONTAINER_PORT}" \
    --restart unless-stopped \
    "${IMAGE_NAME}:${IMAGE_TAG}"

  print_success "Container '$CONTAINER_NAME' deployed successfully"
}
  • -d: Führt den Container im Detached-Modus aus (Hintergrund)
  • -p "${HOST_PORT}:${CONTAINER_PORT}": Ordnet den Host-Port dem Container-Port zu
  • --restart unless-stopped: Startet den Container automatisch neu, wenn er stoppt (außer bei manuellen Stopps)
  • \: Zeilenfortsetzungszeichen für mehrzeilige Befehle

5. Integritätsprüfung

verify_deployment() {
  print_status "Verifying container deployment..."

  ## Wait for container to start
  sleep 5

  ## Check if container is running
  if ! docker ps | grep -q "$CONTAINER_NAME"; then
    print_error "Container is not running"
    docker logs "$CONTAINER_NAME"
    exit 1
  fi

  ## Check if web service is responding
  print_status "Testing web service..."
  for i in {1..10}; do
    if curl -s "http://localhost:${HOST_PORT}" > /dev/null; then
      print_success "Web service is responding"
      break
    fi
    if [ $i -eq 10 ]; then
      print_error "Web service is not responding after 10 attempts"
      exit 1
    fi
    sleep 2
  done
}
  • {1..10}: Bash-Brace-Expansion – erstellt die Sequenz 1, 2, 3... 10
  • curl -s: Silent-Modus-HTTP-Anfrage
  • break: Beendet die Schleife frühzeitig, wenn der Dienst antwortet
  • Dies implementiert einen Wiederholungsmechanismus mit Timeout

Befehlszeilenschnittstelle

case "${1:-deploy}" in
  "deploy" | "")
    main
    ;;
  "cleanup")
    print_status "Cleaning up deployment..."
    cleanup_existing
    docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2> /dev/null || true
    print_success "Cleanup completed"
    ;;
  "status")
    docker ps | grep "$CONTAINER_NAME" || print_warning "Container not running"
    ;;
  *)
    echo "Usage: $0 [deploy|cleanup|status]"
    echo "  deploy  - Build and deploy RHEL container (default)"
    echo "  cleanup - Stop container and remove image"
    echo "  status  - Show container status"
    exit 1
    ;;
esac
  • ${1:-deploy}: Parametererweiterung – verwendet $1 (erstes Argument) oder "deploy" als Standard
  • case-Anweisung: Ähnlich wie switch/case in anderen Sprachen
  • ;;: Beendet jeden Case-Zweig
  • $0: Bezieht sich auf den Skriptnamen selbst

Dies erstellt ein vielseitiges Skript, das für mehrere Operationen verwendet werden kann, ähnlich wie Systemadministratoren verschiedene Tools für Bereitstellung, Wartung und Überwachung verwenden.

Machen Sie das Skript ausführbar:

chmod +x deploy-rhel-container.sh

Führen Sie nun das automatisierte Bereitstellungsskript aus, um den vollständigen Automatisierungsprozess zu sehen:

./deploy-rhel-container.sh

Sie sollten eine Ausgabe sehen, die den vollständigen Bereitstellungsprozess zeigt:

=== RHEL Container Automated Deployment ===
This script automates RHEL container deployment
Similar to Kickstart automation for traditional installations

[INFO] Checking Docker availability...
[SUCCESS] Docker is available
[INFO] Building RHEL container image...
[SUCCESS] Image 'rhel9-automated:latest' built successfully
[INFO] Checking for existing container...
[INFO] Deploying RHEL container...
[SUCCESS] Container 'rhel9-production' deployed successfully
[INFO] Verifying container deployment...
[INFO] Testing web service...
[SUCCESS] Web service is responding
[SUCCESS] === RHEL Container Deployment Complete ===
Container Name: rhel9-production
Image: rhel9-automated:latest
Port Mapping: 8080:8080
Access URL: http://localhost:8080

Testen Sie die verschiedenen Skriptoptionen:

./deploy-rhel-container.sh status

Skriptausführungs-Walkthrough

Wenn Sie das Skript ausführen, führt es automatisch die folgende Sequenz aus:

1. Umgebungsvalidierungsphase

Das Skript prüft zuerst, ob Docker verfügbar und zugänglich ist. Dies ist entscheidend, da die Container-Bereitstellung eine funktionierende Docker-Umgebung erfordert, ähnlich wie die VM-Bereitstellung einen funktionierenden Hypervisor erfordert.

2. Image-Erstellungsphase

Das Skript erstellt ein neues Container-Image aus Ihrem Dockerfile. Dieser Prozess:

  • Liest die rhel9-automated.dockerfile
  • Lädt das Basis-UBI9-Image herunter, falls es noch nicht vorhanden ist
  • Führt jede Anweisung im Dockerfile aus
  • Erstellt ein neues Image, das als rhel9-automated:latest getaggt ist

3. Bereinigungsphase

Vor der Bereitstellung prüft das Skript, ob ein vorhandener Container mit demselben Namen vorhanden ist, und entfernt ihn. Dies gewährleistet eine saubere Bereitstellung ohne Namenskonflikte.

4. Bereitstellungsphase

Das Skript erstellt und startet den neuen Container mit:

  • Detached-Modus: Container wird im Hintergrund ausgeführt
  • Port-Mapping: Host-Port 8080 wird dem Container-Port 8080 zugeordnet
  • Restart-Richtlinie: Container wird automatisch neu gestartet, wenn er unerwartet stoppt
  • Benannter Container: Einfache Identifizierung und Verwaltung

5. Verifizierungsphase

Das Skript führt Integritätsprüfungen durch, um eine erfolgreiche Bereitstellung sicherzustellen:

  • Container-Statusprüfung: Überprüft, ob der Container ausgeführt wird
  • Dienstverfügbarkeitsprüfung: Testet die HTTP-Dienstantwort
  • Wiederholungsmechanismus: Versucht es bis zu 10 Mal mit Intervallen von 2 Sekunden
  • Automatische Fehlererkennung: Beendet sich mit einem Fehler, wenn die Überprüfung fehlschlägt

6. Informationsanzeigephase

Schließlich zeigt das Skript umfassende Bereitstellungsinformationen an, einschließlich Containerdetails, Zugriffs-URLs und Beispielinhalten.

Praktische Verwendungsbeispiele

Sie können dieses Skript auf verschiedene Arten verwenden:

Normale Bereitstellung:

./deploy-rhel-container.sh
## or explicitly
./deploy-rhel-container.sh deploy

Bereitstellungsstatus prüfen:

./deploy-rhel-container.sh status

Ressourcen bereinigen:

./deploy-rhel-container.sh cleanup

Skripthilfe anzeigen:

./deploy-rhel-container.sh help

Vorteile gegenüber herkömmlichen Methoden

Dieser Automatisierungsansatz bietet mehrere Vorteile gegenüber herkömmlichen Kickstart + VM-Bereitstellungen:

  1. Geschwindigkeit: Der Container-Start ist typischerweise 10-100x schneller als der VM-Start
  2. Ressourceneffizienz: Container teilen sich den Host-Kernel und verwenden weniger Speicher und CPU
  3. Konsistenz: Derselbe Container wird in verschiedenen Umgebungen identisch ausgeführt
  4. Skalierbarkeit: Einfach, mehrere Instanzen zu erstellen oder horizontal zu skalieren
  5. Portabilität: Kann auf jedem System mit installiertem Docker ausgeführt werden
  6. Versionskontrolle: Container-Images können versioniert und in Registries gespeichert werden

Dieses Automatisierungsskript demonstriert, wie moderne containerbasierte RHEL-Bereitstellungen den gleichen Grad an Automatisierung und Konsistenz erreichen können wie herkömmliche Kickstart-basierte VM-Installationen, jedoch mit den zusätzlichen Vorteilen der Containerisierung, wie z. B. schnellerer Bereitstellung, besserer Ressourcenauslastung und einfacherer Skalierung in modernen Cloud-Umgebungen.

Zusammenfassung

In diesem Lab haben Sie den modernen Ansatz zur Automatisierung von Red Hat Enterprise Linux (RHEL) 9-Bereitstellungen mithilfe von Docker-Containern und Red Hat Universal Base Images (UBI) kennengelernt. Sie haben erfahren, dass traditionelle RHEL-Bereitstellungen auf Kickstart-Dateien und virtuellen Maschinen basierten, während moderne Cloud-native Umgebungen zunehmend containerisiertes RHEL über UBI-Images wie redhat/ubi9 verwenden.

Sie haben das Übersetzen traditioneller Kickstart-Konzepte in die Container-Automatisierung geübt, indem Sie benutzerdefinierte Dockerfiles erstellt haben, die Systemkonfiguration, Paketinstallation, Benutzerverwaltung und Dienstkonfiguration definieren. Anstatt ksvalidator für Kickstart-Dateien zu verwenden, haben Sie gelernt, Containerkonfigurationen über den Build-Prozess von Docker zu validieren, der sofortiges Feedback zu Syntax- und Ausführungsfehlern liefert.

Schließlich haben Sie ein umfassendes Automatisierungsskript erstellt, das die End-to-End-Container-Bereitstellung demonstriert, ähnlich der Verwendung von virt-install mit Kickstart-Dateien für die VM-Automatisierung. Dieser Ansatz bietet das gleiche Maß an Automatisierung und Konsistenz wie herkömmliche Methoden und bietet gleichzeitig die Vorteile der Containerisierung: schnellere Bereitstellung, bessere Ressourcenauslastung, Portabilität und einfachere Skalierung in modernen Cloud-Umgebungen.