파일 구조

java21-springboot3.4.4
├── Dockerfile
├── docker-compose.yml
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── demo
        │               └── DemoApplication.java
        └── resources
            └── application.properties

1. 디렉터리 생성

mkdir -p java21-springboot3.4.4/src/main/java/com/example/demo java21-springboot3.4.4/src/main/resources
cd java21-springboot3.4.4

2. pom.xml 작성

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>springboot344-demo</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.4</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>21</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

3. 샘플 애플리케이션 작성

src/main/java/com/example/demo/DemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {

    @GetMapping("/")
    public String hello() {
        return "Hello from Spring Boot 3.4.4 with Java 21!";
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

**4.application.properties 작성**

src/main/resources/application.properties

server.port=8080

5.Dockerfile 작성

FROM maven:3.9.9-eclipse-temurin-21 AS builder
WORKDIR /workspace
COPY pom.xml .
COPY src src
RUN mvn clean package -DskipTests

FROM eclipse-temurin:21-jdk
WORKDIR /app
COPY --from=builder /workspace/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

6. docker-compose.yml 작성

version: '3.8'

services:
  springboot-app:
    image: springboot344
    container_name: springboot344
    build: .
    ports:
      - "8080:8080"
    restart: unless-stopped

7. 이미지 빌드 및 실행

docker compose build
docker compose up -d

8. 확인

docker ps
curl <http://localhost:8080>

출력 결과:

Hello from Spring Boot 3.4.4 with Java 21!

1. 목적

본 문서는 OpenShift Container Platform(OCP) 환경에서 MachineConfigPool(MCP) 상태가 Degraded로 표시되는 경우의 원인 분석 및 복구 절차를 정의한다.

2. MCP 상태 점검 절차

2.1 MCP 상태 확인

oc get mcp -o wide
  • Degraded=True 여부 확인
  • DegradedMachineCount 확인 → 문제 노드 개수 식별

2.2 상세 원인 확인

oc describe mcp <pool-name>
  • Message: 필드에서 Degraded 원인 파악
    • 예:
    • Node worker03.ocp.dc.test is reporting: "unexpected on-disk state validating against rendered-worker-xxxx: content mismatch for file "/etc/kubernetes/ca.crt""

3. 문제 노드 분석

3.1 노드 상태 확인

oc describe node <node-name>
  • NodeDegraded 메시지 및 이벤트(Event) 확인

3.2 정상 노드와 파일 비교

# 파일 해시 비교
ssh core@<normal-node> sha256sum /etc/kubernetes/ca.crt
ssh core@<problem-node> sha256sum /etc/kubernetes/ca.crt

# SELinux 라벨 비교
ssh core@<node> ls -lZ /etc/kubernetes/ca.crt
  • 파일 내용, 크기, 해시값이 동일해야 함
  • SELinux 라벨이 system_u:object_r:kubernetes_file_t:s0 와 일치해야 함

4. 복구 절차

4.1 정상 파일 복사

# 정상 노드에서 추출
ssh core@worker01 sudo cat /etc/kubernetes/ca.crt > ca.crt.good
scp ca.crt.good core@worker03:/tmp/ca.crt

4.2 문제 노드 교체 및 라벨 복구

ssh core@worker03 "sudo cp /tmp/ca.crt /etc/kubernetes/ca.crt && sudo restorecon -v /etc/kubernetes/ca.crt"

restorecon 명령은 SELinux 보안 라벨을 정책에 맞게 복구하여 MCD가 정상 상태로 인식하도록 한다.

4.3 상태 확인

oc get mcp <pool-name>
  • Degraded=False, Updated=True 로 변환 여부 확인

5. 정상화 기준

  • MCP 상태
  • UPDATED=True UPDATING=False DEGRADED=False DEGRADEDMACHINECOUNT=0
  • ClusterOperator 상태
  • oc get co machine-config Available=True Progressing=False Degraded=False

6. 재부팅 필요 여부

  • 파일/라벨 mismatch 문제는 재부팅 없이 복구 가능 (MCD가 즉시 반영)
  • 단, 커널 파라미터/CRI-O/kubelet 설정과 같이 시스템 레벨 변경이 포함된 MachineConfig는 노드 재부팅 필요

7. 요약

  1. oc describe mcp 로 원인 메시지 확인
  2. 문제 노드 파일 상태를 정상 노드와 비교 (내용 + SELinux 라벨)
  3. 정상 파일 복사 후 restorecon 으로 라벨 복구
  4. MCD가 자동으로 동기화하여 MCP 상태가 정상화됨

🔗 참고 문서

 

mcp degraded 이슈 실제 사례

더보기

mcp degraded 이슈

[root@bastion ~]# oc get mcp -o wide
NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
master   rendered-master-325d391d426e0e298308b7da2754f21d   True      False      False      3              3                   3                     0                      114d
worker   rendered-worker-ab20e6d8c747ce3000959dbd8e4892cf   False     True       True       3              2                   2                     1                      114d

oc describe mcp worker : 실패 사유 확인

root@bastion ~]# oc describe mcp worker
Name:         worker
..생략..
  Conditions:
    Last Transition Time:  2025-09-11T06:46:58Z
    Message:               Node worker03.ocp.dc.test is reporting: "unexpected on-disk state validating against rendered-worker-ab20e6d8c747ce3000959dbd8e4892cf: content mismatch for file \\\\"/etc/kubernetes/ca.crt\\\\""
    Reason:                1 nodes are reporting degraded status on sync
    Status:                True
    Type:                  NodeDegraded
    Last Transition Time:  2025-09-24T06:44:26Z
    Message:
    Reason:
    Status:                False
    Type:                  RenderDegraded

```bash
[root@bastion ~]# oc describe mcp worker
Name:         worker
Namespace:
Labels:       machineconfiguration.openshift.io/mco-built-in=
              pools.operator.machineconfiguration.openshift.io/worker=
Annotations:  <none>
API Version:  machineconfiguration.openshift.io/v1
Kind:         MachineConfigPool
Metadata:
  Creation Timestamp:  2025-06-02T00:59:34Z
  Generation:          2
  Resource Version:    49932695
  UID:                 782bf566-0d62-4b2c-9023-55f40c6ddad1
Spec:
  Configuration:
    Name:  rendered-worker-ab20e6d8c747ce3000959dbd8e4892cf
    Source:
      API Version:  machineconfiguration.openshift.io/v1
      Kind:         MachineConfig
      Name:         00-worker
      API Version:  machineconfiguration.openshift.io/v1
      Kind:         MachineConfig
      Name:         01-worker-container-runtime
      API Version:  machineconfiguration.openshift.io/v1
      Kind:         MachineConfig
      Name:         01-worker-kubelet
      API Version:  machineconfiguration.openshift.io/v1
      Kind:         MachineConfig
      Name:         97-worker-generated-kubelet
      API Version:  machineconfiguration.openshift.io/v1
      Kind:         MachineConfig
      Name:         98-worker-generated-kubelet
      API Version:  machineconfiguration.openshift.io/v1
      Kind:         MachineConfig
      Name:         99-worker-generated-registries
      API Version:  machineconfiguration.openshift.io/v1
      Kind:         MachineConfig
      Name:         99-worker-ssh
  Machine Config Selector:
    Match Labels:
      machineconfiguration.openshift.io/role:  worker
  Node Selector:
    Match Labels:
      node-role.kubernetes.io/worker:
  Paused:                              false
Status:
  Cert Expirys:
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2035-05-30T17:07:27Z
    Subject:  CN=admin-kubeconfig-signer,OU=openshift
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2025-09-28T01:50:36Z
    Subject:  CN=openshift-kube-controller-manager-operator_csr-signer-signer@1753840235
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2025-10-03T21:19:07Z
    Subject:  CN=kube-csr-signer_@1756934347
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2025-11-01T09:18:12Z
    Subject:  CN=openshift-kube-controller-manager-operator_csr-signer-signer@1756804691
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2025-10-22T05:17:27Z
    Subject:  CN=kube-csr-signer_@1758518246
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2026-06-01T17:07:32Z
    Subject:  CN=kube-apiserver-to-kubelet-signer,OU=openshift
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2026-06-01T17:07:32Z
    Subject:  CN=kube-control-plane-signer,OU=openshift
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2025-11-01T09:28:46Z
    Subject:  CN=openshift-kube-apiserver-operator_kube-control-plane-signer@1756805326
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2025-09-28T01:50:36Z
    Subject:  CN=openshift-kube-apiserver-operator_kube-control-plane-signer@1753840236
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2025-11-01T09:28:46Z
    Subject:  CN=openshift-kube-apiserver-operator_kube-control-plane-signer@1756805307
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2035-05-30T17:07:28Z
    Subject:  CN=kubelet-bootstrap-kubeconfig-signer,OU=openshift
    Bundle:   KubeAPIServerServingCAData
    Expiry:   2026-06-02T00:59:01Z
    Subject:  CN=openshift-kube-apiserver-operator_node-system-admin-signer@1748825941
  Conditions:
    Last Transition Time:  2025-09-11T06:46:17Z
    Message:
    Reason:
    Status:                False
    Type:                  Updated
    Last Transition Time:  2025-09-11T06:46:17Z
    Message:               All nodes are updating to MachineConfig rendered-worker-ab20e6d8c747ce3000959dbd8e4892cf
    Reason:
    Status:                True
    Type:                  Updating
    Last Transition Time:  2025-09-11T06:46:58Z
    Message:
    Reason:
    Status:                True
    Type:                  Degraded
    Last Transition Time:  2025-09-11T06:46:58Z
    Message:               Node worker03.ocp.dc.test is reporting: "unexpected on-disk state validating against rendered-worker-ab20e6d8c747ce3000959dbd8e4892cf: content mismatch for file \\\\"/etc/kubernetes/ca.crt\\\\""
    Reason:                1 nodes are reporting degraded status on sync
    Status:                True
    Type:                  NodeDegraded
    Last Transition Time:  2025-09-24T06:44:26Z
    Message:
    Reason:
    Status:                False
    Type:                  RenderDegraded
  Configuration:
    Name:  rendered-worker-ab20e6d8c747ce3000959dbd8e4892cf
    Source:
      API Version:            machineconfiguration.openshift.io/v1
      Kind:                   MachineConfig
      Name:                   00-worker
      API Version:            machineconfiguration.openshift.io/v1
      Kind:                   MachineConfig
      Name:                   01-worker-container-runtime
      API Version:            machineconfiguration.openshift.io/v1
      Kind:                   MachineConfig
      Name:                   01-worker-kubelet
      API Version:            machineconfiguration.openshift.io/v1
      Kind:                   MachineConfig
      Name:                   97-worker-generated-kubelet
      API Version:            machineconfiguration.openshift.io/v1
      Kind:                   MachineConfig
      Name:                   98-worker-generated-kubelet
      API Version:            machineconfiguration.openshift.io/v1
      Kind:                   MachineConfig
      Name:                   99-worker-generated-registries
      API Version:            machineconfiguration.openshift.io/v1
      Kind:                   MachineConfig
      Name:                   99-worker-ssh
  Degraded Machine Count:     1
  Machine Count:              3
  Observed Generation:        2
  Ready Machine Count:        2
  Unavailable Machine Count:  1
  Updated Machine Count:      2
Events:                       <none>

```

정상 worker노드의 /etc/kubernetes/ca.crt 추출 후 worker03 에 붙여넣기

# worker01에서 추출
ssh core@worker01 sudo cat /etc/kubernetes/ca.crt > ca.crt.good

# worker03에 덮어쓰기
# restorecon 명령으로 라벨 재설정
scp ca.crt.good core@worker03:/var/home/core/ca.crt
ssh core@worker03 "sudo cp /tmp/ca.crt /etc/kubernetes/ca.crt && sudo restorecon -v /etc/kubernetes/ca.crt"

[root@bastion ~]# ssh core@worker01 sha256sum /etc/kubernetes/ca.crt
2b2dbe065a9a8c1a70ecbc11c0cdc2dcf7a034b5fc6f2b85cb193dcecea04037  /etc/kubernetes/ca.crt
[root@bastion ~]# ssh core@worker02 sha256sum /etc/kubernetes/ca.crt
2b2dbe065a9a8c1a70ecbc11c0cdc2dcf7a034b5fc6f2b85cb193dcecea04037  /etc/kubernetes/ca.crt
[root@bastion ~]# ssh core@worker03 sha256sum /etc/kubernetes/ca.crt
2b2dbe065a9a8c1a70ecbc11c0cdc2dcf7a034b5fc6f2b85cb193dcecea04037  /etc/kubernetes/ca.crt

[root@bastion ~]# ssh core@worker01 ls -lZ /etc/kubernetes/ca.crt
-rw-r--r--. 1 root root system_u:object_r:kubernetes_file_t:s0 1123 Sep 24 07:51 /etc/kubernetes/ca.crt
[root@bastion ~]# ssh core@worker02 ls -lZ /etc/kubernetes/ca.crt
-rw-r--r--. 1 root root system_u:object_r:kubernetes_file_t:s0 1123 Sep 24 06:42 /etc/kubernetes/ca.crt
[root@bastion ~]# ssh core@worker03 ls -lZ /etc/kubernetes/ca.crt
-rw-r--r--. 1 root root system_u:object_r:kubernetes_file_t:s0 1123 Sep 24 07:54 /etc/kubernetes/ca.crt

정상화

# 정상화
[root@bastion ~]# oc get mcp
NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
master   rendered-master-325d391d426e0e298308b7da2754f21d   True      False      False      3              3                   3                     0                      114d
worker   rendered-worker-ab20e6d8c747ce3000959dbd8e4892cf   True      False      False      3              3                   3                     0                      114d

 

  • 흐름도 (Mermaid)
  • flowchart TD A[노드 재조인 시도] --> B{문제 발생} %% config.json 문제 경로 B -->|"/var/lib/kubelet/config.json <br/> 없음 "| C[정상 워커에서 config.json 복사] C --> D[restorecon -Rv /var/lib/kubelet 적용] %% nodeip-configuration 실패 경로 B -->|nodeip-configuration 실패| E[로그 확인: credential file 접근 불가] E --> C %% crio 문제 경로 B -->|"crio inactive (dead)"| F[systemctl restart crio] F -->|/var/run/crio/crio.sock 없음| G[이미지 풀링 문제 <br/> → 폐쇄망 레지스트리 확인] %% kubelet 문제 경로 B -->|"kubelet inactive (dead)"| H[systemctl restart kubelet] H -->|"로그에 system:anonymous"| I[CSR Pending 확인] I --> J["oc get csr | grep Pending"] J --> K["oc adm certificate approve <csr>"] K --> L[CSR 모두 승인] L --> M["oc get no → Ready 확인"]

1. 증상

  • oc get no 에서 worker03 노드 미표시
  • systemctl status crio, systemctl status kubelet 모두 inactive (dead)
  • systemctl status nodeip-configuration → credential file (/var/lib/kubelet/config.json) 없음 오류
  • kubelet 로그:
Unable to register node with API server
User "system:anonymous" cannot create resource "nodes"
  • /var/lib/kubelet/pki/kubelet-client-current.pem 파일 없음

2. 원인

  1. /var/lib/kubelet/config.json 누락
    • 이 파일은 podman(및 nodeip-configuration)이 내부 이미지(MCO 관련 컨테이너) pull 시 사용하는 인증파일.
    • 없으니 nodeip-configuration 이 실패 → CRI-O와 kubelet 환경 초기화 지연.
  2. CRI-O, kubelet 서비스 비활성화
    • nodeip-configuration 이 실패하면 drop-in 파일(20-nodenet.conf) 갱신이 안 되어 CRI-O, kubelet이 기동하지 않음.
  3. 부트스트랩 CSR 재발급 필요
    • kubelet이 bootstrap 단계에서 API server와 인증이 안 돼 system:anonymous 로 보임 → 노드 등록 불가.

3. 영향

  • kubelet이 bootstrap 인증서 요청 → CSR 생성을 못 함.
  • nodeip-configuration이 무한 루프처럼 quay.io 에서 pull 시도 → 폐쇄망 환경에서 영구 대기.
  • 결과적으로 kubelet / CRI-O 서비스가 멈춘 상태로 노드가 클러스터에 합류하지 못함.

4. 해결 절차

  1. config.json 복구
    • worker01 노드에서 /var/lib/kubelet/config.json 복사 → worker03 에 반영
    • SELinux context 복원:
restorecon -Rv /var/lib/kubelet
  1. nodeip-configuration 재실행
sudo systemctl restart nodeip-configuration
    • 20-nodenet.conf 와 crio.service.d/20-nodenet.conf 정상 반영 확인
  1. CRI-O, kubelet 기동
sudo systemctl restart crio
sudo systemctl restart kubelet
    • /var/run/crio/crio.sock 생성 확인
    • kubelet 정상 실행 확인
  1. CSR 승인
    • bootstrap, client, serving CSR 순차 승인:
oc get csr | grep Pending
oc adm certificate approve <csr-name>
    • 승인 완료 후 oc get no 에서 Ready 확인

5. 결론

  • 직접 원인: /var/lib/kubelet/config.json 누락 → nodeip-configuration 실패 → CRI-O/kubelet 비활성화 → CSR 생성 및 승인 불가.
  • 간접 원인: 부트스트랩 토큰 만료 및 CSR 미승인 상태에서 재조인 시도.
  • 재발 방지:
    • 노드 교체 시 /var/lib/kubelet/ 초기화 및 config.json 존재 여부 확인
    • 폐쇄망 환경에서는 quay.io pull 안 되므로 반드시 oc-mirror로 레지스트리 미리 준비
    • 신규 노드 합류 시 CSR pending → 승인 절차 체크리스트화

✅ Worker 노드 재조인 점검 체크리스트 (폐쇄망 환경 기준)

1. 사전 점검

  • 기존 노드 /var/lib/kubelet/ 정리 여부 확인 (rm -rf /var/lib/kubelet/*)
  • /var/lib/kubelet/config.json 존재 여부 확인
    • 없으면 다른 정상 워커에서 복사 후 restorecon -Rv /var/lib/kubelet 적용
  • /var/lib/kubelet/pki/kubelet-client-current.pem 이 생성되지 않았다면, CSR 승인 대기 상태 확인 필요

2. nodeip-configuration 서비스

  • systemctl status nodeip-configuration 확인
  • 실패 시 로그 점검:
Error: credential file is not accessible: /var/lib/kubelet/config.json
  • 정상 동작 시, 아래 파일 자동 생성/갱신 여부 확인:
    • /etc/systemd/system/kubelet.service.d/20-nodenet.conf
    • /etc/systemd/system/crio.service.d/20-nodenet.conf
    • /run/nodeip-configuration/primary-ip

3. CRI-O 서비스

  • systemctl status crio 가 active (running) 인지 확인
  • /var/run/crio/crio.sock 파일 생성 여부 확인
  • 폐쇄망 환경에서는 quay.io pull 시도로 무한 대기할 수 있음
  • → 반드시 oc-mirror로 bastion 레지스트리에 이미지 사전 준비

4. Kubelet 서비스

  • systemctl status kubelet 확인 → active (running) 이어야 함
  • 로그 점검:
    • system:anonymous 관련 에러 → CSR 미승인 상태
    • Unable to register node with API server 발생 시 CSR 확인 필요

5. CSR 처리

  • oc get csr | grep Pending 확인
  • CSR 유형별 승인 필요:
oc adm certificate approve <csr-name>

6. 재발 방지 포인트

  • 노드 교체 시 /var/lib/kubelet/ 초기화 필수
  • config.json 미존재 시 사전 복사/검증
  • 폐쇄망 환경 → 이미지 미리 미러링 (oc-mirror, bastion registry 사용)
  • CSR 승인 절차 문서화 및 운영팀 공유

 

 

 

Red Hat Data Grid(JBoss Data Grid, JDG) 6.6과 RHDG 8.5.4는 아키텍처적인 차이 때문에 기본적으로 필요한 포트 구성이 다릅니다.

특히 JDG 6.6은 WildFly/EAP 기반이었기 때문에 애플리케이션 서버 포트까지 포함되지만, RHDG 8.5.4는 독립형 Infinispan 기반이라 훨씬 단순화되어 있습니다.

 


 

JDG 6.6 (EAP 기반) 기본 포트

<socket-binding-group name="standard-sockets" default-interface="public">
  <socket-binding name="management-http" port="9990"/>
  <socket-binding name="management-native" port="9999"/>
  <socket-binding name="http" port="8080"/>
  <socket-binding name="https" port="8443"/>
  <socket-binding name="ajp" port="8009"/>
  <socket-binding name="remoting" port="4447"/>
  <socket-binding name="hotrod" port="11222"/>
  <socket-binding name="memcached" port="11211"/>
  <socket-binding name="txn-recovery-environment" port="4712"/>
  <socket-binding name="txn-status-manager" port="4713"/>
</socket-binding-group>

→ WildFly 관리 포트, HTTP/HTTPS, AJP, Remoting 등 WAS 환경을 위한 포트가 다수 포함되어 있었습니다.

 


 

RHDG 8.5.4 (독립형 Infinispan 기반) 포트 구성

 

RHDG 8.5.4는 필수 포트와 선택 포트가 명확히 구분됩니다.

 

 

✅ 필수 포트

 

  • Hot Rod: 11222(포트 오프셋 적용 시 11322, 11422 등으로 변경 가능)
  • 클라이언트와 Data Grid 서버 간의 기본 연결 포트
  • JGroups 클러스터 통신:
    • TCP 스택 → 예: 7600
    • UDP 스택 → 멀티캐스트 주소/포트 (예: 230.x.x.x:55200)
    • → 노드 간 내부 통신용, 외부에 개방할 필요 없음
  •  

 

 

⚙️ 선택 포트

 

  • REST API: REST 엔드포인트 사용 시 별도 포트 또는 Hot Rod 포트 공유
  • Memcached: Memcached 커넥터 사용 시 (기본값 11221)
  • Metrics/Health: REST 켜져 있으면 /metrics, /health 엔드포인트 제공

 

 

❌ 불필요한 포트 (6.6과 달리 사용 안 함)

 

  • 관리 콘솔(9990/9999)
  • HTTP/HTTPS (8080/8443, 웹 애플리케이션 X)
  • AJP (8009)
  • Remoting (4447)
  • Txn Recovery/Status (4712/4713)

 


 

📊 포트 비교 표

기능JDG 6.6RHDG 8.5.4비고

관리(Management) 9990, 9999 불필요 8.x는 CLI/REST로 대체
HTTP/HTTPS 8080, 8443 불필요(REST만 선택) 웹 애플리케이션 없음
AJP 8009 불필요  
Hot Rod 11222 11222 (필수) 클라이언트 접속
Memcached 11211 11221 (선택) 커넥터 사용 시
Remoting 4447 불필요  
Txn Recovery/Status 4712/4713 불필요  
JGroups 내부 포트 TCP(7600)/UDP 노드 간 통신 전용
콘솔(Web UI) 기본 제공 없음 별도 도구 필요

 


 

🔎 운영 가이드

 

  • 외부 클라이언트 → Hot Rod(11222), 필요 시 REST/Memcached
  • 내부 클러스터 노드 → JGroups 포트(TCP 7600 또는 UDP 멀티캐스트)
  • 불필요한 WAS용 포트는 전혀 열지 않아도 됨
  • 실제 리슨 포트는 server.log 또는 ss -lntp 로 확인 필요

 


 

📝 정리

 

  • JDG 6.6은 EAP 기반 WAS → 관리/웹/트랜잭션 등 다양한 포트 필요
  • RHDG 8.5.4는 순수 Data Grid → Hot Rod + JGroups 중심, 훨씬 단순

 

👉 따라서 RHDG 8.5.4 운영 시에는 Hot Rod(11222)JGroups 포트만 신경 쓰면 되고, 나머지는 옵션

1. 디스크 확장 확인

lsblk

디스크 용량이 늘어난 것을 확인

 


 

2. parted로 기존 2번 파티션 삭제 및 재생성

sudo parted /dev/sda
(parted) print
(parted) rm 2
(parted) mkpart primary 1075MB 100%
(parted) quit

 


 

3. 커널에 파티션 정보 반영

sudo partprobe

또는 재부팅

 


 

4. 물리 볼륨 크기 확장

sudo pvresize /dev/sda2

 


 

5. 논리 볼륨 크기 확장

sudo lvextend -l +100%FREE /dev/mapper/rl-root

 


 

6. 파일시스템 확장 (XFS 기준)

sudo xfs_growfs /

 


 

7. 최종 확인

df -h /

 


이 과정은 growpart 없이 수동으로 파티션을 삭제 후 동일한 위치로 재생성하는 방식이며, 루트 파티션이 LVM 기반일 때 안전하게 사용 가능합니다.

 

 

실제

[root@rocky-8-10 ~]# parted /dev/sda
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 107GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  1075MB  1074MB  primary  xfs          boot
 2      1075MB  53.7GB  52.6GB  primary               lvm

(parted) 2
  align-check TYPE N                        check partition N for TYPE(min|opt) alignment
  help [COMMAND]                           print general help, or help on COMMAND
  mklabel,mktable LABEL-TYPE               create a new disklabel (partition table)
  mkpart PART-TYPE [FS-TYPE] START END     make a partition
  name NUMBER NAME                         name partition NUMBER as NAME
  print [devices|free|list,all|NUMBER]     display the partition table, available devices, free space, all found partitions, or a particular partition
  quit                                     exit program
  rescue START END                         rescue a lost partition near START and END
  resizepart NUMBER END                    resize partition NUMBER
  rm NUMBER                                delete partition NUMBER
  select DEVICE                            choose the device to edit
  disk_set FLAG STATE                      change the FLAG on selected device
  disk_toggle [FLAG]                       toggle the state of FLAG on selected device
  set NUMBER FLAG STATE                    change the FLAG on partition NUMBER
  toggle [NUMBER [FLAG]]                   toggle the state of FLAG on partition NUMBER
  unit UNIT                                set the default unit to UNIT
  version                                  display the version number and copyright information of GNU Parted
(parted) rm 2
Error: Partition(s) 2 on /dev/sda have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.
Ignore/Cancel? Cancel
(parted) ^C

Information: You may need to update /etc/fstab.






[root@rocky-8-10 ~]# lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    0  100G  0 disk
├─sda1        8:1    0    1G  0 part /boot
└─sda2        8:2    0   49G  0 part
  ├─rl-root 253:0    0   44G  0 lvm  /
  └─rl-swap 253:1    0    5G  0 lvm  [SWAP]
sr0          11:0    1 1024M  0 rom
[root@rocky-8-10 ~]# parted /dev/sda print
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 107GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  1075MB  1074MB  primary  xfs          boot

[root@aT-disConn-rocky-8-10 ~]# pvs
  PV         VG Fmt  Attr PSize   PFree
  /dev/sda2  rl lvm2 a--  <49.00g    0
[root@rocky-8-10 ~]# parted /dev/sda
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 107GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  1075MB  1074MB  primary  xfs          boot

(parted) mkpart primary 1075MB 100%
(parted) quit
Information: You may need to update /etc/fstab.

[root@rocky-8-10 ~]# sudo partprobe
[root@rocky-8-10 ~]# lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    0  100G  0 disk
├─sda1        8:1    0    1G  0 part /boot
└─sda2        8:2    0   99G  0 part
  ├─rl-root 253:0    0   44G  0 lvm  /
  └─rl-swap 253:1    0    5G  0 lvm  [SWAP]
sr0          11:0    1 1024M  0 rom
[root@rocky-8-10 ~]# pvresize /dev/sda2
  Physical volume "/dev/sda2" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized
[root@rocky-8-10 ~]# lvextend -l +100%FREE /dev/mapper/rl-root
  Size of logical volume rl/root changed from <44.00 GiB (11263 extents) to <94.00 GiB (24063 extents).
  Logical volume rl/root successfully resized.
[root@aT-disConn-rocky-8-10 ~]# xfs_growfs /
meta-data=/dev/mapper/rl-root    isize=512    agcount=4, agsize=2883328 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=0 inobtcount=0
data     =                       bsize=4096   blocks=11533312, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=5631, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 11533312 to 24640512
[root@rocky-8-10 ~]# df -h /
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/rl-root   94G   44G   51G  47% /




 

LVM 볼륨을 확장했는데도 파일시스템을 별도로 확장해야 하는 이유

 

 

📌 이유: 논리 볼륨(LV)과 파일시스템 은 서로 다른 계층이기 때문입니다

 

구조를 보면:

[ 물리 디스크 ] → [ 파티션 (sda2) ] → [ PV (Physical Volume) ] → [ VG (Volume Group) ] → [ LV (Logical Volume) ] → [ 파일시스템 (XFS 등) ]

 

즉, 확장 과정은 이렇게 나뉩니다:

 

  1. 디스크 크기 늘리기 (vSphere, parted 등)
  2. LVM 계층 (LV) 크기 늘리기 (lvextend)
  3. 파일시스템 크기 늘리기 (xfs_growfs 또는 resize2fs)

 


 

✅ 예시

 

  • lvextend → LV(논리 볼륨)의 블록 공간이 커짐
  • 하지만 파일시스템은 기존 크기까지만 사용하고 있음
  • → 그래서 xfs_growfs /파일시스템이 그 공간을 인식하고 사용하도록 확장해야 함

 


 

💡 만약 xfs_growfs를 안 하면?

 

  • df -h로 확인했을 때 용량이 그대로임 (예: 44G)
  • 실제 LV는 커졌지만, OS는 추가된 공간을 아직 모름

 


 

요약

단계목적명령어

lvextend LV 크기 확장 lvextend -l +100%FREE ...
xfs_growfs 파일시스템 확장 xfs_growfs /

→ 둘 다 해야 공간이 실제로 사용 가능해집니다.

 


 

 

시험 문제

더보기

시험 문제 

 

시스템 IP 주소 Ansible Roles
control.domain1.example.com 172.24.1.11 ansible control node
utility.domain1.example.com 172.24.1.17 Utility node
node1.domain1.example.com 172.24.1.6 ansible managed node
node2.domain1.example.com 172.24.1.7 ansible managed node
node3.domain1.example.com 172.24.1.8 ansible managed node
node4.domain1.example.com 172.24.1.9 ansible managed node
node5.domain1.example.com 172.24.1.10 ansible managed node

 

1.Install and configure Ansible (Ansible 설치 및 구성)

2. Create yum repositories (yum 저장소 생성)

3. Install a Collection (컬렉션 설치)

4. Install packages (패키지 설치)

5. Use a role  (ansible 역할 사용하기)

6. Install roles using Ansible Galaxy (Ansible Galaxy를 사용하여 역할 설치하기)

7. Create and use a role (역할 생성 및 사용하기)

8. Use roles from Ansible Galaxy (Ansible Galaxy에서 역할 사용하기)

9. Create and use a logical volume (Logical Volume (LV) 생성 및 사용하기)

10. Generate a hosts file (Hosts 파일 생성하기)

11. Modify file content (파일 내용 수정하기)

12. Create a web content directory (web 컨텐츠 디렉토리 생성하기)

13. Generate a hardware report (하드웨어 보고서 생성하기)

14. Create a password vault (비밀번호 보관소 생성하기)

15. Create user accounts (사용자 계정 생성하기)

16. Rekey an Ansible vault (Ansible Vault 재키 생성하기)

17. Configure a cron job  (크론작업 설정하기)

 

실제 키오스크 시험 환경

1. 16인치 쯤 돼 보이는 싱크패드 노트북이 놓인 빈 방에서 응시

2. 감독관과 채팅으로 소통, 노트북에 달린 화상캠으로 방을 전부 비춰야한다

3. 중간에 화장실 이용 가능 하나 짧게 다녀와야한다

4. 집중력이 부족한 사람의 경우 창밖에서 나는 도로 소리와 강의실 밖에서 사람들이 간헐적으로 내는 소음을 들으면 난처할 수가 있다

5. 전자제품 사용 금지, 이어플러그 금지, 종이나 팬도 허용되지 않음

 

시험 간 유의 사항

1. 실제 시험에서는 control 서버, node1 ~ node5 총 6대서버로 구성

2. 시험시간은 총 4시간 (최소한 3시간안에 모든 문제를 다 풀도록 해야함)

3. 문제를 잘 읽고 지시 사항대로 구현할 것 🔥🔥🔥  

  예시:

  - 플레이북을 이용해 웹 서버를 통해서 파일을 받으라는 지시사항이 있으면 앤서블 플레이북 작성시 반드시 get_url 모듈을 사용

4. 기본적으로 kiosk 계정에 ssh-keygen이 설정되어있으니 절대로 변경하지말것

5 selinux 적용된상태 또는 서비스가 제대로 재기동하는지 검토해야되므로 주기적으로 재부팅을 하면서 체크하도록한다. 서비스 영구 적용 등

 

ansible-doc <<module name>> 으로 모듈을 검색 후 /EXAPLE로 사용 사례 찾아보기 

 

 

문제 

- 접은 부분은 영문 문제 설명이다

- ansible-playbook 명령어를 사용해 플레이북을 실행했다

- 플레이북에서 ansible.builtin.모듈명은 사용하지 않았다

 

1. Install and configure Ansible (Ansible 설치 및 구성)

제어 노드 control_domain1.example.com에 Ansible을 다음과 같이 구성하시오 

필요한 패키지 설치

/home/admin/ansible/inventory라는 정적 인벤토리 파일을 생성하고 다음과 같이 구성합니다:

  - node1은 dev 호스트 그룹의 구성원입니다.

  - node2는 test 호스트 그룹의 구성원입니다.

  - node3 및 node4는 prod 호스트 그룹의 구성원입니다.

  - node5는 balancers 호스트 그룹의 구성원입니다.

  - prod 그룹은 webservers 호스트 그룹의 구성원입니다.

 

/home/admin/ansible/ansible.cfg라는 구성 파일을 생성하고 다음과 같이 구성합니다:

  - 호스트 인벤토리 파일은 /home/admin/ansible/inventory입니다.

  - 기본 컨텐츠 컬렉션 디렉토리는 /home/admin/ansible/mycollections입니다.

  - 기본 역할 디렉토리는 /home/admin/ansible/roles입니다.

 

더보기

1. Install and configure Ansible on the control node control_domain1.example.com as follows:

 

Install the required packages

Create a static inventory file called /home/admin/ansible/inventory so that:

     -  node1 is a member of the dev host group

     -  node2 is a member of the test host group

     -  node3 and node4 are members of the prod host group

     -  node5 is a member of the balancers host group

     -  The prod group is a member of the webservers host gorup


Create a configuration file called /home/admin/ansible/ansible.cfg so that:

     - The host inventory file is /home/admin/ansible/inventory

     - The default content collections directory is /home/admin/ansible/mycollections

     - The default roles directoty is /home/admin/ansible/roles

 

 

풀이)

방법 1)

sudo dnf –y install ansible-automation-platform-common.noarch

sudo dnf –y install ansible-navigator

 

방법2)

sudo dnf -y install ansible-*

 

mkdir ansible && cd ansible

vim inventory

[dev]
Node1
 
[test]
Node2
 
[prod]
Node3
Node4
 
[balancers]
Node5
 
[webservers:children]
prod

 

 

/home/admin/ansible/ansible.cfg

[defaults]
collections_path=/home/admin/ansible/mycollections:~/.ansible/collections:/usr/share/ansible/collections 
inventory = /home/admin/ansible/inventory 
roles_path = /home/admin/ansible/roles:/usr/share/ansible/roles/ 
remote_user = admin
 
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False

 

결과확인

ansible all -m ping 

 

 


2. Create yum repositories (yum 저장소 생성)

시스템 관리자로서, 관리되는 노드에 소프트웨어를 설치해야합니다. 다음 작업을 수행하는 /home/admin/ansible/yum_repo.yml 플레이북을 생성하세요. 각 관리되는 노드에 다음 yum 저장소를 만듭니다.

 

  - 저장소 이름은 EX294_BASE입니다.

  - 설명은 EX 294 기본 소프트웨어입니다.

  - 기본 URL은 https://rhgl.domain1.example.com/BaseOS입니다.

  - GPG 서명 확인이 활성화되어 있습니다.

  - GPG 키 URL은 https://rhgls.domain1.example.com/RHEL/RPM-GPG-KEY-redhat-release입니다.

  - 저장소가 활성화됩니다.

 

  -  저장소 이름은 EX294_STREAM입니다.

  -  설명은 EX 294 스트림 소프트웨어입니다.

  -  기본 URL은 https://rhgl.domain1.example.com/AppStream입니다.

  -  GPG 서명 확인이 활성화되어 있습니다.

  -  GPG 키 URL은 https://rhgls.domain1.example.com/RHEL/RPM-GPG-KEY-redhat-release입니다.

  -  저장소가 활성화됩니다.

 

더보기

2. As a systemm adminstrator, you will need to install software on the managed nodes.

Create the playbook /home/admin/ansible/yum_repo.yml which creates the following yum repositories on each of the managend

 

Repository1:

  - The name of repository is EX294_BASE

  - The description is EX 294 base software

  - The base URL is https://rhgl.domain1.example.com/BaseOS

  - GPG signature checking is enabled

  - The GPG key url is https://rhgls.domain1.example.com/RHEL/RPM-GPG-KEY-redhat-release

  - The repository is enable

 

Repository2:

  - The name of repository is EX294_STREAM

  - The description is EX 294 stream software

  - The base URL is https://rhgl.domain1.example.com/AppStream

  -  GPG signature checking is enabled

  -  The GPG key url is https://rhgls.domain1.example.com/RHEL/RPM-GPG-KEY-redhat-release

  -  The repository is enable

 

# vi /home/admin/ansible/yum_repo.yml
---
- name: create yum repository
  hosts: all
  tasks:
  - name: Add multiple repositories into the same file (1/2)
    ansible.builtin.yum_repository:
      name: EX294_BASE
      description: EX 294 base software
      file: external_repos
      baseurl: https://rhgl.domain1.example.com/BaseOS
      gpgcheck: yes
      gpgkey: https://rhgls.domain1.example.com/RHEL/RPM-GPG-KEY-redhat-release
      enabled: yes       
 
  - name: Add multiple repositories into the same file (2/2)
    ansible.builtin.yum_repository:
      name: EX294_STREAM
      description: EX 294 stream software
      file: external_repos
      baseurl: https://rhgl.domain1.example.com/AppStream
      gpgcheck: yes
      gpgcheck: yes gpgkey:https://rhgls.domain1.example.com/RHEL/RPM-GPG-KEY-redhat-release
      enabled: yes

[참고] ansible-doc yum_repository(EXAMPLE)

 

결과 확인
각 노드에서 /etc/yum.repos.d/external_repos.repo 파일의 내용을 확인: 
ansible all -m command -a "cat /etc/yum.repos.d/external_repos.repo"

 

YUM 저장소 목록 확인:
ansible all -m command -a "yum repolist all"

 

 

 

3. Install a Collection (컬렉션 설치)

사용자 admin으로 http://rhgls.domain1.example.com/materials에서 사용 가능한 다음 컬렉션 아티팩트를 control_domain1.example.com에 설치합니다.

이 컬렉션들은 기본 컬렉션 디렉토리인 /home/admin/ansible/mycollections에 설치되어야합니다.

 

더보기

3. Install the following collection artifacts available from http://rhgls.domain1.example.com/materials to control domain1.example.com as the user admin

  -  redhat-rhel_system_roles-1.16.2.tar.gz

  -  ansible-posix-1.4.0.tar.gz

  -  conmunity-general-4.3.0.tar.gz

 

The collections should be installed into the default collections directory /home/admin/ansible/mycollections

# admin 사용자로 control_domain1.example.com에 로그인합니다.
> su - admin
 
# /home/admin/ansible/mycollections 디렉토리를 만듭니다.
> mkdir –p /home/admin/ansible/mycollections
 
# 각 컬렉션 아티팩트를 다운로드하고 /home/admin/ansible/mycollections 디렉토리로 이동합니다.
> cd /home/admin/ansible/mycollections
> wget http://rhgls.domain1.example.com/materials/redhat-rhel_system_roles-1.16.2.tar.gz
> wget http://rhgls.domain1.example.com/materials/ansible-posix-1.4.0.tar.gz
> wget http://rhgls.domain1.example.com/materials/conmunity-general-4.3.0.tar.gz
 
방법 1
 
ansible-galaxy collection  install \ 
> /home/admin/ansible/mycollections/redhat-rhel_system_roles-1.16.2.tar.gz \
> -p /home/admin/ansible/mycollections

ansible-galaxy collection  install \
> /home/admin/ansible/mycollections/ansible-posix-1.4.0.tar.gz \
> -p /home/admin/ansible/mycollections

ansible-galaxy collection  install \
> /home/admin/ansible/mycollections/conmunity-general-4.3.0.tar.gz \
> -p /home/admin/ansible/mycollections
 
 
방법 2
vi requirements.yml
---
collections:
  - name: /home/admin/ansible/mycollections/redhat-rhel_system_roles-1.16.2.tar.gz
  - name: /home/admin/ansible/mycollections/ansible-posix-1.4.0.tar.gz
  - name: /home/admin/ansible/mycollections/conmunity-general-4.3.0.tar.gz
 
ansible-galaxy collection install -r requirements.yml \
-p /home/admin/ansible/mycollections

 

 

 

 

4. Install packages (패키지 설치)

 /home/admin/ansible/packages.yml이라는 플레이북을 만드세요. 이 플레이북은 다음을 수행합니다.

  -  dev, test 및 prod 호스트 그룹의 호스트에 php 및 mariadb 패키지를 설치합니다.

  -  dev 호스트 그룹의 호스트에 RPM 개발 도구 패키지 그룹을 설치합니다.

  -  dev 호스트 그룹의 호스트에서 모든 패키지를 최신 버전으로 업데이트합니다.

더보기

4. Create a playbook called /home/admin/ansible/packages.yml that:

  -  Installs the php and mariadb packages on hosts in the dev, test and prod host groups

  -  Install the RPM develpment Tools packages group on hosts in the dev host group

  -  Updates all packages to the latest version on hosts in the dev host group

 

 

vi /home/admin/ansible/packages.yml

---
- name: 1. install packages
  hosts:
    - dev
    - test
    - prod
  become: true
  tasks:
  - name: SETP1-1. install php mariadb
    yum:
      name:
        - php
        - mariadb-server
      state: present
 
- name: 2. install dev Packages
  hosts: dev
  become: true
  tasks:
  - name: STEP2-1. install dev packages
    yum:
      name: "@RPM Development Tools"
      state: latest
 
  - name: STEP2-2. update all Packages
    yum:
      name: '*'
      state: latest

 

[참고] ansible-doc  yum(EXAMPLE)

 

결과 확인:

더보기

1. PHP와 MariaDB 설치 확인:

ssh user@worker-node1 "php -v && mysql --version"
 

2. 개발 패키지 설치 확인:

ssh user@worker-node1 "rpm -qa | grep 'Development'"

 

3. 서비스 상태 확인:

ssh user@worker-node1 "systemctl status mariadb"

4. 여러 노드에 대해 반복해서 확인:

여러 워커 노드에 대해 동일한 작업 수행을 위해 간단한 스크립트를 사용할 수 있으나

파악할 노드가 적으니 그냥 일일이 확인할 것 같다

for node in worker-node1 worker-node2 worker-node3; do
  echo "Checking $node" 
  ssh user@$node "php -v && mysql --version && systemctl status mariadb" 
done
 

 

 

 

5.1.  Use a role  (ansible 역할 사용하기: timesync)

redhat system role인 timesync를 사용한다. 

아래 설정을 가지는 /home/admin/ansible/timesync.yml 이라는 플레이북을 생성한다.

- 모든 관리 호 스트에서 실행

- timesync role 사용

- time server 172.24.254.254를 사용하도록 role 구성

- iburst 매개 변수를 활성화 하도록 역할 구성

 

yum install rhel-system-roles

설치된  rhel-system-roles는 /usr/share/ansible/roles에 저장 

해당 경로는 1번 문제의 인벤토리 생성할 때 roles_path에 추가로 명시한 경로이다.

따라서 이렇게 설치만하고 ansible-galaxy list를 수행하면 설치된 rhel role들이 보이게 된다.

 

vim /home/admin/ansible/timesync.yml

---
- hosts: all
  vars:
    timesync_ntp_servers:
      - hostname: 172.25.254.254
      	iburst: yes
  roles:
    - rhel-system-roles.timesync

 

ansible-navigator run -m stdout timesync.yml 

 

결과 확인

ansible all -m shell -a 'chronyc sources' 명령어 날려서 시간 싱크가 잘 되는 것으로 보이면 완료

 

5.2. Use a role  (ansible 역할 사용하기: selinux)

★플레이북에 적을 내용은 외우지말자. role dir의 readme.md에 있다 ★ 

 

 /home/admin/ansible/selinux.yml이라는 플레이북을 만드세요. 이 플레이북은 다음을 수행합니다

- 모든 관리 대상 노드에서 실행됩니다.

- selinux 역할을 사용합니다.

- SElinux 정책을 대상으로 구성합니다.

- SElinux 상태를 강제로 설정합니다.

 

더보기

5.1. Create a palybook called /home/admin/ansible/selinux.yml that:

- Runs on all managed nodes

-  Uses a selinux role

- Configures SElinux policy as targeted

- Sets SElinux state as enforcing

 

$ sudo dnf list | grep roles

$ sudo dnf install rhel-system-roles

$ vi ~/ansible/selinux.yml 

---
- hosts: all
  become: true
  vars:
     - selinux_policy: targeted
     - selinux_state: enforcing
  roles:
     - rhel-system-roles.selinux

 

결과 확인

ansible all -m command -a "sestatus" 

 

 

 

 

6. Install roles using Ansible Galaxy (Ansible Galaxy를 사용하여 역할 설치하기)

/home/admin/ansible/roles/requirements.yml이라는 요구사항 파일을 사용하여 Ansible Galaxy를 사용하여 다음 URL에서 역할을 다운로드하고 기본값인 /home/admin/ansible/roles에 설치하세요.

 

 http://rhgls.domain1.example.com/materials/haproxy.tar

이 역할의 이름은 balancer여야 합니다.

 http://rhgls.domain1.example.com/materials/phpinfo.tar

이 역할의 이름은 phpinfo여야 합니다.

 

더보기

6. Use Ansible Galaxy with a requirements file called /home/admin/ansible/roles/requirements.yml to download and install roles to the default /home/admin/ansible/roles from the following URLs:

 

 http://rhgls.domain1.example.com/materials/haproxy.tar

     The name of this role should be balancer

 http://rhgls.domain1.example.com/materials/phpinfo.tar

     The name of this role should be phpinfo

 

$ mkdir -p ~/ansible/roles && cd ansible

$ vi roles/requirements.yml

- name: balancer
  src: http://rhgls.domain1.example.com/materials/haproxy.tar

- name: phpinfo
  src: http://rhgls.domain1.example.com/materials/phpinfo.tar

$ ansible-galaxy install -r roles/requirements.yml -p roles/

 

결과확인

iventory에 명시한 roles_path에 설치됐는지 확인하기

 


7. Create and use a role (역할 생성 및 사용하기: apache )

 

다음 요구 사항을 갖는 /home/admin/ansible/roles/apache 역할(role)을 생성하십시오.

 

httpd 패키지가 설치되고 부팅시 자동 시작되며 시작됩니다. 
방화벽이 활성화되고 웹 서버에 액세스를 허용하는 규칙이 적용됩니다. 
Index.html.j2 템플릿 파일이 존재하고, 다음 출력을 사용하여 /var/www/html/Index.html 파일을 생성합니다: 
Welcome to FQDN on IPADDRESS 
여기서 HOSTNAME은 관리 노드의 완전히 정규화된 도메인 이름이고, IPADDRESS는 관리 노드의 IP 주소입니다.
/home/admin/ansible/newrole.yml 이라는 플레이북(playbook)을 다음과 같이 역할(role)로 사용하도록 만드십시오: 
플레이북은 webservers 호스트 그룹의 호스트에서 실행됩니다.

 

더보기

7. Create a role called apache in /home/admin/ansible/roles with the following requirements:

  - The httpd package is installed, enabled on boot, and started

  - The firewall is enabled and running with a rule to allow access to the web server

  - A template file Index.html.j2 exists and is used to create the file /var/www/html/Index.html with the following output:

Welcome to HOSTNAME on IPADDRESS

 

where HOSTNAME is the fully qualified domain name of the managed node and IPADDRESS is the IP address of the managed node.

 

Create a playbook called /home/admin/ansible/newrole.yml that uses this role as follows:

The playbook runs on hosts in the webservers host group

 

1. apache role의 스켈레톤(skelton) 생성

$ cd ~/ansible

ansible-galaxy init apache

 

 

2. templates 디렉터리의 index.html.j2 파일 작성 

$ vi ~/ansible/roles/apache/templates/index.html.j2

Welcome to {{ ansible_fqdn }} on {{ ansible_default_ipv4.address }}

🔥 ansible_fqdn인 이유는 영어 원본을 보면 fully qualified domain name 라고 적혀있기 때문이다🔥 

그치만 실전에서 ansible_hostname을 적었다..

 

 

3. ansible facts 찾기

ansible localhost -m setup -a 'filter=ansible_hostname'
ansible localhost -m setup -a 'filter=ansible_default_ipv4'

 

또는

ansible localhost -m setup | less

 

를 사용하여 ansible_fqdn, ansible_default_ipv4.address 찾기 

 

 

4. tasks 디렉터리의 main.yml 작성하기

$ vi ~/ansible/roles/apache/tasks/main.yml

---
# tasks file for apache
- name: STEP1. install httpd
  yum:
    name: httpd
    state: latest
 
- name: STEP2. Start service httpd
  service:
    name: httpd
    enabled: yes
    state: started
 
- name: STEP3. Start service firewalld
  service:
    name: firewalld
    enabled: yes
    state: started
 
- name: STEP4. Add service firewalld
  firewalld:
    service: http
    state: enabled
    permanent: yes
    immediate: yes
 
- name: Create index.html
  template:
    src: index.html.j2
    dest: /var/www/html/index.html

 

[참고사항]

- ansible-doc yum

- ansible-doc service

- ansible-doc firewalld

- ansible-doc template

 

 

newrole.yml 작성

$ vi ~/ansible/newrole.yml

---
- hosts: webservers
  roles:
    - apache

 

$ ansible-playbook newrole.yml

 

 

prod 그룹의 node3, node4 결과 확인

 

$ curl 172.24.1.8

Welcome to node3.domain1.example.com on 172.24.1.8

 

$ curl 172.24.1.9

Welcome to node4.domain1.example.com on 172.24.1.9

 

 

 

8. Use roles from Ansible Galaxy (Ansible Galaxy에서 역할 사용하기)

다음 요구사항을 갖는 /home/admin/ansible/roles.yml 이름의 playbook을 생성합니다:

     

balancers 호스트 그룹에서 실행되며 balancer role을 사용하는 play가 포함되어야 합니다. 
이 role은 webservers 호스트 그룹 내의 호스트 사이에서 웹 서버 요청을 로드 밸런싱하는 서비스를 구성합니다. 

예를 들어 http://node5.domain1.example.com/을 브라우징하면 다음 출력이 생성됩니다 

Welcome to node3.domain1.example.com on 172.24.1.8 


브라우저를 다시 로드하면 대체 웹 서버에서 출력을 생성합니다: 
Welcome to node4.domain1.example.com on 172.24.1.9

 

webservers 호스트 그룹에서 실행되며 phpinfo role을 사용하는 play가 포함되어야 합니다.
   webservers 호스트 그룹 내의 호스트에서 /hello.php URL로 브라우징하면 다음 출력이 생성됩니다: 

 

      Hello PHP World from FQDN

 

여기서 FQDN은 호스트의 완전한 도메인 이름입니다. 
예를 들어 http://node3.domain1.example.com/hello.php을 브라우징하면 다음 출력이 생성됩니다:

 

      Hello PHP World from node3.domain1.example.com

 

http://node4.domain1.example.com/hello.php를 브라우징하면, PHP 구성의 여러 세부 정보와 함께 다음과 같은 출력이 생성됩니다.

 

      Hello PHP World from node4.domain1.example.com

 

PHP 구성의 다양한 세부 정보와 설치된 PHP 버전을 포함하여 출력됩니다.

 

더보기

8. Create a playbook called /home/admin/ansible/roles.yml with the following requirements:

The playbook contains a play that runs on hosts in the balancers host group and uses the balancer role

      This role configures a service to load balance web server requests between hosts in the webservers host group.

      Browsing to hosts in the balancers host group(for example http://node5.domain1.example.com/) produces the following output:

 

      Welcome to node3.domain1.example.com on 172.24.1.8

      Reloading the browser produces output from the alternate web server:

      Welcome to node4.domain1.example.com on 172.24.1.9

 

The playbook contains a play that runs on hosts in the webserver host group and uses the phpinfo role

      Browsing to hosts in the webservers host group with the URL /hello.php produces the following output:

 

      Hello PHP World from FQDN

      wherer FQDN is the fully qualified domain name of the host. For example, browsing to http://node3.domain1.example.com/hello.php produces the following output:

 

Hello PHP World from node3.domain1.example.com

 

      along with various details of the PHP configuration including the version of PHP that is installed. Similarly, browsing to http://node4.domain1.example.com/hello.php produces the following output:

 

    Hello PHP World from node4.domain1.example.com

 

      along with various details of the PHP configuration including the version of PHP that is installed

 

 

$ vi ~/ansible/roles.yml 

 phpinfo를 먼저 쓸 것

---
- hosts: webservers
  become: true
  roles:
    - phpinfo

 
- hosts: balancers
  become: true
  roles:
    - balancer

 

$ ansible-playbook roles.yml

 

 

balancers 결과 확인 (로드 벨런싱이 정상적으로 출력되는지 확인

 

$ curl http://node5.domain1.example.com

Welcome to node3.domain1.example.com on 172.24.1.8

 

$ curl http://node5.domain1.example.com

Welcome to node4.domain1.example.com on 172.24.1.9

 

 

hello.php 결과 확인

$ curl http://node3.domain1.example.com/hello.php/hello.php

Hello PHP World from node3.domain1.example.com

 

$ curl http://node4.domain1.example.com/hello.php/hello.php

Hello PHP World from node4.domain1.example.com

 

 

 

9. Create and use a logical volume (Logical Volume (LV) 생성 및 사용하기)

문제) 모든 관리 노드에서 실행되는 /home/admin/ansible/lv.yml이라는 플레이북을 만들어서 다음을 수행하십시오:

다음 요구 사항을 갖춘 논리 볼륨을 만듭니다. 
- 논리 볼륨은 research 볼륨 그룹에 생성됩니다. 
- 논리 볼륨 이름은 데이터입니다. 
- 논리 볼륨 크기는 1500 MiB입니다.

 

- ext4 파일 시스템으로 논리 볼륨을 포맷합니다. 
- 요청한 논리 볼륨 크기를 만들 수 없는 경우 오류 메시지 해당 크기의 논리 볼륨을 만들 수 없습니다. 가 표시되며 크기 800 MiB 대신 사용됩니다. 
- 볼륨 그룹 research가 없는 경우 오류 메시지 볼륨 그룹이 없습니다. 가 표시됩니다. 
- 논리 볼륨을 어떤 방식으로도 마운트하지 않습니다.

 

더보기

9. Create a playbook called /home/admin/ansible/lv.yml that runs on all managed nodes that does the following:

 

 Create a logical volume with these requirements:

      - The logical volume is created in the research volume gorup

      - The logical volume name is data

      - The logical volume size is 1500 MiB

 

 Formats the logical volume with the ext4 filesystem

 - If the requested logical volume size cannot be created the error message

    Cloud not create logical volume of that size

    should be displayed and the size 800 MiB should be used instead

 - If the volume group research does not exist, the error message

    Volume group does not exist

    should be displayed

- Does NOT mount the logical volume in any way

 

$ vi ~/ansible/lv.yml

---
- hosts: all
  tasks:
  - block:
      - name: Create a logical volume of 1500m
        lvol:
          vg: research
          lv: data
          size: 1500m
      - name: Create a ext4
        filesystem:
          fstype: ext4
          dev: /dev/research/data
    rescue:
      - debug:
          msg: Could not create logical volume of that size
      - name: Create a logical volume of 800m
        lvol:
          vg: research
          lv: data
          size: 800m
        when: ansible_lvm.vgs.research is defined
        ignore_errors: yes
      - debug:
          msg: Volume group done not exist
        when: ansible_lvm.vgs.research is undefined

 

[참고] ansible-doc lvol

 

 결과확인 :  ansible all -m command -a "명령어"

  • lvdisplay 명령어로 논리 볼륨을 확인
  • lsblk 명령어로 블록 디바이스 목록을 확인
  • df -h 명령어로 파일 시스템이 올바르게 생성되었는지 확인

 

 

 

10. Generate a hosts file (Hosts 파일 생성하기)

http://rhgls.domain1.example.com/material/hosts.j2에서 초기 템플릿 파일을 /home/admin/ansible에 다운로드합니다.
템플릿을 완성하여 /etc/hosts와 동일한 형식의 각 인벤토리 호스트에 대한 라인이 생성될 수 있도록합니다. 
http://rhgls.domain1.example.com/materials/hosts.yml에서 파일을 /home/admin/ansible/hosts.yml로 다운로드합니다.
이 플레이북은 템플릿을 사용하여 dev 호스트 그룹의 호스트에서 /etc/myhosts 파일을 생성합니다.

 

플레이북에는 변경하지 마세요.

 

플레이북을 실행하면 dev 호스트 그룹의 호스트에서 /etc/myhosts 파일에 각 관리 호스트에 대한 라인이 있어야합니다.

127.0.0.1 localhost localhost.localdomain localhosts4 localhosts4.localdomain4 ::1 localhost localhost.localdomain localhosts6 localhosts6.localdomain6

172.24.1.6 node1.damain1.example.com node1 
172.24.1.7 node2.damain1.example.com node2 
172.24.1.8 node3.damain1.example.com node3 
172.24.1.9 node2.damain1.example.com node4 
172.24.1.10 node5.damain1.example.com node5

참고 : 인벤토리 호스트 이름이 나타나는 순서는 중요하지 않습니다.

 

더보기

 10. Download an initial template file from http://rhgls.domain1.example.com/material/hosts.j2 to /home/admin/ansible

Complete the template so that it can be used to generate a file with a line for each inventory host in the same format as /etc/hosts

Download the file from http://rhgls.domain1.example.com/materials/hosts.yml to /home/admin/ansible/hosts.yml. This playbook will use the template to

      generate the file /etc/myhosts on hosts in the dev host group.

 

 Do not make any changes the play book

 

When the playbook is run, the file /etc/myhosts on hosts in the dev host group should have a line for each managed host:

 

127.0.0.1 localhost localhost.localdomain localhosts4 localhosts4.localdomain4

::1 localhost localhost.localdomain localhosts6 localhosts6.localdomain6

 

172.24.1.6 node1.damain1.example.com node1

172.24.1.7 node2.damain1.example.com node2

172.24.1.8 node3.damain1.example.com node3

172.24.1.9 node2.damain1.example.com node4

172.24.1.10 node5.damain1.example.com node5

 

NOTE: The order in which the inventory host names appear is not important.

 

 

hosts.j2 파일내용

 

vi hosts.j2 

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

{% for host in groups['all'] %}
{{ hostvars[host]['ansible_fqdn'] }}
{{ hostvars[host]['ansible_default_ipv4']['address'] }} 
{{ hostvars[host]['ansible_hostname'] }}
{% endfor %}

#실제론 공백을 두고 한줄에 쓴다

 

$ vi ~/ansible/hosts.yml

---
- hosts: dev
  become: true
  tasks:
  - name: template hosts file
    template:
      src: hosts.j2
      dest: /etc/myhosts
    when: ansible_hostsname in groups ['dev']

 

결과 확인: ansible all -m command -a "cat /etc/myhosts "

 

 

 

 

11. Modify file content (파일 내용 수정하기)

다음과 같이 /home/admin/ansible/issue.yml 이라는 플레이북을 작성하세요. 

 

이 플레이북은 인벤토리 호스트 전체에서 실행됩니다.

이 플레이북은 /etc/issue 파일의 내용을 다음과 같이 변경합니다:

  - dev 호스트 그룹의 호스트에서는 다음과 같이 변경됩니다: Development

  - test 호스트 그룹의 호스트에서는 다음과 같이 변경됩니다: Test

  - prod 호스트 그룹의 호스트에서는 다음과 같이 변경됩니다: Production

 

더보기

11.  Create a playbook called /home/admin/ansible/issue.yml as follows:

The playbook runs an all inventory hosts

The playbook replaces the contests of /etc/issue with a single line of text as follow:

     - On hosts in the dev hosts group, the line reads: Development

     - On hosts in the test host group, the line reads: Test

     - On hosts in the prod host group, the line read: Production

 

 

$ vi issue.yml

---
- name: all
  hosts: all
  tasks:
  - name: Copy using Development
    copy:
      content: 'Development'
      dest: /etc/issue
    when: "inventory_hostname in groups['dev']"
 
  - name: Copy using Test
    copy:
      content: 'Test'
      dest: /etc/issue
    when: "inventory_hostname in groups['test']"
 
  - name: Copy using Production
    copy:
      content: 'Production'
      dest: /etc/issue
    when: "inventory_hostname in groups['prod']"

 

결과 확인: $ ansible all -m shell -a 'cat /etc/issue' 명령어로 관리노드의 /etc/issue 파일 확인

 

 

 

12. Create a web content directory (web 컨텐츠 디렉토리 생성하기) 

 

/home/admin/ansible/webcontent.yml이라는 플레이북을 다음과 같이 작성하세요:

 

플레이북은 dev 호스트 그룹의 관리 대상 노드에서 실행됩니다.

다음 요구 사항을 갖는 /webdev 디렉토리를 생성하세요.

  - 그룹 소유권이 webdev로 설정됩니다.

  - 일반 권한 : 소유자=읽기+쓰기+실행, 그룹=읽기+쓰기+실행, 다른 사용자=읽기+실행

               - 특수 권한 : 그룹 ID 설정됨

  - 심볼릭 링크 /var/www/html/webdev를 /webdev로 생성하세요.

  - /webdev/index.html 파일을 생성하고, 해당 파일 내용은 "Development"라는 단일 텍스트 라인이어야 합니다.

 - dev 호스트 그룹의 호스트에서 이 디렉토리를 브라우징하면(http://node1.domain1.example.com/webdev/), "Development"가 출력되어야 합니다.

 

더보기

12. Create a playbook called /home/admin/ansible/webcontent.yml as follows:

 

The playbook runs on managed nodes in the dev host group

Create the directory /webdev with the following requirements:

     - It is owned by the webdev group

     - It has regular permissions: owner=read+write+execute, group=read+write+execute, other=read+execute

     - It has special permissions: set group ID

Symbolically link /var/www/html/webdev to /webdev

Create the file /webdev/index.html with a single line of text that reads: Development

Browsing this directoryu on hosts in the dev host group (for example http://node1.domain1.example.com/webdev/) produces the following output: Development

 

$ vi ~/ansible/webcontent.yml

---
- name: webcontent
  hosts: dev
  tasks:
  - name: Create a directory
    file:
      path: /webdev
      state: directory
      group: webdev
      mode: '2775'
  - name: Create a symbolic link
    file:
      src: /webdev
      dest: /var/www/html/webdev
      state: link
  - name: Copy using Content
    copy:
      content: 'Development'
      dest: /webdev/index.html
      setype: httpd_sys_content_t

 

(참고사항: 실제시험에서는 webdev group 과 httpd서비스가 자동으로 기동 및 설정 되어있다고 한다)

 

결과 확인

$ curl http:// 172.24.1.6/webdev/
Development

 

 

 

 

 

13. Generate a hardware report (하드웨어 보고서 생성하기)

/home/admin/ansible/hwreport.yml 이름의 playbook을 생성하여 다음 정보가 있는 모든 관리 노드에 /root/hwreport.txt 출력 파일을 생성하십시오. 

 

  - 인벤토리 호스트 이름 
  - 메모리 용량(MB) 
  - BIOS 버전 
  - 디스크 장치 vda의 크기 
  - 디스크 장치 vdb의 크기 
  - 출력 파일의 각 줄에는 하나의 키 = 값 쌍이 포함됩니다.

 

이 Playbook은 다음을 수행해야합니다. 
  - http://rhgls.domain1.example.com/materials/hwreport.empty 파일을 다운로드하고 /root/hwreport.txt로 저장합니다. 
  - /root/hwreport.txt를 올바른 값으로 수정합니다. 
  - 하드웨어 항목이 존재하지 않으면 연관된 값은 NONE으로 설정해야합니다.

 

더보기

13. Create a playbook called /home/admin/ansible/hwreport.yml that produces an output file called /root/hwreport.txt on all managed nodes with the following information:

 

- Inventory host name

- Total memory in MB

- BIOS version

- Size of disk device vda

- Size of disk device vdb

- Each line of the output file contains a single key = value pair.

 

Your Playbook should:

- Download the file from http://rhgls.domain1.example.com/materials/hwreport.empty and save it as /root/hwreport.txt

- Modify /root/hwreport.txt with the correct values

- If a hardware item does not exist, the associated value should be set to NONE

 

 

$ vi ~/ansible/hwreport.yml

---
- name: Make hwreport
  hosts: all
  vars:
    hw_all:
    - hw_name: HOST
      hw_cont: "{{ inventory_hostname | default('NONE', true) }}"
    - hw_name: MEMORY
      hw_cont: "{{ ansible_memtotal_mb | default('NONE', true) }}"
    - hw_name: BIOS
      hw_cont: "{{ ansible_bios_version | default('NONE', true) }}"
    - hw_name: SDA
      hw_cont: "{{ ansible_devices.sda.size | default('NONE', true) }}"
    - hw_name: SDB
      hw_cont: "{{ ansible_devices.sdb.size | default('NONE', true) }}"
  tasks:
  - name: download hwreport
    get_url:
      url: http://rhgls.domain1.example.com/materials/hwreport.empty
      dest: /root/hwreport.txt
  - name: hwreport
    lineinfile:
      path: /root/hwreport.txt
      regexp: '^{{ item.hw_name }}='
      line: "{{ item.hw_name }}={{ item.hw_cont }}"
    loop: "{{ hw_all }}"

 

결과 확인: 

$ ansible all -m shell -a 'cat /root/hwreport.txt'

 

 

 

 

14. Create a password vault (비밀번호 보관소 생성하기)

다음과 같이 사용자 비밀번호를 저장하기 위한 Ansible 보안 저장소(vault)를 생성합니다: 

 

저장소 이름은 /home/admin/ansible/locker.yml 입니다. 
저장소에는 다음과 같은 이름과 값의 두 가지 변수가 포함됩니다: 
  - pw_developer의 값은 Imadev 입니다. 
  - pw_manager의 값은 Imamgr 입니다. 
저장소를 암호화하고 복호화하기 위한 비밀번호는 whenyouwlshuponastar 입니다.
비밀번호는 /home/admin/ansible/secret.txt 파일에 저장됩니다.

 

더보기

14. Create an Ansible vault to store user passwords as follows:

The name of the vault is /home/admin/ansible/locker.yml

The vault contains two variables with names:

  - pw_developer with value Imadev

  - pw_manager with value Imamgr

  - The password to encrypt and decrypt the vault is whenyouwlshuponastar

  - The password is stored in the file /home/admin/ansible/secret.txt

풀이

$ echo 'whenyouwishuponastar' > /home/admin/ansible/secret.txt

$ chmod 0600 /home/admin/ansible/secret.txt 🔥🔥🔥🔥

 

$ vi /home/admin/ansible/ansible.cfg

vault_password_file = /home/admin/ansible/secret.txt

 

$ ansible-vault encrypt locker.yml

 

결과확인

$ ansible-vault view locker.yml

pw_developer: Imadev
pw_manager: Imamgr

 

 

 

 

15. Create user accounts (사용자 계정 생성하기)

 

- http://rhgls.domain1.example.com/materials/user_list2.yml에서 생성할 사용자 목록을 다운로드하여 /home/admin/ansible에 저장합니다. 

- 이전에 생성한 비밀번호 보관함인 /home/admin/ansible/locker.yml을 사용하여 /home/admin/ansible/users.yml이라는 플레이북을 생성하여 다음과 같이 사용자 계정을 생성합니다: 

직무가 developer인 사용자는 다음과 같이 처리됩니다: 
- dev 및 test 호스트 그룹의 관리 노드에서 생성됩니다. 
- pw_developer 변수에서 비밀번호를 할당받으며, 30일 후에 비밀번호가 만료되도록 설정합니다.
- 부가 그룹 devops의 멤버가 됩니다.

직무가 manager인 사용자는 다음과 같이 처리됩니다: 
 - prod 호스트 그룹의 관리 노드에서 생성됩니다. 
 - pw_manager 변수에서 비밀번호를 할당받으며, 30일 후에 비밀번호가 만료되도록 설정합니다.
          - 부가 그룹 opsmgr의 멤버가 됩니다.

비밀번호는 SHA512 해시 형식을 사용해야 합니다. 
이 플레이북은 이전에 생성한 비밀번호 파일 /home/admin/ansible/secret.txt를 사용하여 작동해야 합니다.

 

더보기

15. Download a list of users to be created from http://rhgls.domain1.example.com/materials/user_list2.yml and save it to /home/admin/ansible

Using the password vault /home/admin/ansible/locker.yml created elsewhere in this exam create a playbook called /home/admin/ansible/users.yml that

     creates user accounts as follows:

  Users wich a job description of developer should be:

      - created on managed nodes in the dev and test host group

      - assigned the password from the pw_developer variable and should have password that expire after 30 days

      - a member of supplementary group devops

 

  Users with a job description of manager should be:

        - created on managed nodes in the prod host gorup

        - assigned the password from the pw_manager variable should have password that expire after 30 days

        - a member of supplementary group opsmgr

 

- password should use the SHA512 hash format

- Your playbook should work using the vault password file /home/admin/ansible/secret.txt created elsewhere in this exam.

 

 

$ vi ~/ansible/users.yml 

---
- hosts: localhost
  connection: local
  become: true
 
  tasks:
  - name: download a user_list.yml
    get_url:
      url: http://rhgls.domain1.example.com/materials/user_list2.yml
      dest: /home/admin/ansible

 
- hosts: dev,test
  become: true
  vars_files:
    - locker.yml
    - user_list.yml
  tasks:
  - name: create a group
    group:
      name: devops
      state: present
 
  - name: run to developer
    user:
      name: '{{ item.name }}'
      comment: '{{ item.job }}'
      password: "{{ pw_developer | password_hash('sha512') }}"
      groups: devops
      append: yes
      password_expire_max: 30
    loop: '{{ users }}'
 
- hosts: prod
  become: true
  vars_files:
    - locker.yml
    - user_list.yml
  tasks:
  - name: create a group
    group:
      name: opsmgr
      state: present
 
  - name: run to manager
    user:
      name: '{{ item.name }}'
      comment: '{{ item.job }}'
      password: "{{ pw_manager | password_hash('sha512') }}"
      groups: opsmgr
      append: yes
password_expire_max: 30
    loop: '{{ users }}'

 

$ ansible-playbook users.yml

 

결과확인

ansible all -m shell -a "id node1".. 이런식으로 확인해보기  

 

 

 


16. Rekey an Ansible vault (Ansible Vault 키 재생성)

다음과 같이 기존 ansible 보안 저장소의 비밀번호를 변경하세요: 

 

http://rhgls.domain1.example.com/materials/salaries.yml 에서 Ansible 보안 저장소를 다운로드하여 /home/admin/ansible 저장합니다. 
  - 현재 저장소의 비밀번호는 insecure4sure 입니다. 
  - 새 저장소 비밀번호는 bbe2de98389b입니다. 
  - 새로운 비밀번호로 저장소는 암호화된 상태로 유지됩니다.

 

더보기

16.  Rekey an existing ansible vault as follows:

 

Download the Ansible vault from http://rhgls.domain1.example.com/materials/salaries.yml to /home/admin/ansible

  - The current vault password is insecure4sure

  - The new vault password is bbe2de98389b

  - The vault remains in an encrypted state with the new password

 

$ cd /home/admin/ansible
$ wget http://rhgls.domain1.example.com/materials/salaries.yml
$ ansible-vault rekey --ask-vault-pass salaries.yml

Vault password: insecure4sure
New Vault password: bbe2de98389b
Confirm New Vault password: bbe2de98389b
Rekey successful

 

 결과 확인: $ ansible-vault view salaries.yml

 

 

 

 

17. Configure a cron job  (크론작업 설정하기)

/home/admin/ansible/cron.yml라는 이름의 playbook을 만드세요. 이 playbook은 모든 관리 대상 호스트에서 실행되며 다음과 같이 사용자 natasha의 크론 작업을 만듭니다.

 

사용자 natasha는 매 2분마다 실행되고 logger "EX294 in progress"를 실행하는 크론 작업을 설정해야 합니다.

 

더보기

17. Create a playbook called /home/admin/ansible/cron.yml that runs on all managed hosts and creates a cron job for user natasha as follows:

The user natasha must configure a cron job that runs every 2 minutes and executes logger "EX294 in progress"

 

$ vi ~/ansible/cron.yml 

---
- name: cron
  hosts: all
  tasks:
  - name: add cron
    cron:
      name: add cron natasha
      minute: "*/2"
      user: natasha
      job: logger "EX294 in progress"

 

$ ansible-playbook cron.yml

결과확인:

ansible all -m command -a "crontab -l -u natasha"

*/2 * * * * logger "EX294 in progress"

 

 

참고: 

- https://maru1000.tistory.com/92?category=1120346 

- https://tkqltm.tistory.com/19

+ Recent posts