클라우드 환경설정

본 부록에서는 JEUS를 클라우드 환경에서 이용하는 방법을 설명한다.

개요

클라우드 서버가 정상적으로 동작하기 위해서는 다음과 같은 설정이 필요하다.

  • JEUS_HOME/lib/csp 경로에 있는 Cloud Service Provider(CSP) 파일을 JEUS_HOME/lib/system 경로에 위치시킨다.

  • JEUS 클라우드 라이선스를 JEUS_HOME/license 경로에 위치시킨다.

  • 클라우드 서버들을 동일한 SCF 그룹으로 구성하기 위해 다음 중 하나를 설정해야 한다.

    • -Djeus.scf.group-id 속성을 동일한 값으로 설정한다.

    • JEUS_HOME/domains/<DOMAIN_NAME>/config/domain.xml 파일의 <id> 값을 동일한 값으로 설정한다.

Kubernetes

Kubernetes는 컨테이너 관리 자동화를 위한 오픈 소스 플랫폼으로, 대부분의 PaaS 클라우드에서 기본적으로 제공하는 리소스이다. 본 절에서는 Docker 및 Kubernetes 기반 PaaS 클라우드 환경(OpenShift)을 기준으로 JEUS 설정 방법을 설명한다.

JEUS를 OpenShift에서 사용하기 전에 다음 준비 사항을 확인한다.

다음은 OpenShift(Kubernetes) 환경에서 JEUS를 사용하기 위한 설정 절차이다.

  1. 마스터/노드 서버를 실행한다.

  2. 마스터 API 서버 접근 권한을 부여한다. ([참고] Kubernetes 공식 문서)

    컨테이너에서 기동된 JEUS 간 정보 공유를 위해 Kubernetes API 서버를 사용한다. 기본적으로 계정은 API 접근이 제한되므로 적절한 권한 설정이 필요하다. 관련 설정은 아래 항목을 참고한다.

  3. API 서버 접근을 위한 컨테이너 환경 변수를 다음과 같이 설정한다. ([참고] Kubernetes 공식 문서)

    jeusContainerExample.yaml
    spec:
      containers:
      - name: jeus-container
        env:
        - name: API_VERSION
          value: "v1"
        - name: KUBERNETES_NAMESPACE
          value: "default"
  4. Pod를 배포하고 상태를 확인한다.

  5. EC2 리소스를 시작하고 SCF 그룹 구성을 확인한다.

SCF 그룹 구성 Provider

JEUS는 Kubernetes 환경에서 SCF 그룹 구성을 위해 다음 2가지의 Provider 유형을 제공한다.

Provider 설명

kube-provider

Kubernetes API 서버를 통해 Pod IP 정보를 조회하고 SCF 그룹을 구성한다.

kube-dns-provider

Kubernetes DNS를 통해 Pod 정보를 조회하고 SCF 그룹을 구성한다.

  • Provider 통신 방식

    항목 kube-provider kube-dns-provider

    통신 방식

    Pod IP 기반 직접 통신

    DNS 기반 통신

    장점

    • 낮은 지연 시간

    • 직접 통신으로 DNS 의존성 감소

    • 간편한 구성

    • DNS 이름 사용으로 가독성 높음

    단점

    • 권한 설정 필요

    • IP 변경 관리 필요

    • CoreDNS 장애 시 통신 불가

    • DNS 지연 발생 가능

  • Provider 설정 요구사항

    항목 kube-provider kube-dns-provider

    ClusterRole / ClusterRoleBinding

    필수

    불필요

    Pod / Deployment

    N/A

    KUBERNETES_SUBDOMAIN 설정

    Service

    N/A

    clusterIP: None (Headless Service) 설정

환경 변수

  • kube-provider

    환경 변수 설명

    API_VERSION

    Kubernetes API 버전

    KUBERNETES_NAMESPACE

    Deployment, Service, Pod를 분리할 때 사용하는 네임스페이스

    MASTER_PROTOCOL

    마스터 호스트 프로토콜

    KUBERNETES_SERVICE_HOST

    마스터 호스트 주소

    KUBERNETES_SERVICE_PORT

    마스터 포트

    KUBERNETES_CLIENT_CERTIFICATE_FILE

    클라이언트 인증서 파일 경로

    KUBERNETES_CLIENT_KEY_FILE

    클라이언트 키 파일 경로

    KUBERNETES_CLIENT_KEY_PASSWORD

    클라이언트 키 암호

    KUBERNETES_CLIENT_KEY_ALGORITHM

    클라이언트 키 알고리즘

    KUBERNETES_CA_CERTIFICATE_FILE

    CA 인증서 파일 경로

    KUBERNETES_LABELS

    같은 네임스페이스 내에서 클러스터 분리에 사용하는 레이블

  • kube-dns-provider

    환경 변수 설명

    KUBERNETES_SUBDOMAIN

    DNS 도메인 값으로, 해당 DNS를 통해 멤버 이름을 가져올 때 사용한다. (필수)

  • License

    환경 변수 설명

    JEUS_LICENSE_FILE_PATH

    라이선스 파일 경로를 지정한다.

YAML

  • NameSpace

    Namespace는 Kubernetes 클러스터를 논리적으로 분리하기 위한 가상 공간이다. Pod, Service, Deployment 등을 그룹화하고 격리하는 용도로 사용한다. NameSpace명은 서비스명으로 설정을 권장하며 아닐 경우 “ns-jeus”로 정의한다.

    apiVersion: v1
    kind: Namespace
    metadata:
      creationTimestamp: null
      name: ns-jeus
    spec: {}
    status: {}
  • Service

    Service는 변하는 Pod들을 하나의 고정된 네트워크 엔트포인트로 묶어주는 객체이다. Service명은 서비스명으로 설정을 권장하며 아닐 경우 “svc-jeus”로 정의한다.

    apiVersion: v1
    kind: Service
    metadata:
      name: svc-jeus
      namespace: ns-jeus
      labels:
        vendor: tmax
    spec:
      type: NodePort              # Service 타입, 각 노드 포트를 외부에 개방, ClusterIP 기능 포함
      selector:
        app: jeus                # label app=jeus인 Pod들을 Service 대상에 포함
        vendor: tmax
      ports:
        - name: http
          port: 8088              # 서비스 내부 포트
          targetPort: 8088        # 실제 Pod가 리슨하는 포트, containerPort와 동일해야 함
          nodePort: 30300         # 노드에 실제로 열리는 포트
  • Deployment

    Deployment는 Pod의 배포, 확장, 업데이트, 롤백을 선언적으로 관리하는 용도로 사용한다. Deployment명은 서비스명으로 설정을 권장하며 아닐 경우 “deployment-jeus”로 정의한다.

    apiVersion: apps/v1
    kind: Deployment                    # Deployment 리소스 (ReplicaSet + Pod 관리)
    
    metadata:
      name: deployment-jeus             # Deployment 이름
      namespace: ns-jeus                  # 배포될 네임스페이스
      labels:
        app: jeus                       # 리소스 식별용 라벨 (Service selector와 매칭)
        vendor: tmax
    spec:
      replicas: 2                       # 유지시킬 Pod 개수
      selector:
        matchLabels:
          app: jeus                     # 이 Deployment가 관리할 Pod 라벨 조건
          vendor: tmax
      strategy:
        type: RollingUpdate             # 무중단 업데이트 방식 (기본값)
        rollingUpdate:
          maxUnavailable: 0             # 업데이트 시 기존 Pod를 0개까지만 비활성화 가능 (완전 무중단)
          maxSurge: 1                   # 업데이트 시 신규 Pod를 1개까지 추가 생성 가능
      template:                         # 실제 Pod 템플릿 정의
        metadata:
          labels:
            app: jeus                   # Pod 라벨 (Service가 이 라벨로 트래픽 전달)
            vendor: tmax
        spec:
          containers:                   # Container 이름
          - name: jeus
            command: ["sh", "/sw/jeus/bin/jeus.sh"]   # Container 시작 명령
            image: <image>
            imagePullPolicy: Always     # 항상 이미지 pull 하도록 설정
            ports:
            - containerPort: 8088       # Container가 listen하는 포트
            # ---------------- Health Check ----------------
            livenessProbe:              # Container가 살아있는지 확인
              tcpSocket:
                port: 8088              # 8088 포트 TCP 연결 여부로 체크
              initialDelaySeconds: 60   # Container 기동 후 60초 뒤부터 검사
              periodSeconds: 10         # 10초마다 검사, 실패 시 Container 재시작
    
            readinessProbe:             # 트래픽 수용 가능 여부 확인
    
              tcpSocket:
                port: 8088              # 포트 open 여부로 준비 상태 판단
              initialDelaySeconds: 60   # JEUS 기동 고려 시간 설정
              periodSeconds: 10         # 10초마다 검사, 실패 시 Service 내 트래픽 제외
            # ------------------------------------------------
            resources:
              limits:
                cpu: 1500m              # 최대 CPU 1.5 Core
                memory: 1500Mi          # 최대 메모리 1.5GB
              requests:
                cpu: 500m               # 최소 보장 CPU 0.5 Core
                memory: 512Mi           # 최소 보장 메모리 512MB
            env:
            - name: TZ                     # Container 타임존 설정
              value: Asia/Seoul
            - name: KUBERNETES_NAMESPACE   # 네임스페이스 정보
              value: ns-jeus
            - name: KUBERNETES_LABELS      # Pod 라벨 정보
              value: app=jeus
            - name: API_VERSION            # API 버전 정보
              value: v1
            volumeMounts:
            - name: jeus-domain-template
              mountPath: "/sw/jeus/bin/conf/domain.xml"
              subPath: domain.xml                        # ConfigMap의 domain.xml 파일 마운트
          volumes:
          - name: jeus-domain-template
            configMap:
              name: jeus-domain-xml                      # domain.xml 제공 ConfigMap
              defaultMode: 0644
  • ConfigMap

    환경 설정 데이터를 Key-Value 쌍으로 저장하는 데 사용되는 리소스이다. 이미지 안에 설정파일을 넣을 경우 설정 교체될 때마다 새로운 이미지가 필요하기 때문에 ConfigMap으로 JEUS의 domain.xml과 같은 설정파일을 별도로 관리하여 이식성과 유연성을 높일 수 있다.

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: jeus-domain-xml
      namespace: ns-jeus
    data:
      domain.xml:
        <?xml version="1.0" encoding="utf-8"?>
        <domain xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="8.6">
            <production-mode>true</production-mode>
            <id>%DOMAIN_ID%</id>
            <master-server-name>%SERVERNAME%</master-server-name>
            <security-manager>
                 <default-application-domain>SYSTEM_DOMAIN</default-application-domain>
                 <security-domain-names>
                 <security-domain-name>SYSTEM_DOMAIN</security-domain-name>
            </security-domain-names>
        </domain>
  • ClusterRole

    Kubernetes는 RBAC(Role Based Access Control) 매커니즘을 통해서 클러스터 리소스에 대한 접근을 제어한다. ClusterRole은 네임스페이스 범위에 제한되지 않고 클러스터(k8s) 전역에서 사용 가능한 API 권한을 정의하는 객체이다.

    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: pod-reader
    rules:
    - apiGroups: [""]
      resources: ["*"]
      verbs: ["get", "watch", "list"]
  • ClusterRoleBinding

    정의된 ClusterRole을 ServiceAccount, User, Group과 같은 주체에 바인딩하여 실제 권한을 부여하는 역할을 수행한다.

    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: read-pods
    subjects:
    - kind: Group
      name: system:serviceaccounts
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: pod-reader
      apiGroup: rbac.authorization.k8s.io

kube-dns-provider 설정 예시

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jeus-deployment
...
spec:
  subdomain: jeus-svc
  containers:
    ...
    env:
      ...
      - name: JEUS_SCF_ID
        value: "JEUS"
      - name: KUBERNETES_SUBDOMAIN
        value: "jeus-svc"
---
apiVersion: v1
kind: Service
metadata:
  name: jeus-svc
...
spec:
  clusterIP: None
...
Provider 설정은 Provider 설정 요구사항을 참고한다.

License

License는 Pod가 스케줄된 Node의 HostName과 일치해야 한다. Pod 외부에 존재하는 License 파일은 컨테이너 내부에서 직접 접근할 수 없으므로, Kubernetes의 Volume을 이용하여 해당 파일을 Pod 내부 경로에 마운트해야 한다.

Pod 외부의 License 파일을 사용하는 방식은 다음 두 가지를 권장한다.

  • hostPath

    • Host 장비의 로컬 경로를 Pod에 직접 마운트하는 방식이다.

    • 특정 노드에 종속되며, 해당 파일이 존재하는 노드에서만 사용 가능하다.

  • 공유 스토리지 및 PV/PVC

    • NFS와 같은 공유 스토리지를 PersistentVolume(PV)로 정의하고, PersistentVolumeClaim(PVC)을 통해 Pod에 연결하는 방식이다.

    • 여러 Pod에서 공통으로 접근해야 하거나, 노드 이동 시에도 동일한 파일을 사용해야 하는 경우 적합하다.

hostPath 설정 예시

apiVersion: apps/v1
kind: Deployment
...
spec:
  ...
  template:
    spec:
      volumes:
        - name: license-vol                       // 볼륨 이름 정의
          hostPath:
            path: /home/tmax/cloud/license.tmax   // Host 장비 실제 파일 경로
            type: File                            // 파일 타입 지정
      containers:
      - name: jeus
        image: <image>
        volumeMounts:
          - name: license-vol                      // 위에서 정의한 볼륨 연결
            mountPath: /home/tmax/jeus8/license/license.tmax       // 컨테이너 내부 경로
hostPath 방식 사용 시, Pod가 배치되는 Node의 호스트네임과 일치하는 라이선스 파일이 각 Node의 로컬 경로에 반드시 존재해야 한다.

공유 스토리지 및 PV/PVC 설정 예시

공유 스토리지를 사용할 경우, PV/PVC를 통해 스토리지를 연결한 뒤 JEUS에서 제공하는 JEUS_LICENSE_FILE_PATH 환경 변수를 사용하여 라이선스 경로를 지정한다.

apiVersion: apps/v1
kind: Deployment
...
spec:
  ...
  template:
    spec:
      volumes:
        - name: license-vol
          persistentVolumeClaim:
            claimName: jeus-license-pvc       // 사용자가 추가한 PVC 연결
      containers:
      - name: jeus
        image: <image>
        volumeMounts:
          - name: license-vol             // PVC 볼륨 mount
            mountPath: /home/tmax/license // 컨테이너 내부 경로
        ...
        env:
          - name: JEUS_LICENSE_FILE_PATH              // 라이선스 경로지정 환경 변수
            value: "/home/tmax/license/license.tmax"  // 라이선스 파일 경로
공유 스토리지 사용 시, License 파일은 PV에 연결된 실제 스토리지(NFS 등)에 위치해야 하며, 컨테이너 내부에서는 마운트된 경로를 통해 접근한다.