홍미 노트 10 프로 통화녹음멘트 없애기

관리자 자료실|2023. 3. 6. 11:20
반응형

홍미노트 10프로나 11프로나 비슷한 버전은 다 될듯 하다.

원래 안드로이드 롬을 인도네시아롬으로 바꿔 사용하면 되지만

앱을 여러개 설치하여 사용중이라면 새로 설치하고 데이터를 옮기기 번거로우므로

아래 순서대로만 진행하여 사용하도록 하자.

 

1. 구글플레이에서 'TTSLexx' 설치 (검정 동그라미에 노란색 글씨 아이콘)

 

2. 스마트폰 '설정' 에서 > '텍스트 음성 출력' 검색 및 실행

    > 기본엔진을 'TTSLexx' 선택, 주의사항 동의

 

3. '전화' 앱정보에서 데이터 삭제 (저장용량 비우기) & 업데이트 제거

 

4. 초기 상태에서 'phone' 앱이 업데이트가 되지 않도록 해야한다.

    업데이트 될때, 통화 녹음 멘트가 자동으로 살아나기 때문이다.

    구글플레이 'Google의 전화 앱' 상세 페이지에서 우측 상단 '점 세개' 선택 > 자동 업데이트 사용 (체크 해제)

 

이제 114 등으로 전화 걸어 자동응답이 나올때 녹음 테스트를 해보자.

혹시 처음에 통화 녹음 멘트가 나오더라도 반복 테스트 해보면 안나오는 것을 알 수 있다.

 

반응형

댓글()

Openshift 4.12.0 응용프로그램 배포 - 개발 언어 (PHP, Python, Go, NodeJS, Java, Ruby)

리눅스/OpenShift|2023. 2. 22. 08:50
반응형

본 문서는 공식 Documents 를 참고하여 작성하였습니다.

https://docs.openshift.com/container-platform/4.12/openshift_images/create-images.html

 

여기에서 잘 되지 않아 헤매었는데, 현재까지 시행착오를 겪고 이해한 바로는 이렇습니다.

웹서버와 데이터베이스 Pod 는 가동 후 데이터 입력 및 설정을 추가로 하면 되는데,

개발 언어들은 이와 같은 방식으로 Pod 가동이 안됩니다.

(CrashLoopBackOff, Completed 또는 Error 발생)

 

개발 언어들은 두가지 (이미지 + 어플리케이션 소스 코드) 가 올바로 준비되어야 Running 상태로 가동이 됩니다.

- 이미지 : 개발 언어 이미지

- 응용프로그램 소스 : 개발 언어를 이용하여 개발한 소스 코드

 

웹서버와 같이 oc new-app docker.io/php 명령으로 PHP 이미지를 사용하여 새로운 Pod 를 만들면
PHP 이미지에는 실행할 소스 코드가 포함되어 있지 않기 때문에 컨테이너가 Completed 상태로 종료됩니다.
그래서 PHP 응용프로그램을 실행하려면, 이미지에 개발한 소스 코드를 포함시켜야 합니다.

본 매뉴얼에서 진행한 테스트 절차는 아래와 같습니다.

- 개발 소스 준비 > build 하여 소스코드를 이미지에 삽입 > Registry 에 등록 > yaml 작성 > 응용프로그램 배포

 

* 사전 이해

- docker build 명령은 Dockerfile 을 사용하여 새로운 이미지를 빌드하고, 이 이미지를 로컬에 저장합니다.

  docker new-build 명령은 Dockerfile 을 사용하여 새로운 이미지를 빌드하지만, 이 이미지를 메모리에 저장합니다.

  로컬 머신의 디스크 공간을 덜 사용하기 때문에, 빌드 후 즉시 이미지를 삭제할 경우 유용합니다.

- oc new-build 명령은 새로운 Docker 이미지를 처음부터 빌드하는데 사용되며,

  oc start-build 명령은 이미 생성된 BuildConfig를 사용하여 새로운 빌드를 시작하는데 사용됩니다.

- Podman 은 Docker CLI 와 호환되는 CLI 와 API 를 제공하므로, 대부분의 Docker 명령어를 사용할 수 있습니다.

  하지만 Podman 으로 Docker 이미지를 빌드하거나 실행하려면 Docker 데몬이 설치되어 있어야 합니다.

  여기에서는 docker 로 설명 드리지만 docker, podman 패키지가 모두 설치된 상태에서는 podman 명령을 사용해도 무관합니다.

  # yum -y install docker

  # systemctl enable docker

  # systemctl start docker

 

* 프레임워크

개발 언어 컨테이너 만으로는 컨테이너 포트 활성화가 되지 않아 웹서버나 프레임워크를 이용하여 포트를 활성화하고 웹페이지를 확인합니다.

PHP 는 apache 웹서버가 내장된 이미지를 사용하면 포트를 활성화 하고 PHP 코드를 실행할 수 있습니다.

나머지 각 언어들은 다음과 같은 프레임워크를 사용하여 웹 어플리케이션을 개발할 수 있습니다. 그리고 내장된 웹서버를 활용할 수 있습니다.

- PHP : php-apache 이미지

- Ruby : Ruby on Rails, Sinatra
- Python : Django, Flask
- Go : Gin, Echo
- Node.js : Express, Koa
- Java : Spring, Struts

 

 

1. PHP 배포

 

Openshift에서 PHP 를 배포할 때, 포트를 열고 웹페이지를 출력하려면 PHP 어플리케이션을 웹서버와 함께 실행해야 합니다.

이를 위해서는 PHP 와 웹서버가 함께 포함된 이미지를 사용해야 하며, 단순히 PHP 이미지만 사용하는 것은 불가능합니다.
Apache 웹서버와 PHP 가 함께 포함된 이미지 중에서 가장 일반적으로 사용되는 것은 php-apache 이미지입니다.

이 이미지는 Apache 웹서버와 PHP 를 설치하고 구성하여 특정포트에서 애플리케이션을 실행할 수 있도록 합니다.

 

진행할 예제는 php:7.4-apache 기준으로 작성하였습니다.
우선 php:7.4-apache 이미지를 다운로드 합니다.

# docker pull docker.io/php:7.4-apache

 

테스트용으로 PHP 소스 파일을 만듭니다.

# mkdir ./source

# vi ./source/index.php

<?php
echo "Good job";
?>

 

Dockerfile 을 아래 내용으로 작성합니다.
# vi Dockerfile

FROM docker.io/php:7.4-apache

# Apache 설정
#RUN a2enmod rewrite

# 소스 복사
COPY ./source/ /var/www/html/

# PHP 확장기능 설치
#RUN docker-php-ext-install pdo_mysql

# 기본 포트 변경
RUN sed -i 's/Listen 80/Listen 8080/' /etc/apache2/ports.conf
RUN sed -i 's/Listen 443/Listen 8443/' /etc/apache2/ports.conf

# Apache 서버 시작
CMD ["apache2-foreground"]

 

기본포트 80, 443 등 로컬 haproxy 가 사용하는 포트는 사용하지 못하므로 8080, 8443 등으로 변경해서 사용해야 합니다.

변경하지 않고 이미지를 만들게 되면 해당 이미지로 생성한 Pod 에서 아래와 같은 에러 메세지를 볼 수 있습니다.

# oc logs <Pod 이름>
(13)Permission denied: AH00072: make_sock: could not bind to address [::]:80
(13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
AH00015: Unable to open logs

 

현재 디렉토리에 있는 Dockerfile 을 사용하여 Docker 이미지를 빌드 합니다.

형식) docker build --tag <새 이미지 이름> <Dockerfile 위치>

# docker build --tag my-app5 .

 

새로운 이미지가 확인 되었습니다.

# docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
my-app5                              latest              b0aeb2e3c8af        42 seconds ago      453 MB

docker.io/php                        7.4-apache          20a3732f422b        4 months ago        453 MB

 

새로 만든 PHP 이미지로 응용프로그램을 생성하고 상태를 확인합니다.

형식) oc new-app --image=<이미지 이름> --name=<Pod 이름 정하고 싶은 경우>

# oc new-app --image=my-app5

# oc get pods
NAME                           READY   STATUS             RESTARTS   AGE
my-app5-64b9b569fb-jlw5h   0/1     ImagePullBackOff   0          8s

 

* 에러 발생 이유

Pod 상태가 ErrImagePull / 자동 재시도 (또는 ImagePullBackOff / 완전 실패) 일 경우는 이미지가 존재하지 않거나 액세스 권한이 없는 경우 발생할 수 있습니다. 이러한 문제를 해결하려면, 이미지가 올바르게 빌드되어 이미지 레지스트리에 올바르게 업로드되었는지 확인하고, 이미지 레지스트리에 액세스 할 수 있는 권한을 가지고 있는지 확인해야 합니다.

그렇지만 저의 경우는 아래와 같았으며, 다른 방법으로 해결하였습니다.

 

로그를 살펴봅니다.

에러1

# oc logs my-app5-64b9b569fb-jlw5h
Error from server: Get "https://115.68.142.105:10250/containerLogs/project412/my-app5-64b9b569fb-jlw5h/my-app5": remote error: tls: internal error

 

위 로그는 TLS 연결 오류입니다. 만약 Docker가 로컬 호스트에 있는 경우, 인증서와 관련된 문제는 발생하지 않을 수 있습니다.

하지만 OpenShift 클러스터는 기본적으로 Docker 데몬을 직접 실행하지 않으므로, 로컬 호스트의 Docker 데몬에 이미지가 존재하는 경우에도 OpenShift 클러스터와 Docker 레지스트리 간의 연결 문제가 발생할 수 있습니다.

이 경우, oc new-app 명령어에서 Docker 이미지를 로컬 호스트의 Docker 데몬에서 가져오는 대신, OpenShift 클러스터 내에서 Docker 이미지를 빌드 하도록 지시할 수 있습니다. Dockerfile을 작성하고 oc new-build 명령어를 사용하여 Docker 이미지를 빌드해야 합니다.

 

[첫번째 방법]
다음과 같이 oc new-build 명령어를 사용하여 Dockerfile 을 빌드하면 됩니다.

 

형식) oc new-build --name=<app 이름> --binary --strategy=docker

# oc new-build --name=my-app --binary --strategy=docker

형식) oc start-build <app 이름> --from-dir=<Dockerfile 위치>

# oc start-build my-app --from-dir=.

형식) oc new-app <app 이름>

# oc new-app my-app

 

oc new-build 명령어는 이전에 생성된 Docker 이미지를 빌드하기 위한 빈 이미지 스트림을 만듭니다.

oc start-build 명령어는 이 이미지 스트림을 사용하여 Docker 이미지를 빌드합니다.

oc new-app 명령어는 이미지 배포 명령입니다.

 

[두번째 방법]

또는 아래와 같이 단순화 할 수 있습니다.

# oc import-image my-php:7.4-apache --from=docker.io/php:7.4-apache --confirm

 

이 명령어는 Docker Hub의 docker.io/php:7.4-apache 이미지를 가져와서 OpenShift 클러스터의 my-php:7.4-apache 이미지스트림으로 변환합니다. --confirm 옵션을 사용하면, 이미지스트림이 이미 존재할 경우 덮어쓰기를 확인하는 메시지가 표시됩니다.
이미지스트림으로 변환한 후에는, oc new-app 명령어에서 이미지스트림을 사용하여 애플리케이션을 배포할 수 있습니다.

 

형식) oc new-app <이미지스트림 이름>~<소스 위치>

# oc new-app my-php:7.4-apache~./source/

 

이 명령어는 my-php:7.4-apache 이미지스트림을 사용하여 새로운 애플리케이션을 생성하고, <path-to-source-code> 경로에 있는 소스 코드와 결합하여 배포합니다. (하지만 Dockerfile 추가 옵션 사용 불가)

 

에러2

# oc logs my-app11-6c7c9dcd7c-z6cww
Error from server (BadRequest): container "my-app11" in pod "my-app11-6c7c9dcd7c-z6cww" is waiting to start: trying and failing to pull image

 

위에러를 자세히 보기 위해 oc describe 명령을 사용합니다.

# oc describe pod my-app11-6c7c9dcd7c-z6cww
...

Events:
  Type     Reason          Age                From               Message
  ----     ------          ----               ----               -------
  Normal   Scheduled       16m                default-scheduler  Successfully assigned deploy/my-app11-6c7c9dcd7c-z6cww to worker01.az1.sysdocu.kr
  Normal   AddedInterface  16m                multus             Add eth0 [10.128.2.44/23] from openshift-sdn
  Normal   Pulling         14m (x4 over 16m)  kubelet            Pulling image "my-app11:latest"
  Warning  Failed          14m (x4 over 16m)  kubelet            Failed to pull image "my-app5:latest": rpc error: code = Unknown desc = reading manifest latest in docker.io/library/my-app5: errors: denied: requested access to the resource is denied
unauthorized: authentication required
  Warning  Failed   14m (x4 over 16m)   kubelet  Error: ErrImagePull
  Warning  Failed   14m (x6 over 16m)   kubelet  Error: ImagePullBackOff
  Normal   BackOff  69s (x63 over 16m)  kubelet  Back-off pulling image "my-app5:latest"

 

권한이 없어 인증이 필요하다는 것을 확인하였습니다.

이 문제는 아래와 같이 secret 을 생성해서 프로젝트에 권한을 부여하면 됩니다.

# oc create secret docker-registry docker-registry-login \
--docker-server=115.68.142.99:5000 \
--docker-username=sysdocu \
--docker-password=12345678 \
--namespace=project412
secret/docker-registry-login created

- 115.68.142.99 : 본 서버 (OCP 서버 IP)

 

# oc get secrets
NAME                       TYPE                                  DATA   AGE
builder-dockercfg-4jj5l    kubernetes.io/dockercfg               1      24h
builder-token-tpbk6        kubernetes.io/service-account-token   4      24h
default-dockercfg-hsnzx    kubernetes.io/dockercfg               1      24h
default-token-fps64        kubernetes.io/service-account-token   4      24h
deployer-dockercfg-l24hl   kubernetes.io/dockercfg               1      24h
deployer-token-wfrt8       kubernetes.io/service-account-token   4      24h
docker-registry-login      kubernetes.io/dockerconfigjson        1      35s

secret 생성을 확인하였습니다.

이제 해당 secret 정보를 deployment, service 에 적용하고 재생성 명령을 통해 Pod 를 가동해 보겠습니다.

기존 에러 발생한 deployment, service 설정 상태를 yaml 파일로 추출합니다.

# oc get deployment my-app5 -o yaml > deployment_my-app5.yaml
# oc get service my-app5 -o yaml > service_my-app5.yaml

 

파일을 열어 아래 옵션에 secret 정보를 입력합니다.

아래 위치에 옵션이 없으므로 옵션명과 secret 이름을 추가해 줍니다.

# vi deployment_my-app5.yaml

...
spec:
  template:
    spec:
      imagePullSecrets:
        - name: docker-registry-login
...

 

# vi service_my-app5.yaml

...

...

적용

# oc apply -f deployment_my-app11.yaml

 

Deployment 와 Service 를 모두 수정한 후, oc rollout 명령어를 사용하여 Pod를 재생성합니다.

# oc rollout latest deployment/my-app5

 

Openshift 에서 응용프로그램에 대한 라우트를 생성합니다.
# oc expose service my-app5 --port=8080

# oc get route
NAME          HOST/PORT                                     PATH   SERVICES      PORT       TERMINATION   WILDCARD
my-app5   my-app5-project412.apps.az1.sysdocu.kr          php-apache   8080-tcp                 None

 

이제 웹 브라우저를 열고 route 정보에 출력된 호스트네임과 포트로 접근하면 개발한 소스 코드가 출력됩니다.

# curl my-app5-project412.apps.az1.sysdocu.kr:8080

Good job

 

 

2. Python 배포

 

최신 버전의 python 이미지를 다운로드 합니다.

# docker pull docker.io/python:latest

 

빌드할때 필요한 파일을 미리 준비해 둡니다.

# mkdir ./source

# vi ./source/server.py

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)

 

모듈리스트를 작성한 파일을 생성합니다.

여러개의 필요한 모듈을 올릴 수 있지만 본 예제에서는 Flask 모듈만 올렸는데, Flask 프레임워크를 설치하여 웹서버 용도로 사용하기 위해서 입니다.

# vi source/requirements.txt

Flask

 

빌드하기 위해 Dockerfile 을 작성합니다.

# vi Dockerfile

FROM docker.io/python:latest
COPY ./source/ /app/
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 8080
CMD ["python", "server.py"]

 

* 설명

FROM python:latest : Python 의 최신 버전을 기반으로 하는 Docker 이미지를 사용합니다.
COPY ./source/ /app/ : 호스트의 ./source/ 디렉토리에 있는 파일들을 컨테이너 내부의 /app/ 디렉토리로 복사합니다.
WORKDIR /app : 이후 명령어들이 실행될 디렉토리를 /app 으로 설정합니다.

RUN pip install -r requirements.txt : 파일에 작성되어있는 모든 모듈을 설치합니다.

EXPOSE 8080 : 호스트의 8080 포트와 컨테이너 내부의 8080 포트를 연결합니다.
CMD ["python", "server.py"] : 컨테이너가 시작될 때 /app 디렉토리에서 server.py 를 찾아 python 명령으로 실행합니다.

 

빌드 실행하면 새로운 도커 이미지가 생성됩니다.

# docker build -t python-app .

# docker images |grep python-app
python-app                          latest            fc6586828737        5 seconds ago       921 MB

 

로컬의 도커 이미지를 Registry 에 올려놓고 사용하도록 합니다.

업로드 권한이 필요하므로 생성했던 secret 계정을 이용해 Registry 에 로그인을 합니다.

# docker login -u sysdocu -p 12345678 default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000
Login Succeeded

 

태그 설정을 하고 이미지를 업로드 합니다.

# docker tag python-app default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/python
# docker push default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/python

 

python 응용프로그램을 배포하기 위해 yaml 파일을 작성합니다.

# vi app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python-sample
  template:
    metadata:
      labels:
        app: python-sample
    spec:
      containers:
      - name: python-sample
        image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/python
        ports:
        - containerPort: 8080
          protocol: TCP
      imagePullSecrets:
      - name: sysdocu
---
apiVersion: v1
kind: Service
metadata:
  name: python-sample
spec:
  type: LoadBalancer
  selector:
    app: python-sample
  ports:
    - name: python-sample
      protocol: TCP
      port: 8080
      targetPort: 8080

 

위 yaml 파일을 적용면 deployment, pod, service, endpoint 가 모두 생성됩니다.

# oc apply -f app.yaml

deployment.apps/python-sample created
service/python-sample created

 

추가로 외부에서 접근이 가능하도록 route 를 생성합니다.

# oc expose service python-sample --name=python-sample --port=8080

route.route.openshift.io/python-sample exposed

 

생성된 route 정보를 확인합니다.

# oc get route
NAME            HOST/PORT                                    PATH   SERVICES        PORT   TERMINATION   WILDCARD
python-sample   python-sample-project412.apps.az1.sysdocu.kr          python-sample   8080                 None

 

외부에서 호스트명을 이용해 컨테이너 접근이 가능합니다.

# curl python-sample-project412.apps.az1.sysdocu.kr
Hello, World!

 

 

3. Go (Golang) 배포

 

최신 버전의 go 이미지를 다운로드 합니다.

# docker pull docker.io/golang:latest

 

빌드할때 필요한 파일을 미리 준비해 둡니다.

# mkdir ./source

# vi ./source/gogin.go

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.String(200, "Hello, world!")
    })
    r.Run() // default port is 8080
}

 

빌드하기 위해 Dockerfile 을 작성합니다.

# vi Dockerfile

FROM golang:latest
ENV CGO_ENABLED 0
COPY ./source/ /app/
WORKDIR /app
RUN go mod init github.com/example/example
RUN go mod tidy
RUN go build -o gogin .
EXPOSE 8080
CMD ["/app/gogin"]

 

* 설명

FROM python:latest : Golang 의 최신 버전을 기반으로 하는 Docker 이미지를 사용합니다.

ENV CGO_ENABLED 0 : 환경 변수를 설정합니다. CGO_ENABLED 를 0 으로 설정하여 C 기반 라이브러리를 사용하지 않도록 합니다.

COPY ./source/ /app/ : 호스트의 ./source/ 디렉토리에 있는 파일들을 컨테이너 내부의 /app/ 디렉토리로 복사합니다.
WORKDIR /app : 이후 명령어들이 실행될 디렉토리를 /app 으로 설정합니다.

RUN go mod init github.com/example/example : 모듈을 초기화 할때 사용하는 명령이지만 잘못된 URL 을 입력해도 넘어갑니다.

                                                                             이 행이 있어야 다음 행으로 넘어갈 수 있어서 아무렇게나 입력하였습니다.

RUN go mod tidy : Go 모듈 시스템을 사용하여 의존성을 관리하고 go.mod 및 go.sum 파일을 업데이트합니다.

RUN go build -o gogin . : /app 디렉토리에 위치한 소스코드를 컴파일하여 gogin 바이너리 파일을 생성하는 명령입니다.

EXPOSE 8080 : 컨테이너가 사용할 포트 번호를 설정합니다. 이 경우, 8080번 포트를 사용합니다.
CMD ["/app/gogin"] : 컨테이너가 시작될 때 실행할 명령을 설정합니다. 이 경우, gogin 실행 파일을 실행하여 Go 애플리케이션을 실행합니다.

 

빌드 실행하면 새로운 도커 이미지가 생성됩니다.

# docker build -t go-app .

# docker images |grep go-app
go-app                          latest            f5e7faecac07        3 minutes ago       1.05 GB

 

로컬의 도커 이미지를 Registry 에 올려놓고 사용하도록 합니다.

# docker tag go-app default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/go
# docker push default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/go

 

Go 응용프로그램을 배포하기 위해 yaml 파일을 작성합니다.

# vi app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: go-sample
  template:
    metadata:
      labels:
        app: go-sample
    spec:
      containers:
      - name: go-sample
        image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/go
        ports:
        - containerPort: 8080
          protocol: TCP
      imagePullSecrets:
      - name: sysdocu
---
apiVersion: v1
kind: Service
metadata:
  name: go-sample
spec:
  type: LoadBalancer
  selector:
    app: go-sample
  ports:
    - name: go-sample
      protocol: TCP
      port: 8080
      targetPort: 8080

 

위 yaml 파일을 적용면 deployment, pod, service, endpoint 가 모두 생성됩니다.

# oc apply -f app.yaml

deployment.apps/go-sample created
service/go-sample created

 

추가로 외부에서 접근이 가능하도록 route 를 생성합니다.

# oc expose service go-sample --name=go-sample --port=8080

route.route.openshift.io/go-sample exposed

 

생성된 route 정보를 확인합니다.

# oc get route
NAME            HOST/PORT                                    PATH   SERVICES        PORT   TERMINATION   WILDCARD
go-sample       go-sample-project412.apps.az1.sysdocu.kr              go-sample       8888                 None
python-sample   python-sample-project412.apps.az1.sysdocu.kr          python-sample   8080                 None

 

외부에서 호스트명을 이용해 컨테이너 접근이 가능합니다.

# curl go-sample-project412.apps.az1.sysdocu.kr
Hello, world!

 

 

4. NodeJS 배포

 

최신 버전의 nodejs 이미지를 다운로드 합니다.

# docker pull docker.io/node:latest

 

빌드할때 필요한 파일을 미리 준비해 둡니다.

# mkdir ./source

# vi ./source/index.js

var express = require('express')
var app = express()

app.get('/', function (req, res) {
    res.send('Hello World!')
})

app.listen(8080, function () {
    console.log('app listening on port 8080!')
})

 

# vi ./source/package.json

{
  "name": "node-sample",
  "version": "1.0.0",
  "description": "A simple Node.js application",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.17.2"
  }
}

 

빌드하기 위해 Dockerfile 을 작성합니다.

# vi Dockerfile

FROM node:latest
COPY ./source/ /app/
WORKDIR /app
RUN npm init
RUN npm install express
EXPOSE 8080
CMD ["npm", "start"]

 

* 설명

FROM python:latest : Golang 의 최신 버전을 기반으로 하는 Docker 이미지를 사용합니다.

COPY ./source/ /app/ : 호스트의 ./source/ 디렉토리에 있는 파일들을 컨테이너 내부의 /app/ 디렉토리로 복사합니다.
WORKDIR /app : 이후 명령어들이 실행될 디렉토리를 /app 으로 설정합니다.

RUN npm init -y : Node.js 프로젝트를 위한 package.json 파일을 생성합니다. 상호 작용모드로 진입하지 않도록 -y 옵션을 추가합니다.
RUN npm install express : Node.js 프로젝트에서 express 모듈을 설치합니다.

EXPOSE 8080 : 컨테이너가 사용할 포트 번호를 설정합니다.
CMD ["npm", "start"] : 컨테이너가 시작될 때 실행할 명령을 설정합니다. 여기서는 npm start를 실행합니다.

                                   이는 Node.js 프로젝트 내부의 package.json 파일에서 start 스크립트를 실행합니다.

 

빌드 실행하면 새로운 도커 이미지가 생성됩니다.

# docker build -t node-app .

# docker images |grep node-app
node-app                          latest            f5e7faecac07        3 minutes ago       1.05 GB

 

로컬의 도커 이미지를 Registry 에 올려놓고 사용하도록 합니다.

# docker tag node-app default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/node
# docker push default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/node

 

nodejs 응용프로그램을 배포하기 위해 yaml 파일을 작성합니다.

# vi app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: node-sample
  template:
    metadata:
      labels:
        app: node-sample
    spec:
      containers:
      - name: node-sample
        image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/node
        ports:
        - containerPort: 8080
          protocol: TCP
      imagePullSecrets:
      - name: sysdocu
---
apiVersion: v1
kind: Service
metadata:
  name: node-sample
spec:
  type: LoadBalancer
  selector:
    app: node-sample
  ports:
    - name: node-sample
      protocol: TCP
      port: 8080
      targetPort: 8080

 

위 yaml 파일을 적용면 deployment, pod, service, endpoint 가 모두 생성됩니다.

# oc apply -f app.yaml

deployment.apps/node-sample created
service/node-sample created

 

추가로 외부에서 접근이 가능하도록 route 를 생성합니다.

# oc expose service node-sample --name=node-sample --port=8080

route.route.openshift.io/node-sample exposed

 

생성된 route 정보를 확인합니다.

# oc get route
NAME            HOST/PORT                                    PATH   SERVICES        PORT   TERMINATION   WILDCARD
go-sample       go-sample-project412.apps.az1.sysdocu.kr              go-sample       8888                 None
node-sample     node-sample-project412.apps.az1.sysdocu.kr          node-sample   8080                 None
python-sample   python-sample-project412.apps.az1.sysdocu.kr          python-sample   8080                 None

 

외부에서 호스트명을 이용해 컨테이너 접근이 가능합니다.

# curl node-sample-project412.apps.az1.sysdocu.kr
Hello World!

 

 

5. Java 배포

 

특정 버전의 alpine (경량) java 이미지를 다운로드 합니다.

# docker pull docker.io/openjdk:17-alpine

 

빌드할때 필요한 파일을 미리 준비해 둡니다.

아래 java 소스를 보면 웹서버를 담당하는 것은 JDK 에서 제공하는 HTTP 서버 API 입니다.

이 API 를 사용하면 간단한 웹 서버를 만들 수 있지만, Spring 과 같은 프레임워크에 비해 제공하는 기능이 제한적입니다.

# mkdir ./source

# vi ./source/HelloWorld.java

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

public class HelloWorld {
    public static void main(String[] args) throws Exception {
        System.out.println("Hello. Simple Web Server.");

        HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
        server.createContext("/", indexHandler);
        server.createContext("/hello", mHelloHandler);
        server.setExecutor(null);
        server.start();
    }

    private static HttpHandler indexHandler = new HttpHandler() {

        @Override
        public void handle(HttpExchange httpExchange) throws IOException {
            byte[] response = "This is an index page.".getBytes();
            httpExchange.sendResponseHeaders(200, response.length);
            OutputStream os = httpExchange.getResponseBody();
            os.write(response);
            os.close();
        }
    };

    private static HttpHandler mHelloHandler = new HttpHandler() {

        @Override
        public void handle(HttpExchange httpExchange) throws IOException {
            byte[] response = "Hello. SnowDeer!!".getBytes();
            httpExchange.sendResponseHeaders(200, response.length);
            OutputStream os = httpExchange.getResponseBody();
            os.write(response);
            os.close();
        }
    };
}

 

* 참고

- HelloWorld.java 출처 : https://github.com/snowdeer/openshift-java-sample/blob/master/app/SimpleWebServer.java

                                      본 매뉴얼에서는 출처의 내용중 클래스 이름을 변경하여 적용하였음

 

빌드하기 위해 Dockerfile 을 작성합니다.

# vi Dockerfile

FROM openjdk:latest
COPY ./source/ /app/
WORKDIR /app
EXPOSE 8080
RUN javac HelloWorld.java
CMD ["java", "HelloWorld"]

 

* 설명

FROM python:latest : Golang 의 최신 버전을 기반으로 하는 Docker 이미지를 사용합니다.

COPY ./source/ /app/ : 호스트의 ./source/ 디렉토리에 있는 파일들을 컨테이너 내부의 /app/ 디렉토리로 복사합니다.
WORKDIR /app : 이후 명령어들이 실행될 디렉토리를 /app 으로 설정합니다.

EXPOSE 8080 : 컨테이너가 사용할 포트 번호를 설정합니다.

RUN javac HelloWorld.java : HelloWorld.java 소스 파일을 컴파일 하여 실행 가능한 파일을 생성합니다.

CMD ["java", "HelloWorld"] : 컨테이너가 시작될 때 실행할 명령을 설정합니다. 여기서는 java 명령으로 HelloWorld 파일을 실행합니다.

 

빌드 실행하면 새로운 도커 이미지가 생성됩니다.

# docker build -t java-app .

# docker images |grep java-app
node-app                          latest            928efdd8d2cb        2 minutes ago       326 MB

 

로컬의 도커 이미지를 Registry 에 올려놓고 사용하도록 합니다.

# docker tag java-app default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/java
# docker push default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/java

 

java 응용프로그램을 배포하기 위해 yaml 파일을 작성합니다.

# vi app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: java-sample
  template:
    metadata:
      labels:
        app: java-sample
    spec:
      containers:
      - name: java-sample
        image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/java
        ports:
        - containerPort: 8080
          protocol: TCP
      imagePullSecrets:
      - name: sysdocu
---
apiVersion: v1
kind: Service
metadata:
  name: java-sample
spec:
  type: LoadBalancer
  selector:
    app: java-sample
  ports:
    - name: java-sample
      protocol: TCP
      port: 8080
      targetPort: 8080

 

위 yaml 파일을 적용면 deployment, pod, service, endpoint 가 모두 생성됩니다.

# oc apply -f app.yaml
deployment.apps/java-sample created
service/java-sample created

 

추가로 외부에서 접근이 가능하도록 route 를 생성합니다.

# oc expose service java-sample --name=java-sample --port=8080

route.route.openshift.io/java-sample exposed

 

생성된 route 정보를 확인합니다.

# oc get route
NAME            HOST/PORT                                    PATH   SERVICES        PORT   TERMINATION   WILDCARD
go-sample       go-sample-project412.apps.az1.sysdocu.kr              go-sample       8888                 None
java-sample     java-sample-project412.apps.az1.sysdocu.kr            java-sample     8080                 None
nodejs-sample   nodejs-sample-project412.apps.az1.sysdocu.kr          nodejs-sample   8080                 None
python-sample   python-sample-project412.apps.az1.sysdocu.kr          python-sample   8080                 None

 

외부에서 호스트명을 이용해 컨테이너 접근이 가능합니다.

# curl java-sample-project412.apps.az1.sysdocu.kr
This is an index page.

 

 

6. Ruby 배포

 

빌드할때 필요한 Gemfile, config.ru 파일을 미리 준비해 둡니다.

# mkdir ./source

# vi ./source/Gemfile

source 'https://rubygems.org'
gem 'rack'
gem 'puma'

 

# vi ./source/config.ru

require 'rack/lobster'

map '/health' do
  health = proc do |env|
    [200, { "Content-Type" => "text/html" }, ["1"]]
  end
  run health
end

map '/lobster' do
  run Rack::Lobster.new
end

map '/headers' do
  headers = proc do |env|
    [200, { "Content-Type" => "text/plain" }, [
      env.select {|key,val| key.start_with? 'HTTP_'}
      .collect {|key, val| [key.sub(/^HTTP_/, ''), val]}
      .collect {|key, val| "#{key}: #{val}"}
      .sort
      .join("\n")
    ]]
  end
  run headers
end

map '/' do
  welcome = proc do |env|
    [200, { "Content-Type" => "text/html" }, [<<WELCOME_CONTENTS
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Welcome to OpenShift</title>


<style>

/*!
 * Bootstrap v3.0.0
 *
 * Copyright 2013 Twitter, Inc
 * Licensed under the Apache License v2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world @twitter by @mdo and @fat.
 */

  .logo {
    background-size: cover;
    height: 58px;
    width: 180px;
    margin-top: 6px;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkwAIYBQAAeQF6gEsgPwAAAABJRU5ErkJggg==);
  }
.logo a {
  display: block;
  width: 100%;
  height: 100%;
}
*, *:before, *:after {
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
aside,
footer,
header,
hgroup,
section{
  display: block;
}
body {
  color: #404040;
  font-family: "Helvetica Neue",Helvetica,"Liberation Sans",Arial,sans-serif;
  font-size: 14px;
  line-height: 1.4;
}

html {
  font-family: sans-serif;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}
ul {
    margin-top: 0;
}
.container {
  margin-right: auto;
  margin-left: auto;
  padding-left: 15px;
  padding-right: 15px;
}
.container:before,
.container:after {
  content: " ";
  /* 1 */

  display: table;
  /* 2 */

}
.container:after {
  clear: both;
}
.row {
  margin-left: -15px;
  margin-right: -15px;
}
.row:before,
.row:after {
  content: " ";
  /* 1 */

  display: table;
  /* 2 */

}
.row:after {
  clear: both;
}
.col-sm-6, .col-md-6, .col-xs-12 {
  position: relative;
  min-height: 1px;
  padding-left: 15px;
  padding-right: 15px;
}
.col-xs-12 {
  width: 100%;
}

@media (min-width: 768px) {
  .container {
    width: 750px;
  }
  .col-sm-6 {
    float: left;
  }
  .col-sm-6 {
    width: 50%;
  }
}

@media (min-width: 992px) {
  .container {
    width: 970px;
  }
  .col-md-6 {
    float: left;
  }
  .col-md-6 {
    width: 50%;
  }
}
@media (min-width: 1200px) {
  .container {
    width: 1170px;
  }
}

a {
  color: #069;
  text-decoration: none;
}
a:hover {
  color: #EA0011;
  text-decoration: underline;
}
hgroup {
  margin-top: 50px;
}
footer {
    margin: 50px 0 25px;
}
h1, h2, h3 {
  color: #000;
  line-height: 1.38em;
  margin: 1.5em 0 .3em;
}
h1 {
  font-size: 25px;
  font-weight: 300;
  border-bottom: 1px solid #fff;
  margin-bottom: .5em;
}
h1:after {
  content: "";
  display: block;
  width: 100%;
  height: 1px;
  background-color: #ddd;
}
h2 {
  font-size: 19px;
  font-weight: 400;
}
h3 {
  font-size: 15px;
  font-weight: 400;
  margin: 0 0 .3em;
}
p {
  margin: 0 0 2em;
  text-align: justify;
}
p + h2 {
  margin-top: 2em;
}
html {
  background: #f5f5f5;
  height: 100%;
}
code {
  background-color: white;
  border: 1px solid #ccc;
  padding: 1px 5px;
  color: #888;
}
pre {
  display: block;
  padding: 13.333px 20px;
  margin: 0 0 20px;
  font-size: 13px;
  line-height: 1.4;
  background-color: #fff;
  border-left: 2px solid rgba(120,120,120,0.35);
  white-space: pre;
  white-space: pre-wrap;
  word-break: normal;
  word-wrap: break-word;
  overflow: auto;
  font-family: Menlo,Monaco,"Liberation Mono",Consolas,monospace !important;
}

</style>

</head>
<body>

<section class='container'>
          <hgroup>
            <h1>Welcome to your Ruby application on OpenShift</h1>
          </hgroup>


        <div class="row">
          <section class='col-xs-12 col-sm-6 col-md-6'>
            <section>
              <h2>Deploying code changes</h2>
                <p>
                  The source code for this application is available to be forked from the <a href="https://www.github.com/sclorg/ruby-ex">OpenShift GitHub repository</a>.
                  You can configure a webhook in your repository to make OpenShift automatically start a build whenever you push your code:
                </p>

<ol>
  <li>From the Web Console homepage, navigate to your project</li>
  <li>Click on Browse &gt; Builds</li>
  <li>From the view for your Build click on the button to copy your GitHub webhook</li>
  <li>Navigate to your repository on GitHub and click on repository settings &gt; webhooks</li>
  <li>Paste your webhook URL provided by OpenShift &mdash; that's it!</li>
</ol>
<p>After you save your webhook, if you refresh your settings page you can see the status of the ping that Github sent to OpenShift to verify it can reach the server.</p>
<p>Note: adding a webhook requires your OpenShift server to be reachable from GitHub.</p>

                <h3>Working in your local Git repository</h3>
                <p>If you forked the application from the OpenShift GitHub example, you'll need to manually clone the repository to your local system. Copy the application's source code Git URL and then run:</p>

<pre>$ git clone &lt;git_url&gt; &lt;directory_to_create&gt;

# Within your project directory
# Commit your changes and push to OpenShift

$ git commit -a -m 'Some commit message'
$ git push</pre>

<p>After pushing changes, you'll need to manually trigger a build if you did not setup a webhook as described above.</p>
      </section>
          </section>
          <section class="col-xs-12 col-sm-6 col-md-6">

                <h2>Managing your application</h2>

                <p>Documentation on how to manage your application from the Web Console or Command Line is available at the <a href="http://docs.okd.io/latest/dev_guide/overview.html">Developer Guide</a>.</p>

                <h3>Web Console</h3>
                <p>You can use the Web Console to view the state of your application components and launch new builds.</p>

                <h3>Command Line</h3>
                <p>With the <a href="http://docs.okd.io/latest/cli_reference/overview.html">OpenShift command line interface</a> (CLI), you can create applications and manage projects from a terminal.</p>

                <h2>Development Resources</h2>
                  <ul>
                    <li><a href="http://docs.okd.io/latest/welcome/index.html">OpenShift Documentation</a></li>
                    <li><a href="https://github.com/openshift/origin">Openshift Origin GitHub</a></li>
                    <li><a href="https://github.com/openshift/source-to-image">Source To Image GitHub</a></li>
                    <li><a href="http://docs.okd.io/latest/using_images/s2i_images/ruby.html">Getting Started with Ruby on OpenShift</a></li>
                    <li><a href="http://stackoverflow.com/questions/tagged/openshift">Stack Overflow questions for OpenShift</a></li>
                    <li><a href="http://git-scm.com/documentation">Git documentation</a></li>
                  </ul>


          </section>
        </div>

        <footer>
          <div class="logo"><a href="https://www.openshift.com/"></a></div>
        </footer>
</section>


</body>
</html>
WELCOME_CONTENTS
    ]]
  end
  run welcome
end

 

* 참고

Ruby 의 경우 Rack 애플리케이션을 실행하는 데 사용되는 파일 이름이 config.ru 입니다.

Rack 은 Ruby 웹 프레임워크에서 사용되는 인터페이스로써 HTTP 요청을 처리하고 응답을 생성하기 위한 메소드들을 제공합니다.

따라서 Ruby 애플리케이션을 컨테이너에서 실행할 때, 컨테이너는 config.ru 파일을 찾아서 Rack 애플리케이션을 실행합니다.

- config.ru 출처 : https://github.com/sclorg/ruby-ex/blob/master/config.ru

                          본 매뉴얼에서는 출처의 내용중 background-image 부분만 짧은 (용량이 적은) 내용으로 변경하여 적용하였음

 

빌드하기 위해 Dockerfile 을 작성합니다.

Ruby 에서 사용하는 프레임워크는 sinatra 를 선택하였고 아래 예제는 sinatra 설치를 포함하고 있습니다.

# vi Dockerfile

FROM ruby:latest
COPY ./source/ /app/
WORKDIR /app
RUN bundle install
RUN gem install rack
RUN gem install sinatra -v 3.0.6
EXPOSE 8080
CMD ["rackup", "-o", "0.0.0.0", "-p", "8080"]

 

* 설명

FROM ruby:latest : Ruby의 최신 버전을 기반으로 하는 Docker 이미지를 사용합니다.
COPY ./source/ /app/ : 호스트의 ./source/ 디렉토리에 있는 파일들을 컨테이너 내부의 /app/ 디렉토리로 복사합니다.
WORKDIR /app : 이후 명령어들이 실행될 디렉토리를 /app 으로 설정합니다.
RUN bundle install : /app 디렉토리에서 Gemfile 에 명시된 Ruby 패키지를 설치합니다.
RUN gem install rack : Rack 웹 서버를 사용하기 위한 Ruby 패키지 rack 을 설치합니다.
RUN gem install sinatra -v 3.0.6 : Sinatra 웹 프레임워크의 특정 버전인 3.0.6 을 설치합니다.
                                                       Sinatra 는 간단한 Ruby 웹 애플리케이션을 빠르고 쉽게 작성할 수 있게 도와주는 경량 웹 프레임워크 입니다.

                                                       (출시 버전 정보 : https://rubygems.org/gems/sinatra/versions/)

EXPOSE 8080 : 컨테이너의 8080 포트를 오픈합니다.
CMD ["rackup", "-o", "0.0.0.0", "-p", "8080"] : 컨테이너가 시작될 때 /app 디렉토리에서 config.ru 를 찾아 Rack 애플리케이션을 실행하고,

                                                                       호스트의 8080 포트와 컨테이너 내부의 8080 포트를 연결합니다.

 

빌드 실행하면 새로운 도커 이미지가 생성됩니다.

# docker build -t ruby-app .

# docker images |grep ruby-app
ruby-app                          latest            24f660cbf71f       5 minutes ago      915 MB

 

로컬의 도커 이미지를 Registry 에 올려놓고 사용하도록 합니다.

# docker tag ruby-app default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/ruby
# docker push default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/ruby

 

ruby 응용프로그램을 배포하기 위해 yaml 파일을 작성합니다.

# vi app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ruby-sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ruby-sample
  template:
    metadata:
      labels:
        app: ruby-sample
    spec:
      containers:
      - name: ruby-sample
        image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/ruby
        ports:
        - containerPort: 8080
          protocol: TCP
      imagePullSecrets:
      - name: sysdocu

---
apiVersion: v1
kind: Service
metadata:
  name: ruby-sample
spec:
  type: LoadBalancer
  selector:
    app: ruby-sample
  ports:
    - name: ruby-sample
      protocol: TCP
      port: 8080
      targetPort: 8080

 

* 참고

imagePullSecrets 에 sysdocu 는 registry 접근 권한을 가진 사용자 입니다.

secret 생성 방법은 다른 포스트를 참고해주세요. ( https://sysdocu.tistory.com/1776 )

 

위 yaml 파일을 적용면 deployment, pod, service, endpoint 가 모두 생성됩니다.

# oc apply -f app.yaml
deployment.apps/ruby-sample created
service/ruby-sample created

 

추가로 외부에서 접근이 가능하도록 route 를 생성합니다.

# oc expose service ruby-sample --name=ruby-sample --port=8080

route.route.openshift.io/ruby-sample exposed

 

생성된 route 정보를 확인합니다.

# oc get route
NAME            HOST/PORT                                    PATH   SERVICES        PORT   TERMINATION   WILDCARD
go-sample       go-sample-project412.apps.az1.sysdocu.kr              go-sample       8888                 None
java-sample     java-sample-project412.apps.az1.sysdocu.kr            java-sample     8080                 None
nodejs-sample   nodejs-sample-project412.apps.az1.sysdocu.kr          nodejs-sample   8080                 None
python-sample   python-sample-project412.apps.az1.sysdocu.kr          python-sample   8080                 None

ruby-sample     ruby-sample-project412.apps.az1.sysdocu.kr            ruby-sample     8080                 None

 

외부에서 호스트명을 이용해 컨테이너 접근이 가능합니다.

curl 명령으로 접근하면 html 코드가 많이 출력되기 때문에 브라우저로 완성된 페이지를 보는것이 좋습니다.

- 웹브라우저 접속 URL : ruby-sample-project412.apps.az1.sysdocu.kr

 

반응형

댓글()

Openshift 4.12.0 응용프로그램 배포 - 웹서버, 데이터베이스

리눅스/OpenShift|2023. 2. 17. 10:45
반응형

여기에서는 다양한 응용프로그램을 배포해보겠습니다.

배포하면서 겪는 오류 및 해결책을 포함하였습니다.

1. 웹서버 : Nginx, Httpd

2. DB : MySQL, Redis, MongoDB, PostgreSQL

 

개발 언어를 배포하는 방법은 다음 포스팅을 확인해주세요.

( https://sysdocu.tistory.com/1778 )

개발언어 : Java, Node.js, PHP, Python, Ruby, Go

 

 

[ 사전 작업 ]

 

1) 프로젝트 생성

응용프로그램을 배포하기 전에 프로젝트를 생성해 놓아야 합니다.

사용자를 만들고 프로젝트 생성 권한을 주어도 되지만

본 매뉴얼에서는 편의를 위해 관리자 (system:admin) 로 작업을 진행하도록 하겠습니다.

# export KUBECONFIG=/root/installation_directory/auth/kubeconfig

# oc whoami

system:admin

 

project412 라는 프로젝트를 생성합니다.

# oc new-project project412 --description="This is an example project" --display-name="Hello OpenShift"

 

생성한 프로젝트를 선택합니다.

# oc project project412

 

2) 컨테이너 관리 도구 준비

응용프로그램 생성 방식에는 여러 가지가 있습니다.

- Git 저장소를 통해 생성하는 방법

- Docker 이미지를 통해 생성하는 방법

- Template 를 통해 생성하는 방법

 

여기에서는 Docker image 를 받아서 응용프로그램으로 배포하는 방식을 설명하겠습니다.

Docker 패키지를 설치합니다.

# yum -y install docker

 

Docker 데몬이 가동되어 있어야 다운로드가 됩니다.

# systemctl enable docker

# systemctl start docker

 

3) registry.redhat.io 로그인

몇가지 응용프로그램 이미지를 다운로드하고 배포하기 위해서 redhat 에 가입 합니다.

registry.redhat.io 에서는 다양한 이미지를 제공하고 있으므로 종류 및 버전을 확인하고자 할 경우

레드햇 사이트나 회원 가입 후 로그인하여 명령어로 살펴 볼 수 있습니다.

가입 하였을 경우 아래와 같이 로그인 합니다.

# docker login registry.redhat.io
Username: <redhat 계정>
Password: 
Login Succeeded

 

 

1-1. Nginx 배포

 

1) Nginx 배포

nginx 최신 버전 이미지를 다운로드 합니다.
# docker pull docker.io/nginx:latest

 

Openshift 에서 응용프로그램 생성은 oc new-app 명령을 이용합니다.

이 방식을 사용하면 어플리케이션을 생성할때 Deployment 와 Service 가 함께 생성됩니다.

# oc new-app docker.io/nginx:latest

 

응용프로그램 생성이 잘 되었는지 확인합니다.

생성은 되었으나 사용할 준비가 되지 않았고, CrashLoopBackOff 상태인 것이 확인됩니다.

# oc get pods
NAME                     READY   STATUS             RESTARTS     AGE
nginx-5fb558b844-qg99g   0/1     CrashLoopBackOff   1 (2s ago)   9s

 

로그를 확인합니다.

# oc logs nginx-5fb558b844-qg99g

...

2023/02/16 23:04:53 [warn] 1#1: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
2023/02/16 23:04:53 [emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)

 

디렉토리 생성 권한이 없어 에러가 출력되었습니다.

Pod, Deployment, Service 를 지우고, Security Context Constraints 권한을 부여한뒤 다시 설치합니다.

(팁 : deployment 를 먼저 삭제하면 pod 도 같이 삭제 됩니다)

# oc delete deployment nginx

# oc delete service nginx

oc adm policy add-scc-to-user anyuid -z default
clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid added: "default"

 

다시 설치를 합니다.

# oc new-app docker.io/nginx:latest

 

nginx 가 정상 구동 된것을 확인하였습니다.

# oc get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5fb558b844-jp4jt   1/1     Running   0          11s

 

* 참고

설치가 다 되었으면 위에서 주었던 권한을 제거 해야 하지만 아래로 계속 응용프로그램 설치를 할 예정이므로

해당 권한은 제거하지 않고 방법만 알고 넘어가도록 하겠습니다.

oc adm policy remove-scc-from-user anyuid -z default
clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid removed: "default"

 

2) 라우팅 설정

외부에서 컨테이너 접근이 가능하도록 포트를 노출시킵니다.

뒤에 --port 80 옵션을 주어 특정 포트로 허용할 수도 있습니다.

# oc expose service nginx
route.route.openshift.io/nginx exposed
# oc get route
NAME    HOST/PORT                               PATH   SERVICES   PORT   TERMINATION   WILDCARD
nginx   nginx-project412.apps.az1.sysdocu.kr           nginx      80-tcp               None

 

출력된 호스트명과 포트로 서비스 접근을 확인합니다.

# curl --head nginx-project412.apps.az1.sysdocu.kr

HTTP/1.1 200 OK
server: nginx/1.23.3
date: Thu, 16 Feb 2023 23:19:57 GMT
content-type: text/html
content-length: 615
last-modified: Tue, 13 Dec 2022 15:53:53 GMT
etag: "6398a011-267"
accept-ranges: bytes
set-cookie: 7769a7256fe4dda43770015df5735002=e53f29e3aa14fd7cc39e7efd9f5e8535; path=/; HttpOnly
cache-control: private

 

 

1-2. Httpd 배포

 

1) Httpd 배포

httpd 최신 버전 이미지를 다운로드하고 배포합니다.
# docker pull docker.io/httpd:latest

# oc new-app docker.io/httpd:latest

 

응용프로그램 생성이 잘 되었는지 확인합니다.

# oc get pods
NAME                    READY   STATUS    RESTARTS   AGE
httpd-c9ccd7f68-9h7cd   1/1     Running   0          2m19s

 

2) 라우팅 설정

외부에서 컨테이너 접근이 가능하도록 포트를 노출시킵니다.

# oc expose service httpd
route.route.openshift.io/httpd exposed
# oc get route
NAME    HOST/PORT                               PATH   SERVICES   PORT     TERMINATION   WILDCARD
httpd   httpd-project412.apps.az1.sysdocu.kr           httpd      80-tcp                 None

 

출력된 호스트명과 포트로 서비스 접근을 확인합니다.

# curl --head httpd-project412.apps.az1.sysdocu.kr
HTTP/1.1 200 OK
date: Wed, 22 Feb 2023 00:33:05 GMT
server: Apache/2.4.55 (Unix)
last-modified: Mon, 11 Jun 2007 18:53:14 GMT
etag: "2d-432a5e4a73a80"
accept-ranges: bytes
content-length: 45
content-type: text/html
set-cookie: e391fcb731862e31c8659df26b916428=7b084df01e88111b96161caf6bb84603; path=/; HttpOnly
cache-control: private

 

 

2-1. MySQL 배포

 

MySQL 최신 버전 이미지를 다운로드하고 배포합니다.
# docker pull docker.io/mysql:latest

 

어플리케이션 배포 전 필요한 환경 변수를 필수로 입력해야 합니다.

- 택일 : MYSQL_ROOT_PASSWORD
            MYSQL_ALLOW_EMPTY_PASSWORD
            MYSQL_RANDOM_ROOT_PASSWORD

# oc new-app docker.io/mysql:latest -e MYSQL_ROOT_PASSWORD=12345678

 

아래와 같이 정상으로 구동되는 것이 확인되었습니다.

# oc get pods
NAME                    READY   STATUS    RESTARTS   AGE
mysql-bd544cdb8-zt87x   1/1     Running   0          12s

 

접속 테스트를 해봅니다.

# oc rsh mysql-bd544cdb8-zt87x
sh-4.4# mysql -u root -p12345678
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.32 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

 

* 참고 : 컨테이너 환경 변수 확인

예) oc set env pod <Pod 이름> --list
# oc set env pod mysql-bd544cdb8-zt87x --list
# pods/mysql-bd544cdb8-zt87x, container mysql
MYSQL_ROOT_PASSWORD=12345678

 

 

2-2. Redis 배포

 

Redis 최신 버전 이미지를 다운로드하고 배포합니다.
# docker pull docker.io/redis:latest

# oc new-app docker.io/redis:latest

 

응용프로그램 생성이 잘 되었는지 확인합니다.

# oc get pods
NAME                    READY   STATUS    RESTARTS   AGE
redis-6b68567b5-2dgk6   1/1     Running   0          11s

 

접속 테스트를 해봅니다.

# oc rsh redis-6b68567b5-2dgk6
# redis-cli
127.0.0.1:6379> ping
PONG

 

 

2-3. MongoDB 배포

 

MongoDB 이미지를 다운로드합니다.

# docker pull registry.redhat.io/rhscl/mongodb-34-rhel7

 

어플리케이션 배포 전 필요한 환경 변수를 필수로 입력해야 합니다.

- 필수 : MONGODB_ADMIN_PASSWORD

- 선택 : MONGODB_USER
            MONGODB_PASSWORD
            MONGODB_DATABASE

# oc new-app -e MONGODB_ADMIN_PASSWORD=12345678 registry.redhat.io/rhscl/mongodb-34-rhel7

 

응용프로그램 생성이 잘 되었는지 확인합니다.

# oc get pods
NAME                                READY   STATUS    RESTARTS   AGE
mongodb-34-rhel7-7477746d74-fdsjb   1/1     Running   0          45s


접속 테스트를 해봅니다.

# oc rsh mongodb-34-rhel7-7477746d74-fdsjb
sh-4.2$ mongo
MongoDB shell version v3.4.9
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.9
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user

 

 

2-4. PostgreSQL 배포

 

PostgreSQL 이미지를 다운로드합니다.

# docker pull registry.redhat.io/rhscl/postgresql-95-rhel7

 

어플리케이션 배포 전 필요한 환경 변수를 필수로 입력해야 합니다.

- 필수 : POSTGRESQL_ADMIN_PASSWORD 

- 선택 : POSTGRESQL_USER

            POSTGRESQL_PASSWORD

            POSTGRESQL_DATABASE

# oc new-app -e POSTGRESQL_ADMIN_PASSWORD=12345678 registry.redhat.io/rhscl/postgresql-95-rhel7

 

응용프로그램 생성이 잘 되었는지 확인합니다.

# oc get pods
NAME                                   READY   STATUS    RESTARTS   AGE
postgresql-95-rhel7-8666588965-tf28s   1/1     Running   0          16s


접속 테스트를 해봅니다.

# oc rsh postgresql-95-rhel7-8666588965-tf28s
sh-4.2$ psql        
psql (9.5.14)
Type "help" for help.

postgres=# \q

sh-4.2$

 

 

 

 

반응형

댓글()

Openshift 4.12.0 내부 이미지 레지스트리 (Private Image Registry) 구성

리눅스/OpenShift|2023. 2. 16. 13:43
반응형

본 문서는 공식 Documents 를 참고하여 작성하였습니다.

https://docs.openshift.com/container-platform/4.12/registry/index.html

 

Registry 를 구축, 운영하는 이유는 OCP 서버 내부 용량이 적어서 docker 이미지를 저장할 공간이 부족할때 사용하거나

보통은 어디에서든 접근이 가능하도록 Docker hub 처럼 서비스 하려는 목적이 있습니다.

아래는 Docker 이미지를 OpenShift 내부 Docker 레지스트리에 업로드 하는 방법 입니다.

 

[요구사항]
- 클러스터 관리자 권한 필요
- 100G 이상의 용량이 필요

 

 

1. Registry 구성하기

 

1) registry Pod 확인

현재 사용자를 확인합니다.

# export KUBECONFIG=/root/installation_directory/auth/kubeconfig

# oc whoami

system:admin

 

registry Pod 가 있는지 확인합니다.

있을 경우에 구성을 할 필요가 없기 때문입니다.

# oc get pod -n openshift-image-registry -l docker-registry=default
No resources found in openshift-image-registry namespace.

 

2) 이미지 레지스트리 상태 변경

베어메탈과 같은 플랫폼에 클러스터를 구성하면 OpenShift Image Registry Operator 는 자체적으로 Removed 되어 구성됩니다.

그렇기 때문에 Image Registry 사용을 위해서는 클러스터 구성 후 managementState 를 Removed 에서 Managed 로 전환하도록 Image Registry Operator 구성을 편집해야 합니다.

 

configs.imageregistry.operator.openshift.io 구성을 바로 패치 (수정) 합니다.

# oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patch '{"spec": {"managementState":"Managed"}}'

config.imageregistry.operator.openshift.io/cluster patched

 

변경된 레지스트리 구성을 확인합니다.

# oc get configs.imageregistry.operator.openshift.io/cluster -o yaml |grep managementState

    managementState: Managed

 

3) 디렉토리 설정

원래 이미지를 안전하게 저장하기 위해서는 Persistent Volume (별도 스토리지) 을 사용해야 하지만, 여기에서는 동작 여부만 확인하는 것이 목적이므로 이미지 레지스트리 스토리지를 빈 디렉터리로 설정하겠습니다.

레지스트리를 재기동 하면 모든 이미지가 없어지기 때문에 이 방법은 반드시 테스트 환경에서만 사용하여야 합니다.

아래와 같이 config파일에 emptyDir를 추가해주면 됩니다.

# oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patch '{"spec":{"storage":{"emptyDir":{}}}}'

config.imageregistry.operator.openshift.io/cluster patched

 

* 참고

Image Registry Operator가 구성 요소를 초기화하기 전에 이 명령을 실행하면 명령이 실패하며 다음 오류가 발생합니다.
Error from server (NotFound): configs.imageregistry.operator.openshift.io "cluster" not found
몇 분 후에 명령을 다시 실행해 보세요.

 

4) 스토리지 클래스 및 PVC (PersistentVolumeClaim) 구성

사용할 스토리지 클래스 및 가용성 영역을 지정하는 yaml 파일을 생성합니다.

# vi storage_class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: custom-csi-storageclass
provisioner: cinder.csi.openstack.org
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
  availability: az1

 

metadata: name: 스토리지 클래스를 구분짓는 이름

parameters: availability: 클러스터 구성시 사용한 클러스터 이름

 

구성을 적용합니다.

# oc apply -f storage_class.yaml 
storageclass.storage.k8s.io/custom-csi-storageclass created

 

스토리지 클래스 및 openshift-image-registry 네임스페이스를 사용하는 PVC (영구 볼륨 클레임) 를 지정하는 yaml 파일을 생성합니다. 

# vi pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: csi-pvc-imageregistry
  namespace: openshift-image-registry
  annotations:
    imageregistry.openshift.io: "true"
spec:
  accessModes:
  - ReadWriteMany
  volumeMode: Filesystem
  resources:
    requests:
      storage: 100Gi
  storageClassName: custom-csi-storageclass

metadata: name: PVC 를 구분짓는 이름

metadata: namespace: PVC 를 생성할 프로젝트 위치

spec: accessModes: 영구 볼륨 클레임의 액세스 모드

* 참고 : accessMode 옵션 설명

- ReadWriteOnce : 하나의 노드에서만 읽고 쓸 수 있습니다. 즉, PVC를 마운트한 노드만 해당 볼륨에 읽고 쓸 수 있습니다.
- ReadWriteMany : 여러 노드에서 동시에 읽고 쓸 수 있습니다. 즉, 볼륨이 여러 노드에 마운트되어 있어도 모든 노드에서 동시에 읽고 쓸 수 있습니다.

두 개 이상의 노드로 고 가용성을 지원하는 이미지 레지스트리를 배포하려면 ReadWriteMany 액세스가 필요합니다.

 

spec: resources: requests: storage: 사용할 볼륨 크기

spec: resources: storageClassName: 위에서 생성한 스토리지 클래스 이름

 

구성을 적용합니다.

# oc apply -f pvc.yaml

persistentvolumeclaim/csi-pvc-imageregistry created

 

외부에서 사용이 가능하도록 route 노출 시킵니다.

# oc patch configs.imageregistry.operator.openshift.io/cluster --type=merge --patch '{"spec":{"defaultRoute":true}}' -n openshift-image-registry

config.imageregistry.operator.openshift.io/cluster patched

 

5) 상태 확인

Cluster Operator 상태를 확인합니다.

# oc get co image-registry

NAME             VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
image-registry   4.12.0    False       False         True       4h34m   Available: Error: storage backend not configured...

 

또는 이렇게 출력될 수 있습니다.

# oc get co image-registry
NAME             VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
image-registry   4.12.0    False       True          False      49s     Available: The deployment does not have available replicas...

 

하지만 시간이 지나면 정상적인 상태로 돌아옵니다.

# oc get co image-registry
NAME             VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
image-registry   4.12.0    True        False         False      4h51m   

 

레지스트리 Pod 가 확인됩니다.

# oc get pod -n openshift-image-registry -l docker-registry=default
NAME                                              READY   STATUS      RESTARTS   AGE
image-registry-7d646777fb-s6bwk                   1/1     Running     0          2d18h

 

6) Certificate 생성

Image registry 에 접근하기 위해서 연결하려는 도메인에 인증서가 설치 되어 있어야 합니다.

무료 사용을 원하시면 Let's encrypt SSL 또는 StartSSL 을 추천합니다.

https://sysdocu.tistory.com/1781

 

본 매뉴얼에서는 Let's encrypt 로 SSL 인증서를 발급받았으며, 필요한 파일 두개를 아래 디렉토리로 옮겨놓았습니다.

 

# mkdir -p /opt/registry/certs

(발급 인증서 복사 부분 생략)

# ll /opt/registry/certs
합계 12
-rw-r--r--. 1 root root 5701  2월 20 16:15 fullchain1.pem
-rw-------. 1 root root 1704  2월 20 16:15 privkey1.pem

 

참고로 위 파일에서 fullchain1.pem 은 cert1.pem 파일과 chain1.pem 파일의 내용을 모두 포함한 파일입니다.

즉, 공개 SSL 인증서와 인증서 체인이 모두 포함되었습니다.

 

용도 별 디렉토리를 추가로 생성하고 필요한 파일을 복사합니다.

# cd /opt/registry

# mkdir auth data

* 참고

/opt/registry/auth : 계정정보 파일 위치

/opt/registry/certs : 도메인 인증서 위치

/opt/registry/data : 이미지 저장 위치

 

이미지 레지스트리 사용자 계정을 생성을 위해 패키지 설치 및 명령을 수행합니다.

# cd auth

# yum -y install httpd-tools

# htpasswd -c -b -B htpasswd sysdocu 12345678

Adding password for user sysdocu

# cd

 

7) image-registry 컨테이너 생성

docker 를 이용해 image-registry 컨테이너를 가동합니다.

# docker run --name image-registry --restart=always -p 5000:5000 \
    -v /opt/registry/auth:/auth \
    -v /opt/registry/certs:/certs \
    -v /opt/registry/data:/var/lib/registry \
    -e "REGISTRY_AUTH=htpasswd" \
    -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain1.pem \
    -e REGISTRY_HTTP_TLS_KEY=/certs/privkey1.pem \
    -e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true \
    -d docker.io/library/registry:2

17e3d6b238fcebc19ffd87d39634234e4cf4708b4470f1e5c9f1e5ebaeee5264

 

route 정보에서 이미지 레지스트리 URL 을 확인 할 수 있습니다.

# oc get route -n openshift-image-registry
NAME            HOST/PORT                                                     PATH   SERVICES         PORT    TERMINATION   WILDCARD
default-route   default-route-openshift-image-registry.apps.az1.sysdocu.kr           image-registry   <all>   reencrypt     None

 

htpasswd 명령으로 생성했던 계정으로 로그인해서 아래와 같은 결과가 나오면 성공입니다.

# curl -u sysdocu:12345678 https://default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/v2/_catalog
{"repositories":[]}

 

출력이 안될경우 인증서 문제인데, -k 옵션을 사용하여 인증서를 무시하고 결과를 확인 할 수 있으나

이경우는 추천하지 않으므로 올바른 도메인으로 SSL 인증서를 다시 발급받거나

위의 컨테이너 생성 단계에서 인증서 파일에 인증서 및 체인키가 함께 들어 있는지 확인합니다.

 

* 에러 발생

여기에서 인증서 관련 에러 출력 : curl: (60) Peer's Certificate issuer is not recognized.

시스템에서 신뢰하지 않는 SSL 인증서를 사용하는 원격 서버에 접속하려고 할 때 발생합니다.

즉, 인증서 발급자가 시스템에서 인식되지 않을 때 발생하는 오류입니다.

이를 무시하는 방법은 curl -k 옵션을 추가하면 쉽게 해결이 되지만 설정한 인증서에 인증서 Chain 이 빠졌는지 확인해보면 좋습니다.

 

* 에러 발생

여기에서 인증서 관련 에러 출력 : x509: certificate signed by unknown authority

참고 (계정 정책 허용) : https://docs.openshift.com/container-platform/4.12/registry/accessing-the-registry.html

이미지에 직접 로그인 할 수도 있습니다.

# docker login -u sysdocu -p 12345678 default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000
Login Succeeded!

 

* 에러 발생

여기에서 연결 실패 에러 출력 : curl: (7) Failed connect to default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000; 연결이 거부됨

컨테이너 생성이 되지 않아 포트가 열리지 않은 경우가 가장 큰데, docker ps -a 명령으로 registry ID 값을 확인하여 logs 를 살펴보면 단서를 찾을 수 있습니다.

# docker ps -a

# docker logs <컨테이너 생성시 출력된 ID 값>

컨테이너를 삭제하고 재생성이 필요한 경우는 아래와 같이 진행합니다.

# docker stop <컨테이너 ID>

# docker rm <컨테이너 ID>

 

* 에러 발생

여기에서 연결 실패 에러 출력 : curl: (51) Unable to communicate securely with peer: requested domain name does not match the server's certificate.

이 오류는 아래와 같은 경우에 발생합니다.

- 요청한 도메인 이름과 인증서의 CN (Common Name) 이 일치하지 않는 경우 (인증서가 *.sysdocu.kr 인지, 서브도메인까지 일치하는지 확인 필요)

- 인증서의 subjectAltName 에서 요청한 도메인 이름이 발견되지 않는 경우

인증서를 재발급 받거나 인증서에 subjectAltName을 추가하여 요청한 도메인 이름이 인증서에 포함되도록 합니다.

 

 

2. 실습하기 (이미지 업로드)

 

원격으로 apache 가 포함된 php 이미지를 받아 내부 image-registry 에 올려 보도록 하겠습니다.

먼저 도커 사이트에서 이미지를 다운로드 받습니다.

# docker pull docker.io/php:7.4-apache
Trying to pull repository docker.io/library/php ... 
7.4-apache: Pulling from docker.io/library/php
a603fa5e3b41: Pull complete 
c428f1a49423: Pull complete 
156740b07ef8: Pull complete 
fb5a4c8af82f: Pull complete 
25f85b498fd5: Pull complete 
9b233e420ac7: Pull complete 
fe42347c4ecf: Pull complete 
d14eb2ed1e17: Pull complete 
66d98f73acb6: Pull complete 
d2c43c5efbc8: Pull complete 
ab590b48ea47: Pull complete 
80692ae2d067: Pull complete 
05e465aaa99a: Pull complete 
Digest: sha256:c9d7e608f73832673479770d66aacc8100011ec751d1905ff63fae3fe2e0ca6d
Status: Downloaded newer image for docker.io/php:7.4-apache

 

내부 이미지 레지스트리에 사용할 주소를 만들기위해 project 를 확인합니다.

각 사용자마다 프로젝트가 다를 수 있으므로 구분하기 위해 프로젝트명을 활용하지만 공용으로 사용하는 명칭도 괜찮습니다.

# oc project
Using project "project412" on server "https://api.az1.sysdocu.kr:6443".

 

Registry 에 로그인을 하지 않았다면 업로드 권한이 없으므로 위에서 생성했던 secret 계정을 이용해 Registry 에 로그인을 합니다.

# docker login -u sysdocu -p 12345678 default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000
Login Succeeded

 

태그 설정을 합니다.

예) docker tag <docker images 명령으로 출력된 이미지명> <내부 리포지토리 주소/프로젝트명/이미지명:버전>

# docker tag docker.io/php:7.4-apache default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/php

 

내부 이미지 레지스트리로 업로드 합니다.

예) docker push <내부 리포지토리 주소/프로젝트명/이미지명:버전>

# docker push default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/php
The push refers to a repository [default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/php]
3d33242bf117: Pushed 
529016396883: Pushed 
5464bcc3f1c2: Pushed 
28192e867e79: Pushed 
d173e78df32e: Pushed 
0be1ec4fbfdc: Pushed 
30fa0c430434: Pushed 
a538c5a6e4e0: Pushed 
e5d40f64dcb4: Pushed 
44148371c697: Pushed 
797a7c0590e0: Pushed 
f60117696410: Pushed 
ec4a38999118: Pushed 
latest: digest: sha256:18b3497ee7f2099a90b66c23a0bc3d5261b12bab367263e1b40e9b004c39e882 size: 3035

 

* 이 부분에서 업로드 되지 않는 경우 체크 사항

- 마지막 행에 'no basic auth credentials' 에러 출력시 Registry 에 로그인을 했는지 확인

- docker ps -a 명령으로 Registry 컨테이너가 정상 가동 되고 있는지 확인

 

명령이 잘 실행 되었다면 이미지 리스트를 다시 확인합니다.

# curl -u sysdocu:12345678 https://default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/v2/_catalog

{"repositories":["project412/php"]}

 

이제 다음과 같은 형태로 어느 호스트에서든 Registry 에 올려진 Docker Image 를 사용할 수 있습니다. (포트 확인)

# docker pull default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/php

 

 

3. Pod 생성하기

 

내부 레지스트리에 올려진 php 이미지로 컨테이너 생성이 가능하지만 접근권한이 없어서 다운로드 (pull) 가 되지 않을것입니다.

secret 을 생성하여 Pod 생성시 내부 레지스트리에 접근 권한을 획득하면 됩니다.

secret 은 현재 위치인 접근자 프로젝트 (예제에서는 project412) 에서 생성하면 됩니다.

# oc create secret docker-registry sysdocu \
  --docker-username=sysdocu \
  --docker-password=12345678 \
  --docker-email=admin@sysdocu.kr \
  --docker-server=default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000

 

Dockerfile 을 이용하여 php:7.4-apache 이미지에 설정을 변경하고 개발 소스를 추가하는 방법으로 진행해 보겠습니다.

테스트용으로 PHP 소스 파일을 만듭니다.

# mkdir ./source

# vi ./source/index.php

<?php
echo "Good job";
?>

 

Dockerfile 을 아래 내용으로 만듭니다.

80 포트를 이미 사용중일때는 바인딩이 되지 않습니다.

그래서 컨테이너는 8080 포트로 열고 외부접근은 80 번으로 접근하도록 합니다.

# vi Dockerfile

FROM default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/php
COPY ./source/ /var/www/html/
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
RUN sed -i 's/Listen 80/Listen 8080/' /etc/apache2/ports.conf
EXPOSE 8080
CMD ["apache2ctl", "-D", "FOREGROUND"]

 

현재 디렉토리에 있는 Dockerfile 을 사용하여 Docker 이미지를 새로 만듭니다.

형식) docker build --tag <새 이미지 이름> <Dockerfile 위치>

# docker build --tag my-app5 .

 

새로운 이미지가 확인 되었습니다.

# docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
my-app5                              latest              b0aeb2e3c8af        42 seconds ago      453 MB

docker.io/php                        7.4-apache          20a3732f422b        4 months ago        453 MB

default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/php   latest        20a3732f422b     4 months ago     453 MB

 

이번에는 로컬에 만들어져 있는 my-app5 이미지를 내부 레지스트리에 올려놓고 그것을 이용해 Pod 를 생성해보겠습니다.

업로드 권한이 필요하므로 생성했던 secret 계정을 이용해 Registry 에 로그인을 합니다.

# docker login -u sysdocu -p 12345678 default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000
Login Succeeded

 

태그 설정을 하고 업로드 합니다.

# docker tag my-app5 default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/custom-php

# docker push default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/custom-php

 

Pod 생성을 위해 deployment yaml 파일을 만듭니다.

Deployment 는 Pod 를 생성, 업데이트, 롤백 및 모니터링하는데 사용되는 추상화 계층입니다.

Deployment 는 Pod 의 명세를 정의하며, 해당 명세를 기반으로 하나 이상의 파드를 자동으로 생성합니다.

아래 deployment 생성 후 Pod 를 삭제하면 다시 생성되는 것을 볼 수 있습니다. Pod 유지 개수는 replicas 값에 따라 결정 됩니다.

내부 레지스트리에 올려진 이미지 주소와 하단부에 imagePullSecret (위에서 만든 secret 이름) 을 잘 지정하여 작성합니다.

# vi deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app5  // Deployment 이름. Pod 이름도 같은 이름으로 생성되지만 뒤에 랜덤 문자가 붙음
spec:
  replicas: 1
  selector:
    matchLabels:
      app: l-app5  // 아래랑 같아야 함
  template:
    metadata:
      labels:
        app: l-app5  // 위랑 같아야 함
    spec:
      containers:
      - name: c-app5
        image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/custom-php
        ports:
        - containerPort: 8080
      imagePullSecrets:
      - name: sysdocu

 

Deployment 를 생성합니다.

# oc apply -f deployment.yaml

 

----- Deployment 생성시 Pod 가 함께 생성되었기 때문에 이 부분은 건너 뜁니다 -----

참고로 Deployment 없이 Pod 만 생성하는 방법입니다.

# vi pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: app5
spec:
  label:
    app: l-app5
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: c-app5
    image: default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/custom-php
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: ["ALL"]
      runAsNonRoot: true
  imagePullSecrets:
  - name: sysdocu

 

Pod 를 생성합니다.

# oc apply -f pod.yaml

-----------------------------------------------------------------------------------------------------------

 

Pod 가 생성된 것이 확인되었습니다.

# oc get pod
NAME   READY   STATUS    RESTARTS   AGE
app5   1/1     Running   0          3s

 

외부에서 접근하려면 service 와 endpoint, route 까지 생성해야 합니다.

명령 한줄로 service 와 endpoint 가 같이 생성됩니다.

형식) oc expose deployment <Deployment 이름> --type=LoadBalancer --name=<생성할 Service 이름>

# oc expose deployment app5 --type=LoadBalancer --name=s-app5

 

----- Service 생성시 이 부분은 건너 뜁니다 -----

# vi service.yaml

apiVersion: v1
kind: Service
metadata:
  name: s-app5
spec:
  type: LoadBalancer
  selector:
    app: l-app5
  ports:
    - name: p-app5
      protocol: TCP
      port: 80
      targetPort: 8080

 

* 설명

- type : 옵션이 없으면 클러스터 내부에서만 접속 가능한 Cluster-IP 가 부여되는데

            외부에서 접속 가능하게 하려면 NodePort 또는 LoadBalancer 로 설정 해야 합니다.

            ㄴ NodePort : 단일 사용자 및 단일 Pod 연결의 경우 NodePort 가 적절하며 개발 및 테스트 용도로 사용합니다.

                                   노드의 IP 와 포트로 직접 접근할 수 있으므로 보안이 취약합니다.

            ㄴ LoadBalancer : 다수의 Pod 제공이 가능하며 주로 프로덕션 환경에서 사용됩니다. 또한 안전하고 성능이 우수합니다.

- selector: app : 위에 app.yaml 에서 명시한 label 이름

- port : Service 가 노출하고 있는 포트

- targetPort : Service 가 연결하려는 백엔드 Pod 의 포트

 

위 yaml 파일을 적용합니다.

# oc apply -f service.yaml

------------------------------------------------------------

 

service 생성된것이 확인되었습니다.

# oc get service
NAME     TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
s-app5   LoadBalancer   172.30.40.43   115.68.142.106   8080:30343/TCP   26s

 

route 를 생성하여 외부에서 접근 가능하도록 합니다.

형식) oc expose service <service 이름> --name=<생성할 route 이름> --port=<open 할 포트>

# oc expose service s-app5 --name=r-app5 --port=8080
route.route.openshift.io/r-app5 exposed

 

생성된 route 를 확인합니다.

# oc get route
NAME     HOST/PORT                             PATH   SERVICES   PORT   TERMINATION   WILDCARD
r-app5   r-app5-project412.apps.az1.sysdocu.kr          s-app5     8080                 None

 

외부에서 접근 테스트를 합니다.

# curl r-app5-project412.apps.az1.sysdocu.kr

Good job

 

[ oc new-app 명령어 사용하기 ]

위에 Pod, Service, Endpoint, Route 생성을 자동으로 도와주는 oc new-app 명령이 있습니다.

이 방법은 추후에 추가하도록 하겠습니다...

 

 

4. Registry 이미지 삭제하기

 

운영 서버 용량 부족이나 기타 사유로 인해 Registry 의 이미지를 지워야 할때나

같은 이름의 리포지토리가 있으면 push 를 해도 덮어씌우기가 적용되지 않고 그냥 넘어가므로 (pass) 기존 이미지를 지워야 할때가 있습니다.

그럴때 사용하는 명령인데, 올바른지 모르겠지만 아래와 같은 형식으로 명령을 실행했더니 에러가 출력되었습니다.

 

1) Registry 에서 삭제

예시) project412 에 올려놓은 ruby3 이미지 삭제

# oc adm prune images --registry-url=default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/ruby3 --confirm

error: you must use a client config with a token

 

하지만 더 간단한 방법이 있습니다.

위 예제를 따라서 구성하였다면 registry 에 올려진 이미지의 경로는 아래와 같습니다.

/opt/registry/data/docker/registry/v2/repositories/<프로젝트명>

 

registry 에 업로드 된 이미지를 확인해 봅니다.

# curl -u sysdocu:12345678 https://default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/v2/_catalog
{"repositories":["project412/custom-php","project412/custom-php2","project412/ruby","project412/ruby2","project412/ruby3"]}

 

로컬 디스크에 저장된 이미지를 확인합니다.

# ll /opt/registry/data/docker/registry/v2/repositories/project412
합계 0
drwxr-xr-x. 5 root root 55  4월  5 14:28 custom-php
drwxr-xr-x. 5 root root 55  4월 11 10:30 custom-php2
drwxr-xr-x. 5 root root 55  4월 18 09:12 ruby
drwxr-xr-x. 5 root root 55  4월 18 14:33 ruby2
drwxr-xr-x. 5 root root 55  4월 18 15:01 ruby3

 

시스템의 rm 명령을 이용하여 원하는 이미지 디렉토리를 삭제합니다.

# rm -rf /opt/registry/data/docker/registry/v2/repositories/project412/ruby3

 

지워진것이 확인되었습니다.

# curl -u sysdocu:12345678 https://default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/v2/_catalog
{"repositories":["project412/custom-php","project412/custom-php2","project412/ruby","project412/ruby2"]}

 

2) ImageStream 목록에서 삭제

이미지 Registry 를 재설치하거나 Repository 를 한개 삭제 했다 하더라도 이미지 스트림 목록에는 여전히 보입니다.

이미지 스트림은 Openshift 내부에서 관리되며, 클러스터 노드에서 호스팅되는 Docker 레지스트리와는 별개이기 때문입니다.

Openshift 의 Docker 이미지 레지스트리는 기본적으로 Docker V2 이미지 프로토콜을 지원하며, 이 레지스트리에는 이미지 스트림에서 참조하는 Docker 이미지가 저장됩니다.
정리하면, 이미지 스트림은 Openshift 서버 내에서 관리되며, 이미지는 Openshift의 Docker 이미지 레지스트리에 저장됩니다.

그렇기 때문에 Registry 에서도 삭제한 아이템을 ImageStream 에서도 따로 지워줘야 합니다.

 

# oc get is
NAME            IMAGE REPOSITORY                                                                    TAGS                UPDATED
custom-php      default-route-openshift-image-registry.apps.az1.sysdocu.kr/project412/custom-php      latest              8 days ago

custom-php2     default-route-openshift-image-registry.apps.az1.sysdocu.kr/project412/custom-php2     latest              8 days ago
ruby             default-route-openshift-image-registry.apps.az1.sysdocu.kr/project412/ruby            latest              7 days ago
ruby2            default-route-openshift-image-registry.apps.az1.sysdocu.kr/project412/ruby2           latest              8 days ago

ruby3            default-route-openshift-image-registry.apps.az1.sysdocu.kr/project412/ruby3           latest              8 days ago

 

# oc delete is ruby3

imagestream.image.openshift.io "ruby3" deleted

 

 

* 참고 : 외부 이미지를 Registry 로 바로 가져오기

 

외부 Registry 의 이미지를 내부 Registry 로 가져오는 방법 (import-image) 입니다.

import-image 를 이용하여 가져온 이미지는 docker images 로는 이미지가 보이지 않으며 oc get is 명령으로 이미지 확인이 가능합니다.

형식) oc import-image <이미지 스트림 이름> --from=<원본 이미지 경로> --confirm

# oc import-image my-image --from=default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/library/my-app5 --confirm

 

이번엔 Docker Hub 에서 한 가지 더 받아보겠습니다.

# oc import-image test --from=docker.io/nginx --confirm

 

특이사항은 등록 상태를 확인해보면 현재의 project 명 (project412) 과 이미지 스트림 이름으로 서비스 주소가 완성 되어진 것이 보입니다.

그렇기 때문에 이미지 스트림 이름을 명확히 해야 추후 이미지를 이용할때 혼동되지 않습니다.

# oc get is

NAME       IMAGE REPOSITORY                                                                 TAGS     UPDATED
my-image   default-route-openshift-image-registry.apps.az1.sysdocu.kr/project412/my-image   latest   

test             default-route-openshift-image-registry.apps.az1.sysdocu.kr/project412/test             latest

 

 

* 참고 : 내부 이미지 레지스트리 삭제

 

1) PVC 삭제

서비스 중지 또는 재설치 등의 이유로 Registry 를 재설치할 경우 아래와 같은 절차를 따릅니다.

모든 프로젝트에서 PVC 를 확인하면 image registry pvc 가 어느 네임스페이스에 있는지 확인이 됩니다.

# oc get pvc -A
NAMESPACE                  NAME                    STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS              AGE
openshift-image-registry   csi-pvc-imageregistry   Pending                                      custom-csi-storageclass   4d21h

 

이름과 네임스페이스를 이용하여 pvc 정보를 삭제합니다.

# oc delete pvc csi-pvc-imageregistry -n openshift-image-registry
persistentvolumeclaim "csi-pvc-imageregistry" deleted

 

2) Pod 삭제

openshift-image-registry 프로젝트 (네임스페이스) 에서 이미지 레지스트리 Pod 이름을 확인합니다.

# oc get pod -n openshift-image-registry -l docker-registry=default
NAME                              READY   STATUS    RESTARTS   AGE
image-registry-6dfb9c8f99-xbzbd   1/1     Running   0          4d21h

 

프로젝트명을 명시하여 해당 이미지 레지스트리 Pod 를 삭제하면 곧바로 다른 이름으로 되살아납니다.
# oc delete pod image-registry-6dfb9c8f99-xbzbd -n openshift-image-registry
pod "image-registry-6dfb9c8f99-xbzbd" deleted

 

그렇기에 완전히 삭제를 원할 경우 이미지 레지스트리 구성의 상태값에 Removed 로 표기를 해야 합니다.

# oc patch configs.imageregistry.operator.openshift.io cluster -p '{"spec":{"managementState":"Removed"}}' --type='merge'
config.imageregistry.operator.openshift.io/cluster patched

 

Terminating 상태이므로 시간이 지나 삭제 됩니다.

# oc get pod -n openshift-image-registry -l docker-registry=default
NAME                                              READY   STATUS        RESTARTS        AGE
image-registry-6dfb9c8f99-r89vg                   1/1     Terminating   0               10m

 

삭제 되었습니다.

# oc get pod -n openshift-image-registry -l docker-registry=default
No resources found in openshift-image-registry namespace.

 

3) Docker 컨테이너 및 이미지 삭제

컨테이너 ID 를 확인하고 중지, 삭제합니다.

# docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
46d0300f61f6        docker.io/library/registry:2   "/entrypoint.sh /e..."   37 minutes ago      Up 37 minutes       0.0.0.0:5000->5000/tcp   image-registry

 

# docker stop 46d0300f61f6
46d0300f61f6

 

# docker rm 46d0300f61f6
46d0300f61f6

 

끝으로 Docker 이미지를 저장하였던 폴더를 비워줍니다.

# rm -rf /opt/registry/data/*

 

 

* 참고 : SSL 인증서 업데이트

 

SSL 인증서 사용기간이 정해져있어 만료일이 도래하기 전에 인증서 업데이트를 해주어야 정상적인 서비스가 가능하며, 인증서를 교체하지 않고 기간이 만료된 경우 Pod 생성 에러 'Failed to pull image' 가 발생됩니다.

 

Registry 인증서가 있는 디렉토리로 이동합니다.

# cd /opt/registry/certs
# ll
합계 20
-rw-r--r-- 1 root root 1960  3월 20 10:55 cert1.pem
-rw-r--r-- 1 root root 3749  3월 20 10:55 chain1.pem
-rw-r--r-- 1 root root 5709  3월 20 10:55 fullchain1.pem
-rw------- 1 root root 1704  3월 20 10:55 privkey1.pem

 

갱신한 SSL 인증서를 아래와 같이 덮어씌워 교체 하였습니다. (교체 방법 생략)

참조 : https://sysdocu.tistory.com/1546

# ll
합계 40
-rw-r--r-- 1 root root 2232  6월 23 08:48 cert1.pem
-rw-r--r-- 1 root root 3749  6월 23 08:48 chain1.pem
-rw-r--r-- 1 root root 5981  6월 23 08:48 fullchain1.pem
-rw------- 1 root root 3272  6월 23 08:48 privkey1.pem

 

Let's encrypt 로 생성했다면 필요한 파일은 fullchain1.pem 과 privkey1.pem 두개 입니다.

docker 를 이용해 image-registry 컨테이너를 재가동합니다. 재가동 방식은 기존 image-registry 컨테이너를 삭제하고 재생성 하는 방법입니다.

# docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
d1fba07b40ef        docker.io/library/registry:2   "/entrypoint.sh /e..."   6 weeks ago         Up 6 weeks          0.0.0.0:5000->5000/tcp   image-registry

 

출력된 CONTAINER ID 를 이용하여 image-registry 컨테이너를 중지하고 삭제합니다.

# docker stop d1fba07b40ef
d1fba07b40ef

# docker rm d1fba07b40ef
d1fba07b40ef

 

다시 생성합니다.

# docker run --name image-registry --restart=always -p 5000:5000 \
    -v /opt/registry/auth:/auth \
    -v /opt/registry/certs:/certs \
    -v /opt/registry/data:/var/lib/registry \
    -e "REGISTRY_AUTH=htpasswd" \
    -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain1.pem \
    -e REGISTRY_HTTP_TLS_KEY=/certs/privkey1.pem \
    -e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true \
    -d docker.io/library/registry:2

1c3e5d916cf9665658e9828db7ca973062dc4fa4bdc8fb2a0d5b9fe110883045

 

이제 Registry 이미지가 잘 다운로드 되는지 테스트 하는 방법은 Pod 를 직접 생성해본다거나, 다음과 같이 docker images 로 출력되는 REPOSITORY 중에 하나를 받아보는 것입니다.

# docker pull default-route-openshift-image-registry.apps.az1.sysdocu.kr:5000/project412/python

 

반응형

댓글()

Openshift 4.12.0 응용프로그램 관리 (Pod, Deployment, Service), 스케일아웃 (Replica), 로드발란서 (LoadBalancer) 설정

리눅스/OpenShift|2023. 2. 15. 13:35
반응형

본 문서는 공식 Documents 를 참고하여 작성하였습니다.

https://docs.openshift.com/container-platform/4.12/applications/index.html

https://docs.openshift.com/container-platform/4.12/networking/configuring_ingress_cluster_traffic/configuring-ingress-cluster-traffic-load-balancer.html

 

응용프로그램을 생성하고 관리하는 방법에 대해 기술합니다.

응용프로그램은 프로젝트 내에서 생성되고 가동 되므로 프로젝트 관리부터 시작합니다.

 

 

1. 프로젝트 관리

 

1) 프로젝트 생성

관리자 권한으로 변경합니다.

# export KUBECONFIG=/root/installation_directory/auth/kubeconfig

# oc whoami

system:admin

 

project412 라는 프로젝트를 생성합니다.

# oc new-project project412 --description="This is an example project" --display-name="Hello OpenShift"

 

프로젝트 리스트를 확인합니다.

# oc get projects

 

생성한 프로젝트를 선택합니다.

# oc project project412

 

현재 프로젝트의 상태를 출력합니다.

# oc status

 

* 참고 : 현재 프로젝트에서 다른 프로젝트로 변경

# oc project <프로젝트명>

 

* 참고 : 다른 사용자로 프로젝트 생성

# oc new-project <프로젝트명> --as=<사용자명> --as-group=system:authenticated --as-group=system:authenticated:oauth

 

다음은 project412 프로젝트를 수정하고 삭제하는 방법이지만,

예제를 계속 이어나가기 위해 참고로만 알아두고 건너뜁니다.

 

2) 프로젝트 수정

기본 프로젝트 템플릿을 생성합니다.

# oc adm create-bootstrap-project-template -o yaml > template.yaml

 

수정 후 적용 (예 : openshift-config 프로젝트)

# oc create -f template.yaml -n openshift-config

 

3) 프로젝트 삭제

# oc delete project project412

 

 

2. 응용프로그램 생성

 

응용프로그램 생성 방식에는 여러 가지가 있습니다.

- Git 저장소를 통해 생성하는 방법

- Docker 이미지를 통해 생성하는 방법

- Template 를 통해 생성하는 방법

 

여기에서는 Docker image 를 받아서 응용프로그램으로 배포하는 방식을 설명하겠습니다.

 

1) 응용프로그램 생성 (배포)

도커 이미지를 다운로드 하기 위해 docker 패키지를 설치합니다.

# yum -y install docker

 

docker 데몬이 가동되어 있어야 다운로드가 됩니다.

# systemctl enable docker

# systemctl start docker

 

nginx 응용프로그램을 배포해보겠습니다.

nginx 최신 버전을 다운로드 합니다.
# docker pull nginx:latest

 

Openshift 에서 응용프로그램 생성은 oc new-app 명령을 이용합니다.

이 방식을 사용하면 어플리케이션을 생성할때 Deployment 와 Service 가 함께 생성됩니다.

# oc new-app docker.io/nginx:latest

 

응용프로그램 생성이 잘 되었는지 확인합니다.

생성은 되었으나 사용할 준비가 되지 않았고, CrashLoopBackOff 상태인 것이 확인됩니다.

# oc get pods
NAME                     READY   STATUS             RESTARTS     AGE
nginx-5fb558b844-qg99g   0/1     CrashLoopBackOff   1 (2s ago)   9s

 

로그를 확인합니다.

# oc logs nginx-5fb558b844-qg99g

...

2023/02/16 23:04:53 [warn] 1#1: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
2023/02/16 23:04:53 [emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (13: Permission denied)

 

에러가 출력되면 Pod, Deployment, Service 를 지우고, Security Context Constraints 권한을 부여한뒤 다시 설치하면 됩니다.

# oc delete pod nginx-5fb558b844-qg99g

# oc delete deployment nginx

# oc delete service nginx

oc adm policy add-scc-to-user anyuid -z default
clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid added: "default"

 

다시 설치를 해봅니다.

# oc new-app docker.io/nginx:latest

 

nginx 가 정상 구동 된것을 확인하였습니다.

# oc get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5fb558b844-jp4jt   1/1     Running   0          11s

 

설치가 다 되었으므로 위에서 주었던 권한을 제거 합니다.

oc adm policy remove-scc-from-user anyuid -z default
clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid removed: "default"

 

--------------------------------------------------

* 참고 : MySQL 설치시 에러가 발생할때

MySQL 설치시 에러가 출력되는데 이는 다음과 같이 해결이 가능합니다.

# oc new-app docker.io/mysql:latest

# oc get pods
NAME                     READY   STATUS             RESTARTS      AGE
mysql-cb5c58bfc-n2zmq   0/1     CrashLoopBackOff   4 (28s ago)   2m5s

# oc logs mysql-cb5c58bfc-n2zmq
2023-02-16 00:19:35+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.32-1.el8 started.
2023-02-16 00:19:35+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
    You need to specify one of the following as an environment variable:
    - MYSQL_ROOT_PASSWORD
    - MYSQL_ALLOW_EMPTY_PASSWORD
    - MYSQL_RANDOM_ROOT_PASSWORD

 

데이터베이스가 초기화되지 않았으며 암호 옵션이 지정되지 않았다고 합니다.

Pod, Deployment, Service 를 지우고, 아래와 같이 환경 변수를 포함하여 MySQL 응용프로그램을 다시 배포 합니다.

# oc delete pod mysql-cb5c58bfc-n2zmq

# oc delete deployment mysql

# oc delete service mysql

# oc new-app docker.io/mysql:latest -e MYSQL_ROOT_PASSWORD=<mysql root 패스워드>

 

* 참고 : 컨테이너 환경 변수 확인

# oc set env pod <Pod 이름> --list
# pods/mysql-bd544cdb8-2w8dz, container mysql
MYSQL_ROOT_PASSWORD=12345678

--------------------------------------------------

 

2) 응용프로그램 삭제 

응용프로그램을 삭제할때는 Pod 와 Deployment, Service 까지 지워줍니다.

 

(1) Pod 확인 후 삭제

# oc get pods
NAME                    READY   STATUS             RESTARTS      AGE
mysql-cb5c58bfc-n2zmq   0/1     CrashLoopBackOff   3 (34s ago)   90s

# oc delete pod mysql-cb5c58bfc-n2zmq
pod "mysql-cb5c58bfc-n2zmq" deleted

 

(2) Deployments 확인 후 삭제

# oc get deployments
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
mysql   0/1     1            0           30m
# oc delete deployments mysql
deployment.apps "mysql" deleted

 

(3) Service 확인 후 삭제

# oc get services
NAME    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)              AGE
mysql   ClusterIP  172.30.186.165   <none>        3306/TCP,33060/TCP   26m
# oc delete service mysql
service "mysql" deleted

 

3) 응용프로그램 컨테이너 접근

컨테이너 쉘을 통하여 nginx 서비스에 접근하는 방법입니다. (rsh : remote shell)

# oc rsh nginx-5fb558b844-jp4jt

# hostname
nginx-5fb558b844-jp4jt

# pwd
/
# whoami
root

 

4) 라우팅 설정

외부에서 컨테이너 접근이 가능하도록 포트를 노출시킵니다.

뒤에 --port 80 옵션은 추가하지 않아도 컨테이너의 열려진 포트로 자동 설정됩니다.

# oc expose service nginx --port 80
route.route.openshift.io/nginx exposed
# oc get route
NAME    HOST/PORT                               PATH   SERVICES   PORT   TERMINATION   WILDCARD
nginx   nginx-project412.apps.az1.sysdocu.kr           nginx      80                   None

 

출력된 호스트명과 포트로 서비스 접근을 확인합니다.

# curl --head nginx-project412.apps.az1.sysdocu.kr

HTTP/1.1 200 OK
server: nginx/1.23.3
date: Thu, 16 Feb 2023 23:19:57 GMT
content-type: text/html
content-length: 615
last-modified: Tue, 13 Dec 2022 15:53:53 GMT
etag: "6398a011-267"
accept-ranges: bytes
set-cookie: 7769a7256fe4dda43770015df5735002=e53f29e3aa14fd7cc39e7efd9f5e8535; path=/; HttpOnly
cache-control: private

 

 

3. 스케일 아웃 (Replica)

 

1) Pod 복제

스케일 아웃은 성능 향상 및 부하 분산을 위해 사용하며, 동일한 Pod 가 복제 구성 되어집니다.

위에서 경험했듯 nginx 는 Pod 생성 전에 SCC 권한을 부여해야 합니다.

그리고 replica 를 2 로 조정하면 2개의 Pod 가 자동 생성되어집니다.

# oc adm policy add-scc-to-user anyuid -z default

# oc scale deployment nginx --replicas=2
deployment.apps/nginx scaled

 

복제되는 과정에서 컨테이너 양만큼 시간이 소요되며 모니터링을 해보면 아래와 같이 Ready 와 AVAILABLE 값이 2까지 늘어나는 것이 보입니다.

# oc get deployment nginx

NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   2/2     2            2           17m

 

Pod 와 엔드포인트도 replica 개수대로 늘어난 것을 확인할 수 있습니다.

# oc get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5fb558b844-8nz5f   1/1     Running   0          2m7s
nginx-5fb558b844-jp4jt   1/1     Running   0          19m

 

# oc get ep nginx
NAME    ENDPOINTS                       AGE
nginx   10.128.2.56:80,10.131.1.42:80   19m

 

Pod 가 추가 생성이 확인 되었으므로 SCC 권한을 제거 합니다.

oc adm policy remove-scc-from-user anyuid -z default

 

Pod 하나를 삭제 해보세요. 또다른 이름의 Pod 가 자동 생성되어 replica 개수 2 로 유지하는 것을 볼 수 있습니다.

 

2) 클러스터 접근 허용 설정

현재의 서비스 정보에서 nginx type 이 ClusterIP 로 되어있습니다.

# oc get service
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   172.30.252.2   <none>        80/TCP    20m

 

기존 서비스를 삭제하고 LoadBalancer 형태로 다시 생성해 줍니다.

# oc delete service nginx
service "nginx" deleted

 

# oc expose deployment nginx --type=LoadBalancer --port 80
service/nginx exposed

 

다시 서비스 정보를 출력해보면 nginx 가 LoadBalancer 형태로 바뀌었습니다.

# oc get service
NAME    TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx   LoadBalancer   172.30.167.95   <pending>     80:31574/TCP   31s

 

(이부분 생략, 위에서 했었음)

외부에서 컨테이너 접근이 가능하도록 포트를 노출시킵니다.

# oc expose service nginx --port 80
route.route.openshift.io/nginx exposed
# oc get route
NAME    HOST/PORT                               PATH   SERVICES   PORT   TERMINATION   WILDCARD
nginx   nginx-project412.apps.az1.sysdocu.kr           nginx      80                   None

route 정보에 출력된 호스트명과 포트로 서비스에 접근할 수 있는데,

두개의 컨테이너에 번갈아 가며 접근하는 것이 확인됩니다.

 

확인을 위해 각각의 컨테이너 쉘로 로그인하여 index.html 파일 내용을 변경합니다.

# oc rsh nginx-5fb558b844-8nz5f
# echo "one" > /usr/share/nginx/html/index.html
# exit

# oc rsh nginx-5fb558b844-jp4jt
# echo "two" > /usr/share/nginx/html/index.html
# exit

 

curl 명령을 반복하여 호출하는 페이지 내용을 확인합니다.

# curl nginx-project412.apps.az1.sysdocu.kr
one
# curl nginx-project412.apps.az1.sysdocu.kr
one
# curl nginx-project412.apps.az1.sysdocu.kr
two
# curl nginx-project412.apps.az1.sysdocu.kr
one

 

반응형

댓글()

Openshift 4.12.0 사용자 생성 및 권한 설정

리눅스/OpenShift|2023. 2. 14. 14:02
반응형

본 문서는 공식 Documents 를 참고하여 작성하였습니다.

https://docs.openshift.com/container-platform/4.12/authentication/understanding-identity-provider.html

 

OpenShift 컨테이너 플랫폼 마스터에는 OAuth 서버가 내장되어 있습니다.

개발자 및 관리자는 OAuth 액세스 토큰을 취득하여 API 에 대해 자신을 인증할 수 있습니다.

처음 클러스터를 구성하면 모든 Openshift 관리 권한을 가진 kubeadmin 이라는 계정만 존재하게 됩니다.

여기에 동일한 권한의 관리자 계정이나 프로젝트 단위의 권한이 작은 사용자 계정을 추가할 수 있습니다.

 

ID 생성을 위해 ID 제공자를 선택해야 하는데, ID 제공자는 htpasswd, Keystone, LDAP, Basic authentication, Request header, GitHub or GitHub Enterprise, GitLab, Google, OpenID Connect 가 있습니다.

여기에서는 우리에게 친숙한 htpasswd 를 통하여 계정 생성하는 방법과

웹콘솔에 접근하기 위해 사용되는 기본계정 kubeadmin 을 대체하는 방법을 알아봅니다.

 

 

1. 프로젝트 (Namespace) 생성

 

현재 사용자를 확인합니다.

# export KUBECONFIG=/root/installation_directory/auth/kubeconfig

# oc whoami

system:admin

 

testwork 라는 프로젝트 (Namespace) 를 생성합니다.

# oc create ns testwork
namespace/testwork created

 

생성한 프로젝트를 확인합니다.

testwork 프로젝트는 물론이고 Openshift 를 구성하는 모든 프로젝트가 출력됩니다.

# oc get ns

또는

# oc get projects

 

 

2. 계정 관리

 

1) 계정 추가

우선 htpasswd 명령어를 사용하기 위해 패키지를 하나 설치 합니다.

# yum -y install httpd-tools

 

옵션 뒤에 파일명, ID, PW 순서로 생성을 원하는 계정정보 입력 후 실행합니다.

# htpasswd -c -B -b list.txt sysdocu 12345678
Adding password for user sysdocu

 

한개의 계정을 추가로 입력합니다.

# htpasswd -B -b list.txt fntop abcdABCD

Adding password for user fntop

 

계정 정보가 파일에 잘 입력되었는지 확인합니다.

# cat list.txt

sysdocu:$2y$05$0SIDRCNuYNZIQngZBdWzN.UlaA5CY6XM6wPQLMuAy908B7v.Y62mW

fntop:$2y$05$YW1tslShApDQEMxDfsfJUuck0adzlArLWiznqzTtDZVNTcDfvTgYq

 

계정정보가 들어있는 파일을 이용하여 위에서 생성한 testwork 프로젝트에 생성합니다.

myusers 라는 계정들의 별칭을 짓고 list.txt 파일 내용 (sysdocu, fntop 계정 정보) 를 입력합니다.

# oc create secret generic myusers --from-file=htpasswd=list.txt -n testwork

secret/myusers created

 

2) 계정 업데이트

계정을 생성하는 또 다른 방법과 기존 계정을 삭제하는 방법 입니다.

'계정 업데이트' 내용이 필요하지 않을 경우 건너뛰어도 됩니다.

 

(1) 현재 정보 저장

현재 HTPasswd secret 정보를 파일로 추출 (아래 {.data.htpasswd} 문자 그대로 입력)
$ oc get secret myusers -ojsonpath={.data.htpasswd} -n testwork | base64 --decode > current_list.txt

 

(2-1) 새 사용자 추가
$ htpasswd -bB current_list.txt <username> <password>

 

(2-2) 기존 사용자 삭제
$ htpasswd -D current_list.txt <username>

 

(3) 변경 정보 갱신

생성한 시크릿을 testwork 프로젝트 (Namespace) 에 갱신
$ oc create secret generic myusers --from-file=htpasswd=current_list.txt --dry-run=client -o yaml -n testwork | oc replace -f -

 

(4) 사용자 및 리소스 삭제

하나 이상의 사용자를 삭제한 경우 각 사용자의 기존 리소스를 추가로 제거해야 합니다.

삭제하지 않으면 토큰이 만료되지 않은 한 계속 사용할 수 있습니다.

# oc delete user <username>

# oc delete identity my_htpasswd_provider:<username>

// my_htpasswd_provider 는 identityProviders 이름 입니다.

 

 

3. web-console 계정 교체

 

새 클러스터 관리자를 생성한 후 kubeadmin 을 제거하여 클러스터 보안을 개선할 수 있습니다.
다른 사용자가 cluster-admin 이 되기 전에 kubeadmin 계정을 삭제 할 경우 OpenShift Container Platform 을 다시 설치해야 합니다.

이 명령은 취소가 안되므로 반드시 하나 이상의 계정에 cluster-admin 역할을 추가하고 로그인이 되는것을 확인합니다.

그리고 kubeadmin 계정을 삭제 해야 합니다.

 

1) 계정 추가

계정은 위에서 생성한 sysdocu 계정을 사용하도록 하겠습니다.

openshift-config 프로젝트에 계정을 생성합니다.

# oc create secret generic myusers --from-file=htpasswd=list.txt -n openshift-config

 

커스텀 리소스를 yaml 파일로 생성합니다.

# vi htpasswd.yaml

apiVersion: config.openshift.io/v1
kind: OAuth
metadata:
  name: cluster
spec:
  identityProviders:
  - name: my_htpasswd_provider
    challenge: true
    login: true
    mappingMethod: claim
    type: HTPasswd
    htpasswd:
      fileData:
        name: myusers

identityProviders: name: 사용자를 구분짓는 별칭

identityProviders: type: 생성했던 계정의 ID 제공자

htpasswd: fileData: name: openshift-config 프로젝트에 생성했던 계정들 별칭으로 위 예제에서는 sysdocu, fntop 두 개의 계정입니다.

 

정의된 커스텀 리소스를 적용하여 웹 콘솔에서 로그인이 가능하도록 합니다.

# oc apply -f htpasswd.yaml
oauth.config.openshift.io/cluster configured

 

브라우저로 웹 콘솔 페이지에 접속하면 기존과 다르게, 먼저 아래 두가지 사용자에 대해 선택하도록 되어 있습니다.

- kube:admin

- my_htpasswd_provider

 

아래 my_htpasswd_provider 를 선택하고 위에서 생성한 계정 sysdocu 로 로그인합니다.

로그인이 확인되면 kubeadmin 계정을 지우도록 합니다.

 

2) kubeadmin 계정 삭제
삭제 명령은 다음과 같습니다.
# oc delete secrets kubeadmin -n kube-system

 

 

4. 권한 관리

 

RBAC (Role-Based Access Control) 를 사용한 권한 정의 및 적용 방법 입니다.

RBAC 는 오브젝트에 따라 사용자의 권한이 결정되고 프로젝트 내에서 지정된 작업을 수행합니다.

 

[ RBAC 의 두가지 레벨 ]

- Cluster RBAC : cluster-admin 에 해당되는 권한으로 클러스터 내 모든 프로젝트에 접근하거나 관리가 가능합니다.

- Local RBAC : 지정된 프로젝트에만 접근하거나 관리가 가능합니다.

 

[ Openshift 구축시 제공되는 기본 클러스터 역할 (role) ]

- admin : 프로젝트 매니저로서 프로젝트의 리소스를 보고 수정하는 권한을 가지고 있습니다.
- basic-user : 프로젝트 및 사용자에 대한 기본 정보를 얻을 수 있는 사용자입니다.
- cluster-admin : 모든 프로젝트에서 모든 작업을 수행할 수 있는 슈퍼 사용자 (최상위 관리자) 입니다.

                           로컬 바인딩을 가진 사용자에게 바인드되어 할당량을 완전히 제어할 수 있습니다.

                           프로젝트의 모든 리소스에 대한 모든 작업을 수행할 수 있습니다.
- cluster-status : 기본 클러스터 상태 정보를 가져올 수 있는 사용자입니다.
- cluster-reader : 대부분의 개체를 가져오거나 볼 수 있지만 수정할 수 없습니다.
- edit : 프로젝트의 대부분의 개체를 수정할 수 있지만 역할 또는 바인딩을 보거나 수정 권한이 없는 사용자입니다.
- self-provisioner : 자신의 프로젝트를 생성할 수 있는 사용자입니다.
- view : 변경할 수 없지만 대부분의 개체를 볼 수 있는 사용자입니다.

            프로젝트, 역할 또는 바인딩을 보거나 수정할 수 없습니다.

 

1) 계정과 역할 연결 (Binding)

생성된 계정과 Role 을 연결하여, 계정에 역할을 부여하는 작업을 바인딩 이라고 합니다.

현재 생성되어진 sysdocu 계정에는 admin 권한을 바인딩하고, fntop 계정은 그대로 두어 프로젝트 접근 여부를 비교해 보도록 합니다.

 

testwork 프로젝트의 sysdocu 계정에 admin 역할을 연결 (binding) 합니다.

# oc adm policy add-role-to-user admin sysdocu -n testwork

clusterrole.rbac.authorization.k8s.io/admin added: "sysdocu"

 

testwork 프로젝트의 로컬 역할 바인딩을 보려면 아래와 같이 실행합니다.

# oc describe rolebinding.rbac -n testwork

 

2) 권한 비교

sysdocu 계정으로 전환하고 프로젝트 리스트를 확인합니다.

# oc login -u sysdocu

Password: (패스워드 입력)

You have access to 68 projects, the list has been suppressed. You can list all projects with 'oc projects'

Using project "default".

// 68개 프로젝트 접근 가능 확인

# oc whoami

sysdocu

# oc get ns

...

// 68개 프로젝트 출력

 

fntop 계정으로 전환하고 프로젝트 리스트를 확인합니다.

# oc login -u fntop

Password: (패스워드 입력)

You don't have any projects. You can try to create a new project, by running

oc new-project <projectname>

// 프로젝트 없음 확인

# oc whoami

fntop

# oc get ns

Error from server (Forbidden): namespaces is forbidden: User "fntop" cannot list resource "namespaces" in API group "" at the cluster scope

// 권한 없음 확인

 

원래의 admin 계정으로 전환합니다.

# oc login -u system:admin

You have access to 68 projects, the list has been suppressed. You can list all projects with 'oc projects'
Using project "default".

// 68개 프로젝트 접근 가능 확인

# oc whoami

system:admin

# oc get ns

...

// 68개 프로젝트 출력

 

반응형

댓글()

sed 명령어로 특정 문자가 속한 라인만 수정하기

리눅스/OS 일반|2023. 2. 14. 09:33
반응형

아래는 run.sh 파일에서 master 라는 글자가 들어간 라인만 주석처리 하는 방법입니다.

 

# cat run.sh

#!/bin/bash

echo master >> result.txt
echo slave >> result.txt

 

# sed -i '/master/s/^/#/' run.sh

 

# cat run.sh

#!/bin/bash

#echo master >> result.txt
echo slave >> result.txt

 

 

반응형

댓글()

[Openshift] machine-config 에러 : Failed to resync 4.12.0 because: error during syncRequiredMachineConfigPools

리눅스/OpenShift|2023. 2. 13. 13:40
반응형

Cluster Operators 상태 확인 명령중 machine-config 에서 아래와 같은 오류가 출력되었습니다.

필수 시스템 구성 풀 동기화 중 오류 발생한 내용으로 출력되며,

이에대한 조치는 다음과 같이 할 수 있습니다.

 

 

[ 에러 ]

# oc get co machine-config
NAME             VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
machine-config   4.12.0    True        False         True       4d17h   Failed to resync 4.12.0 because: error during syncRequiredMachineConfigPools: [timed out waiting for the condition, error pool master is not ready, retrying. Status: (pool degraded: true total: 3, ready 0, updated: 0, unavailable: 2)]

 

 

[ 시도 ]

Machine Config 정보를 확인합니다.

# oc get mc
NAME                                               GENERATEDBYCONTROLLER                      IGNITIONVERSION   AGE
00-master                                          2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h
00-worker                                          2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h
01-master-container-runtime                        2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h
01-master-kubelet                                  2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h
01-worker-container-runtime                        2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h
01-worker-kubelet                                  2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h
99-master-generated-registries                     2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h
99-master-ssh                                                                                 3.2.0             4d20h
99-worker-generated-registries                     2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h
99-worker-ssh                                                                                 3.2.0             4d20h
rendered-master-66a1694f13f84151e53205fd83d336d0   2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             16h
rendered-worker-bb1960e620ab292f59adbe8549700341   2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             20h
rendered-worker-e04ed26b510360ba9a8ccbba6aa7382e   2b3eba74dd9e4371f35ab41dbda02642f60707ec   3.2.0             4d18h

 

Machine Config Poll 을 확인합니다.

# oc get mcp
NAME     CONFIG                                             UPDATED   UPDATING   DEGRADED   MACHINECOUNT   READYMACHINECOUNT   UPDATEDMACHINECOUNT   DEGRADEDMACHINECOUNT   AGE
master                                                      False     True       True       3              0                   0                     3                      16h
worker   rendered-worker-e04ed26b510360ba9a8ccbba6aa7382e   False     True       True       2              0                   0                     1                      4d19h

 

위에서 master 만의 문제라면 아래 명령 만으로 상태 제거 (시간이 지나면 다시 자동으로 생성 됌) 하면 되겠지만

# oc delete mcp master

 

실 사례 에서는 worker 노드까지 문제가 발생한 것으로 확인되었습니다.

머신의 구성 풀을 조사하면, 문제의 원인이 설정 변경 때문인지 아닌지를 판단할 수 있습니다.

# oc describe mcp worker |grep -i node
        f:nodeSelector:
            f:node-role.kubernetes.io/worker:
  Node Selector:
      node-role.kubernetes.io/worker:  
    Message:               All nodes are updating to rendered-worker-bb1960e620ab292f59adbe8549700341
    Message:               Node worker01.az1.sysdocu.kr is reporting: "Error checking type of update image: failed to run command podman (6 tries): [timed out waiting for the condition, running podman pull -q --authfile /var/lib/kubelet/config.json quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:6db665511f305ef230a2c752d836fe073e80550dc21cede3c55cf44db01db365 failed: Error: initializing source docker://quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:6db665511f305ef230a2c752d836fe073e80550dc21cede3c55cf44db01db365: reading manifest sha256:6db665511f305ef230a2c752d836fe073e80550dc21cede3c55cf44db01db365 in quay.io/openshift-release-dev/ocp-v4.0-art-dev: unauthorized: access to the requested resource is not authorized\n: exit status 125]"
    Reason:                1 nodes are reporting degraded status on sync
    Type:                  NodeDegraded

 

worker01.az1.sysdocu.kr 노드의 상태를 좀 더 자세히 확인합니다.

# oc describe node/worker01.az1.sysdocu.kr

...

Annotations:        machineconfiguration.openshift.io/controlPlaneTopology: HighlyAvailable
                    machineconfiguration.openshift.io/currentConfig: rendered-worker-e04ed26b510360ba9a8ccbba6aa7382e
                    machineconfiguration.openshift.io/desiredConfig: rendered-worker-bb1960e620ab292f59adbe8549700341
                    machineconfiguration.openshift.io/desiredDrain: uncordon-rendered-worker-e04ed26b510360ba9a8ccbba6aa7382e
                    machineconfiguration.openshift.io/lastAppliedDrain: uncordon-rendered-worker-e04ed26b510360ba9a8ccbba6aa7382e
                    machineconfiguration.openshift.io/reason:
                      Error checking type of update image: failed to run command podman (6 tries): [timed out waiting for the condition, running podman pull -q ...
                      : exit status 125]
                    machineconfiguration.openshift.io/ssh: accessed
                    machineconfiguration.openshift.io/state: Degraded
                    volumes.kubernetes.io/controller-managed-attach-detach: true

...

 

노드 상태는 여전히 Degraded 로 확인되었습니다.

 

[ 해결 ]

insights 항목의 오류 부분을 해결하고자 오류 이벤트를 전송하지 않도록 disable 해놨었는데,

그것이 원인이 되어 machine-config 가 에러 발생한 것이였습니다.

insights 를 disable 하지 않아도 어차피 오류 정보는 전송이 안될테니까 아래 내용으로 돌려놨더니

machine-config 가 정상으로 돌아왔습니다.

 

# oc get co insights
NAME       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
insights   4.12.0    False       False         True       7d16h   Unable to report: unable to build request to connect to Insights server: Post "https://console.redhat.com/api/ingress/v1/upload": x509: certificate is valid for *.apps.az1.sysdocu.kr, not console.redhat.com

 

# oc get co machine-config
NAME             VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
machine-config   4.12.0    True        False         False      7d18h  

반응형

댓글()

[Openshift] 브라우저에서 OpenShift web-console 에 접근하지 못할때

리눅스/OpenShift|2023. 2. 13. 12:55
반응형

로그인 창이 뜨기도 전에 접근이 안된다면 도메인 문제는 아닌가 확인해보세요.

 

[ 에러 ]
아래와 같은 OpenShift web-console URL 을 브라우저에서  접근하려 할때 접근 불가 메세지 출력

(예 : 도메인에 오타가 있는지 살펴보세요. 등)
https://console-openshift-console.apps.az1.sysdocu.kr


[ 조치 ]
실제로 사용하지 않는 테스트 도메인을 입력 후 연결하려 하였을때 발생합니다.
접근하려는 작업 PC 에서 아래와 같이 OpenShift web-console 에 접근하기 위해 사용하는 도메인 두개와 서버 IP 를 hosts 에 등록하면 됩니다.

# vi /etc/hosts
...
192.168.0.2 console-openshift-console.apps.az1.sysdocu.kr oauth-openshift.apps.az1.sysdocu.kr

 

반응형

댓글()

[Openshift] 원격 상태 보고 비활성화 (insights disable, 전역 클러스터 풀 시크릿 업데이트)

리눅스/OpenShift|2023. 2. 13. 12:37
반응형

아래와 같은 명령으로 insights 항목에 에러가 출력된 경우

 

[ 에러 ]
# oc get co insights
insights                                   4.12.0    False       False         True       3d20h   Unable to report: unable to build request to connect to Insights server: Post "https://console.redhat.com/api/ingress/v1/upload": x509: certificate is valid for *.apps.az1.sysdocu.kr, not console.redhat.com

[ 원인 ]
insights 는 윈도우즈나 다른 응용프로그램처럼 프로그램 개선에 참여하기 위해 오류 정보를 SW 개발사로 전송하여 버그 수정 및 패치에 도움을 주고자 하는 일을 담당합니다.
이를 비활성화하여 오류 정보를 보내지 않도록 합니다.

[ 조치 ]
1) 애초에 Openshift 설치시 install-config.yaml 파일에서 Pull secret 값을 입력하지 않습니다.
2) 모르고 설치한 경우 Pull secret 파일을 추출하여 인증값을 제거, 업데이트 합니다.
# oc extract secret/pull-secret -n openshift-config --to=.
# vi .dockerconfigjson

아래 형식으로 남게끔 .dockerconfigjson 파일을 수정합니다.
(앞부분 항목 1개와 중괄호 한개만 지우고, hash 와 email 은 수정하지 않아도 됩니다.)
"cloud.openshift.com":{"auth":"<hash>","email":"<email_address>"}

저장 후 아래와 같이 Pull secret 을 업데이트 합니다.
# oc set data secret/pull-secret -n openshift-config --from-file=.dockerconfigjson

어느정도 시간이 소요되어 결과를 다시 확인하면 아래와 같이 disabled 되었다는 표시가 출력됩니다.
# oc get co insights
insights                                   4.12.0    False       False         False      3d20h   Health reporting is disabled

 

[ 참고 ]

insights 를 비활성화 하면 machine-config 에서 에러가 발생하는 현상이 확인되었습니다.

되돌리면 정상으로 출력되나 다시 insights 에러가 나타나는데 원인은 아직 미확인 되었습니다.

(어쩌면 insights 를 사용 안하려는 목적이였으므로 에러난 채로 두어도 되지 않을까 생각함)

 

# oc get co machine-config
NAME             VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
machine-config   4.12.0    True        False         True       4d19h   Failed to resync 4.12.0 because: error during syncRequiredMachineConfigPools: [timed out waiting for the condition, error pool worker is not ready, retrying. Status: (pool degraded: true total: 2, ready 0, updated: 0, unavailable: 0)]

 


[출처] https://docs.openshift.com/container-platform/4.12/support/remote_health_monitoring/opting-out-of-remote-health-reporting.html#insights-operator-new-pull-secret_opting-out-remote-health-reporting

 

반응형

댓글()

Openshift 4.12.0 on BareMetal 설치 및 설정

리눅스/OpenShift|2023. 1. 20. 10:02
반응형

Openshift 의 무료 버전이 있습니다. 예전 커뮤니티 버전 Openshift origin 이 새 이름 OKD 로 배포되고 있는데요.

공식 홈페이지는 https://www.okd.io 이며, 관련 문서는 https://docs.okd.io/ 에서 확인하실 수 있습니다.

그리고 Openshift 의 Documents 는 다음과 같습니다.

https://docs.openshift.com/container-platform/4.12/welcome/index.html

양쪽 Documents 를 살펴보니 설치와 운영상의 차이는 없어보이고, master 노드와 worker 노드에 사용되는 운영체제가 각각 FCOS (OKD), RHCOS (Openshift) 이라는게 눈에 띄는데요. OKD 가 무료이면 Openshift 는 유료인가 싶어서 레드햇사에 문의를 해보았더니 배포되는 Openshift 이미지로 서비스를 만들어서 무료 제공하면 괜찮지만, 유료로 판매하면 안된다고 하였습니다. 하지만 OKD 는 서비스 구성후 상업용으로 판매해도 된다고 확인하였으며, 운영 환경에서 발생되는 다양한 오류나 버그는 직접 해결해야하는 단점이 있다고 하였습니다.

여기에서는 테스트 목적이므로 Openshift 기반으로 작성되었음을 알려드립니다.

 

[ 테스트에 사용된 서버 ]

- OCP 서버 제외하고, 기입된 CPU, RAM, Disk, IOPS 는 최소 리소스 요구사항입니다.

- 테스트를 진행했던 모든 서버는 공인 IP 1개씩만 사용하였습니다.

  혹시 공인 IP 로 테스트하기 어려운 환경일 경우 사설 IP 를 사용하고 마스커레이드 서버 (게이트웨이) 에서

  외부망으로 연결이 가능하도록 셋팅해 놓으면 됩니다.

- bootstrap 및 master (Control plane) 서버를 지원하는 유일한 운영체제는 RHCOS (Redhat CoreOS) 입니다.

  worker (Compute) 서버는 RHCOS, RHEL 8.4, RHEL 8.5 로 사용이 가능합니다.

- az1 은 클러스터명입니다. 여러개의 클러스터를 구분하기 위해 사용하였습니다.

- 공식 Document 상의 명칭 정리 : Control plane = master, Compute = worker

- 주 명령을 실행하는 첫번째 서버는 Bastion 서버라고도 불리는데 여기에서는 OCP 서버라고 명칭 하도록 하겠습니다.

Hostname IP OS CPU RAM Disk IOPS
ocp.az1.sysdocu.kr 115.68.142.99 CentOS 7.9 2 4GB 50GB 300
bootstrap.az1.sysdocu.kr 115.68.142.100 RHCOS 4.12.0 4 16GB 100GB 300
master01.az1.sysdocu.kr 115.68.142.101 RHCOS 4.12.0 4 16GB 100GB 300
master02.az1.sysdocu.kr 115.68.142.102 RHCOS 4.12.0 4 16GB 100GB 300
master03.az1.sysdocu.kr 115.68.142.103 RHCOS 4.12.0 4 16GB 100GB 300
worker01.az1.sysdocu.kr 115.68.142.104 RHCOS 4.12.0 2 8GB 100GB 300
worker02.az1.sysdocu.kr 115.68.142.105 RHCOS 4.12.0 2 8GB 100GB 300

* OS 이미지 다운로드

CentOS : https://centos.org/download/

RHCOS : https://mirror.openshift.com/pub/openshift-v4/x86_64/dependencies/rhcos/4.12

 

 

1. DNS 설치

 

Openshift 사용을 위해 내부 DNS 를 준비해야 합니다.

OCP 서버에서 DNS, LoadBalancer 및 http 파일 서버 역할을 담당하게 됩니다.

미리 준비가 된 OCP 서버 (CentOS 7) 에서 작업을 진행합니다.

 

# yum -y update

# yum -y upgrade

 

SELinux 비활성화 설정을 하고 적용합니다.

# vi /etc/selinux/config

SELINUX=disabled

 

# setenforce 0

 

호스트 네임을 적용 합니다.

예) hostnamectl set-hostname ocp.az1.sysdocu.kr

 

bind 패키지를 설치합니다.

# yum -y install bind bind-utils

 

정방향 및 역방향 zone 파일을 생성합니다. (둘 다 필요)

# vi /var/named/sysdocu.kr.zone

$TTL 60
@    IN    SOA    ocp.az1.sysdocu.kr.    root (
                                                              2023012001    ; serial
                                                              1D       ; refresh
                                                              1H       ; retry
                                                              1W      ; expire
                                                              3H )    ; minimum

                        IN      NS      ocp.az1.sysdocu.kr.

az1                   IN      A        115.68.142.99
ocp.az1            IN      A        115.68.142.99
helper.az1        IN      A        115.68.142.99
api.az1             IN      A        115.68.142.99
api-int.az1        IN      A        115.68.142.99
*.az1                 IN      A        115.68.142.99

bootstrap.az1   IN      A        115.68.142.100

master01.az1    IN      A        115.68.142.101
master02.az1    IN      A        115.68.142.102
master03.az1    IN      A        115.68.142.103

worker01.az1    IN      A        115.68.142.104
worker02.az1    IN      A        115.68.142.105

 

# vi /var/named/142.68.115.rev.zone

$TTL 60
@    IN    SOA    ocp.az1.sysdocu.kr.    root (
                                                              2023012001    ; serial
                                                              1D       ; refresh
                                                              1H       ; retry
                                                              1W      ; expire
                                                              3H )    ; minimum

             IN    NS    ocp.az1.sysdocu.kr.

99          IN    PTR    api.az1.sysdocu.kr.
99          IN    PTR    api-int.az1.sysdocu.kr.

100         IN    PTR    bootstrap.az1.sysdocu.kr.

101         IN    PTR    master01.az1.sysdocu.kr.
102         IN    PTR    master02.az1.sysdocu.kr.
103         IN    PTR    master03.az1.sysdocu.kr.

104         IN    PTR    worker01.az1.sysdocu.kr.
105         IN    PTR    worker02.az1.sysdocu.kr.

 

외부에서도 질의가 가능하도록 하고 zone 파일을 config 파일에 연결 합니다.

# vi /etc/named.conf

options {
        listen-on port 53 { any; };
        listen-on-v6 port 53 { ::1; };
        directory  "/var/named";
        dump-file  "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        recursing-file  "/var/named/data/named.recursing";
        secroots-file   "/var/named/data/named.secroots";
        allow-query     { any; };

        recursion yes;

        forwarders { 168.126.63.1; };

        dnssec-enable yes;
        dnssec-validation yes;

        bindkeys-file "/etc/named.root.key";

        managed-keys-directory "/var/named/dynamic";

        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";
};

...

 

아래 파일에 zone 파일을 연결합니다.

# vi /etc/named.rfc1912.zones

...

zone "sysdocu.kr" IN {
        type master;
        file "sysdocu.kr.zone";
        allow-update { none; };
};

zone "142.68.115.in-addr.arpa" IN {
        type master;
        file "142.68.115.rev.zone";
        allow-update { none; };
};

 

데몬을 재시작하고 정방향과 역방향 질의가 잘 되는지 테스트 합니다.

# systemctl enable named

# systemctl start named

# nslookup ocp.az1.sysdocu.kr localhost
Server: localhost
Address: 127.0.0.1#53

Name: ocp.az1.sysdocu.kr
Address: 115.68.142.99

 

# nslookup 115.68.142.99 localhost
99.142.68.115.in-addr.arpa name = api-int.az1.sysdocu.kr.
99.142.68.115.in-addr.arpa name = api.az1.sysdocu.kr.

 

서버의 1차, 2차 네임서버를 지정합니다.

네트워크 설정 파일에서의 DNS 도 올바르게 입력해주세요.

NetworkManager 사용시 설정파일에서 바꾸고 데몬 재시작을 해주면 resolv.conf 에도 적용됩니다.

# cat /etc/resolv.conf

# Generated by NetworkManager
search az1.sysdocu.kr
nameserver 115.68.142.99    // 내부 DNS (우선)
nameserver 168.126.63.1      // 외부 DNS

 

2. HTTP 파일 서버 설정

 

# vi /etc/yum.repos.d/nginx.repo

[nginx] 
name=nginx repo 
baseurl=http://nginx.org/packages/centos/7/$basearch/ 
gpgcheck=0 
enabled=1

 

# yum -y install nginx
# systemctl start nginx

 

nginx 를 설정 파일을 열고 아래 내용으로 수정합니다.

 

# vi /etc/nginx/conf.d/default.conf

server {
    listen       8080;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html/files;
        index  index.html index.htm;
        autoindex on;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

 

파일 서버로 사용할 디렉토리를 만듭니다.

# mkdir /usr/share/nginx/html/files

 

설정했던 내용이 적용되도록 합니다.

# systemctl reload nginx

 

방화벽 사용중일 경우 8080 포트 접근이 가능하도록 룰 추가 및 데몬 재시작을 해줍니다.

저는 테스트가 목적이므로 아래와 같이 모든 방화벽 룰을 내렸습니다.

하지만 실제 서비스 구성시 방화벽에 필요한 포트만 오픈하는것이 좋습니다.

# systemctl stop firewalld

 

웹브라우저로 OCP 서버 8080 포트로 접속하면 현재는 파일이 없으므로 상위 디렉토리 이동 링크만 확인됩니다.

http://115.68.142.99:8080

 

3. LB (LoadBalancer) 설정

 

LB 구성을 위해 haproxy 를 설치하고 설정파일을 아래 내용으로 변경 합니다.

# yum -y install haproxy

# cp -arp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.ori
# vi /etc/haproxy/haproxy.cfg

global
  log         127.0.0.1 local2
  pidfile     /var/run/haproxy.pid
  maxconn     4000
  daemon

defaults
  mode                    http
  log                     global
  option                  dontlognull
  option http-server-close
  option                  redispatch
  retries                 3
  timeout http-request    10s
  timeout queue           1m
  timeout connect         10s
  timeout client          1m
  timeout server          1m
  timeout http-keep-alive 10s
  timeout check           10s
  maxconn                 3000

frontend stats
  bind *:1936
  mode            http
  log             global
  maxconn 10
  stats enable
  stats hide-version
  stats refresh 30s
  stats show-node
  stats show-desc Stats for az1 cluster 
  stats auth admin:az1@
  stats uri /stats

listen api-server-6443 
  bind *:6443
  mode tcp
  server bootstrap bootstrap.az1.sysdocu.kr:6443 check inter 1s backup 
  server master01 master01.az1.sysdocu.kr:6443 check inter 1s
  server master02 master02.az1.sysdocu.kr:6443 check inter 1s
  server master03 master03.az1.sysdocu.kr:6443 check inter 1s

listen machine-config-server-22623 
  bind *:22623
  mode tcp
  server bootstrap bootstrap.az1.sysdocu.kr:22623 check inter 1s backup 
  server master01 master01.az1.sysdocu.kr:22623 check inter 1s
  server master02 master02.az1.sysdocu.kr:22623 check inter 1s
  server master03 master03.az1.sysdocu.kr:22623 check inter 1s

listen ingress-router-443 
  bind *:443
  mode tcp
  balance source
  server worker01 worker01.az1.sysdocu.kr:443 check inter 1s
  server worker02 worker02.az1.sysdocu.kr:443 check inter 1s

listen ingress-router-80 
  bind *:80
  mode tcp
  balance source
  server worker01 worker01.az1.sysdocu.kr:80 check inter 1s
  server worker02 worker02.az1.sysdocu.kr:80 check inter 1s

 

데몬이 서버 부팅시 자동 구동 되도록 하고, 설정된 값은 재시작하여 적용합니다.

# systemctl enable haproxy

# systemctl start haproxy

참고로 HAproxy 로드발란서 상태 및 전송량 등 통계를 확인하려면 위에서 설정한대로 아래 URL 및 계정을 이용하여 로그인하면 됩니다.

http://115.68.142.99:1936/stats

계정 : admin / az1@

 

4. Openshift Installer 설치

 

Openshift Installer 는 Redhat 계정을 만들고 다운로드 해야 하지만 미러 서버에서도 설치 파일을 배포하고 있으므로

여기에서는 설치파일을 계정 없이 다운로드 받아 설치를 진행하겠습니다.

하지만 하단에서 secret 키가 필요하므로 반드시 Redhat 계정으로 로그인하여 확인하는 작업이 필요합니다.

 

다운로드 미러 서버 : https://mirror.openshift.com/pub/openshift-v4/clients/ocp/

 

1) install 및 client 파일 다운로드

설치 파일을 미러 서버에서 다운로드 받습니다.

# yum -y install wget

# wget https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.12.0/openshift-install-linux-4.12.0.tar.gz

 

압축을 해제 합니다.

# tar xvzf openshift-install-linux-4.12.0.tar.gz

# ./openshift-install version
./openshift-install 4.12.0
built from commit ba940311c8cb2a07173725e5c2f668df7c61924c
release image quay.io/openshift-release-dev/ocp-release@sha256:4c5a7e26d707780be6466ddc9591865beb2e3baa5556432d23e8d57966a2dd18
release architecture amd64

 

Client 파일을 다운로드 받아 설치합니다.

# wget https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.12.0/openshift-client-linux-4.12.0.tar.gz

# tar xvzf openshift-client-linux-4.12.0.tar.gz

# mv oc kubectl /usr/local/bin/

# oc version
Client Version: 4.12.0
Kustomize Version: v4.5.7

# kubectl version
WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short.  Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.1", GitCommit:"854f807d8a84dde710c062a5281bca5bc07cb562", GitTreeState:"clean", BuildDate:"2023-01-05T01:27:27Z", GoVersion:"go1.19.4", Compiler:"gc", Platform:"linux/amd64"}
Kustomize Version: v4.5.7
Error from server (NotFound): the server could not find the requested resource

 

2) ssh key 생성

클러스터 노드 SSH 접근을 위해 키를 생성합니다.

생성된 키가 노드에 전달되면 클러스터 각 노드 SSH 원격 접속을 할 수 있습니다.

# ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519

# cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMbzVOXu4A6uUsYyD0cbGAhWTF2HdqOIQaIwuk+b4qCQ root@ocp.az1.sysdocu.kr

 

아래 OpenShift 컨테이너 플랫폼을 설치할 때 설치 프로그램에 해당 키를 입력할 예정입니다.

 

3) 설치 구성 파일 생성

설치 디렉토리를 만들고 이동합니다.

# mkdir installation_directory
# cd installation_directory

 

Redhat 로그인 후 아래 URL (Downloads 메뉴) 페이지 맨 하단부에 Tokens 항목을 확인합니다.

https://console.redhat.com/openshift/downloads

 

'Pull secret' 이 있는데 행 끝에 'Copy' 버튼을 눌러 내용을 복사하고 기록해 둡니다.

 

아래 내용으로 yaml 파일을 생성합니다.

# vi install-config.yaml

apiVersion: v1
baseDomain: sysdocu.kr
compute:
- hyperthreading: Enabled
  name: worker
  replicas: 0
controlPlane:
  hyperthreading: Enabled
  name: master
  replicas: 3     
metadata:
  name: az1
networking:
  clusterNetwork:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  networkType: OpenShiftSDN
  serviceNetwork:
  - 172.30.0.0/16
platform:
  none: {}
fips: false
pullSecret: '{"auths": ...}'
sshKey: 'ssh-ed25519 AAAA... root@ocp.az1.sysdocu.kr'

 

baseDomain : DNS 서버 구축시 사용한 도메인

compute: replicas: 수동으로 연결해주어야 하기 때문에 반드시 0 으로 설정합니다.

metadata: name: 클러스터 이름

clusterNetwork : Pod IP 주소가 할당되는 범위

serviceNetwork : 서비스 IP 주소가 할당되는 범위

pullSecret : Redhat 홈페이지에서 복사한 Pull secret 키

sshKey : 위에서 ssh-keygen 으로 생성한 public key

               # cat ~/.ssh/id_ed25519.pub 으로 출력된 키 (행 전체)

networkType : 설치할 클러스터 네트워크 플러그인입니다. (설치 후 변경 불가)

                        지원되는 값은 OVNKubernetes (Default) 및 OpenShiftSDN 입니다.

install-config.yaml 파일에 대한 자세한 설명 : https://docs.openshift.com/container-platform/4.12/installing/installing_bare_metal/installing-bare-metal.html#installation-bare-metal-config-yaml_installing-bare-metal

 

아래에서 manifest 파일 생성시 install-config.yaml 파일이 삭제되므로 만일을 위해 백업을 해둡니다.

# cp -arp install-config.yaml install-config.yaml.bak

# cd ..

 

4) manifest 파일 생성

# ./openshift-install create manifests --dir installation_directory/

INFO Consuming Install Config from target directory 
WARNING Making control-plane schedulable by setting MastersSchedulable to true for Scheduler cluster settings 
INFO Manifests created in: installation_directory/manifests and installation_directory/openshift 

 

생성된 두 개의 디렉토리 안에 다양한 manifest 파일이 생성되었습니다.

# cd installation_directory

# ll
합계 12
-rw-r--r-- 1 root root 3572  1월 26 11:20 install-config.yaml.bak
drwxr-x--- 2 root root 4096  1월 26 11:21 manifests
drwxr-x--- 2 root root 4096  1월 26 11:21 openshift

 

* 참고

manifests/cluster-scheduler-02-config.yml 파일의 mastersSchedulable 파라미터 값은 아래와 같습니다.

- true : Master 에 POD 가 스케쥴링 될 수 있으며, Master 가 Worker 의 역할까지 수행 (Default 값)

- false : Master 는 컨트롤플레인의 역할만 하게 되어 Worker 노드가 추가로 필요 함. (권장 사항)

 

위 내용대로 리소스를 많이 사용하게 될 Worker 노드를 별도로 둘 예정이므로 yaml 파일을 수정합니다.

(mastersSchedulable: true -> false)

# sed -i 's/true/false/' manifests/cluster-scheduler-02-config.yml

 

5) ignition 파일 생성

CoreOS 를 초기 구성하는데 필요한 파일 ignition 파일을 생성합니다.

# cd ..
# ./openshift-install create ignition-configs --dir installation_directory/

INFO Consuming Openshift Manifests from target directory 
INFO Consuming Master Machines from target directory 
INFO Consuming Worker Machines from target directory 
INFO Consuming OpenShift Install (Manifests) from target directory 
INFO Consuming Common Manifests from target directory 
INFO Ignition-Configs created in: installation_directory and installation_directory/auth 

 

# cd installation_directory

# ll

합계 292
drwxr-x--- 2 root root     48  1월 26 11:38 auth
-rw-r----- 1 root root 280621  1월 26 11:38 bootstrap.ign
-rw-r--r-- 1 root root   3572  1월 26 11:20 install-config.yaml.bak

drwxr-x--- 2 root root   4096  1월 26 11:33 manifests.bak
-rw-r----- 1 root root   1719  1월 26 11:38 master.ign
-rw-r----- 1 root root     98  1월 26 11:38 metadata.json

drwxr-x--- 2 root root   4096  1월 26 11:33 openshift.bak
-rw-r----- 1 root root   1719  1월 26 11:38 worker.ign

 

생성된 ignition 파일들을 nginx 파일 서버 디렉토리로 복사하고 다운로드가 가능하도록 퍼미션을 조정합니다.

# cp -arp *.ign /usr/share/nginx/html/files/

# chmod 644 /usr/share/nginx/html/files/*

 

* 참고

추후 클러스터 명 변경 (예 : az1)을 위해 다시 ignition 파일을 생성할 경우 아래 파일은 덮어씌워지지 않으므로 

아래 파일을 수동으로 삭제 후 ignition 파일을 생성해야 합니다.

installation_directory/auth/.openshift_install_state.json

 

5. bootstrap 서버 설치

 

ISO 다운로드 : https://mirror.openshift.com/pub/openshift-v4/dependencies/rhcos/

 

위 URL 에서 RH CoreOS ISO 파일을 다운로드 하고, OS 설치를 위해 CD 굽기 또는 iODD 와 같은 장치에 넣어둡니다.

나머지 서버 6대 (bootstrap, master, worker) 에 설치를 해야 합니다.

- 파일명 : rhcos-4.12.0-x86_64-live.x86_64.iso

 

파일 URL 은 아래와 같은 명령으로도 쉽게 확인이 가능합니다. (위와 같은파일)

# ./openshift-install coreos print-stream-json | grep '\.iso[^.]' | grep x86_64
                "location": "https://rhcos.mirror.openshift.com/art/storage/prod/streams/4.12/builds/412.86.202212081411-0/x86_64/rhcos-412.86.202212081411-0-live.x86_64.iso",

 

* OCP 서버에서 작업합니다.

추후 bootstrap.ign 검증을 위해 해시값이 필요한데, 해시값의 길이가 길어 타이핑이 어려우므로 bootstrap.hash 파일에 해시값 넣습니다.

# cd /usr/share/nginx/html/files

# sha512sum bootstrap.ign |awk {'print $1'} > bootstrap.hash

# sha512sum master.ign |awk {'print $1'} > master.hash

# sha512sum worker.ign |awk {'print $1'} > worker.hash

 

* 여기부터 bootstrap 서버에서의 작업입니다.

bootstrap 서버에 CD 또는 iODD 장치를 연결하고 위에서 다운로드 받았던 RH CoreOS ISO 이미지로 부팅하면 시간이 지나 명령 수행이 가능한 쉘프롬프트로 떨어지게 됩니다.

 

우선 네트워크에 연결되어진 장치명을 확인하고 nmtui (Network Manager TUI) 명령을 이용하여 네트워크 설정을 진행합니다.

$ nmcli d

DEVICE  TYPE        STATE                                                    CONNECTION

eno2        ethernet    connecting (getting IP configuration)     Wired connection 2

eno1        ethernet    unavailable                                             --

lo             loopback   unmanaged                                            --

 

$ nmtui

* IPv4 설정에 아래 내용만 입력하면 됩니다. (IP 와 Subnet 같이 입력, 내부 DNS)

  DNS 는 내부 DNS 만 입력해주세요.

- Addresses : 115.68.142.100/27

- Gateway : 115.68.142.97

- DNS servers : 115.68.142.99

 

셋팅 후 자동으로 네트워크가 구성되는데, 간혹 네트워크 연결이 늦는 경우가 있어

sudo 를 붙여 root 권한으로 데몬을 재시작 해줍니다.

$ sudo systemctl restart NetworkManager

 

ignition 파일의 해시값을 변수에 저장하고 이를 이용하여 OS 설치를 진행합니다.

OS 설치 명령줄 앞에 sudo 를 붙여 root 권한으로 설치 해야 합니다.

$ hash=`curl http://115.68.142.99:8080/bootstrap.hash`

$ sudo coreos-installer install --copy-network --ignition-url http://115.68.142.99:8080/bootstrap.ign /dev/sda --ignition-hash sha512-${hash}

* 사용한 옵션

- 현재 네트워크 정보 복사 (/etc/NetworkManager/system-connections/ 디렉토리 아래 네트워크 설정 파일)

- 노드 유형의 ignition 파일

- 설치할 HDD 장치명

- 노드 유형의 ignition 파일 sha512 다이제스트 (해시값)

 

OS 가 설치 되면, 리부팅을 한 번 해줍니다.

정상 부팅이 될 경우 ignition 파일이 적용되면서 로그인 화면 상단에 아래와 같은 메세지가 출력됩니다.

 

Red Hat Enterprise Linux CoreOS 412.86.202212081411-0 (Optpa) 4.12

Ignition: ran on 2023/01/26 05:32:21 UTC (this boot)

Ignition: user-provided config was applied

SSH host key: SHA256:SOwMQInuqATecciNzA1NcTfAQRJvsn18EbXD9FX0Ycw (ECDSA)

SSH host key: SHA256:XvmtyNr1IWD4P+WNUhd6yIuu2b+7mEBEy+6k1swRIvu (ED25519)

SSH host key: SHA256:5ut4yCLOm0zuEmiBz9bfw75FSS8WjRt3EhyvthuV93A (RSA)

localhost login:

 

* 로그인 방법

OCP 서버에서 ssh 접근을 하면 패스워드 없이 로그인이 가능합니다.

# ssh core@115.68.142.100

 

접속후 서버 시간을 한국 표준시로 맞춰줍니다.

$ sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

 

* root 로그인 허용

core 계정이 아닌 root 계정으로 로그인하고 싶을 경우 아래와 같은 절차를 따릅니다.

# ssh core@115.68.142.100

[core@bootstrap ~]$ sudo su -

[root@bootstrap ~]# passwd    // 새 패스워드 두번 입력

[root@bootstrap ~]# vi /etc/ssh/sshd_config    // ssh 설정파일에서 아래 3가지 옵션 확인 및 수정

PermitRootLogin yes

PasswordAuthentication yes
ChallengeResponseAuthentication no

[root@bootstrap ~]# systemctl restart sshd    // ssh 데몬 재시작

이제 OCP 서버에서 다른 노드로 root 접속이 가능해 졌습니다.

 

* bootstrap 서버 네트워크 문제

bootstrap 서버의 네트워크가 연결 되지 않거나 연결중 끊어지는 경우 네트워크 상태를 확인해봐야 합니다.

연결 문제가 언제 발생할지 모르므로 단절 반복 주기인 5분 동안 (icmp_seq 300회 정도) 외부망 연결을 지켜 봅니다.

여기에서 테스트 할때는 원인은 찾지 못했지만 5분 단절, 5분 연결이 반복 되었기 때문입니다.

$ ping 8.8.8.8

 

끊어진다면 bootstrap 서버에서 NetworkManager 데몬을 몇차례 다시 재시작 해보고 5분 정도 추가 모니터링을 합니다.

끊김이 없다면 bootstrap 서버 설치를 완료한 것이므로 Kubernetes API 연결이 잘 되는지 아래 명령으로 확인해봅니다.

(OCP 서버에서)

# ./openshift-install --dir installation_directory wait-for bootstrap-complete --log-level=info
INFO Waiting up to 20m0s (until 9:17AM) for the Kubernetes API at https://api.az1.sysdocu.kr:6443... 
INFO API v1.25.4+77bec7a up                       
INFO Waiting up to 30m0s (until 9:36AM) for bootstrapping to complete...

 

지금까지의 설정이 올바로 되었다면 파란색 두줄이 출력됩니다. Kubernetes API 연결 확인이 잘 된 것입니다.

(최대 20분까지 대기하지만 이 경우 성공 가능성 낮음)

 

에러 출력시 --------------------

INFO Waiting up to 20m0s (until 4:03PM) for the Kubernetes API at https://api.az1.sysdocu.kr:6443... 
ERROR Attempted to gather ClusterOperator status after wait failure: listing ClusterOperator objects: Get "https://api.az1.sysdocu.kr:6443/apis/config.openshift.io/v1/clusteroperators": EOF 
INFO Use the following commands to gather logs from the cluster 
INFO openshift-install gather bootstrap --help    
ERROR Bootstrap failed to complete: Get "https://api.az1.sysdocu.kr:6443/version": EOF 
ERROR Failed waiting for Kubernetes API. This error usually happens when there is a problem on the bootstrap host that prevents creating a temporary control plane. 

 

이 경우 bootstrap 서버에서 도메인 질의가 잘 되는지 확인합니다.

구입해서 사용하는 도메인일 경우 외부 DNS 로 인해 도메인 연결이 안되는 경우가 있습니다.

(bootstrap 서버에서)

$ ping api.az1.sysdocu.kr

만약 연결이 안되는 것이 맞다면 내부 DNS 에 설정한 zone 파일 내용을 외부 DNS 에도 설정해주면 됩니다.

그리고 서버내 네임서버 설정도 확인이 필요합니다. 아래처럼 내부 DNS 만 있으면 됩니다.

$ cat /etc/resolv.conf

search az1.sysdocu.kr
nameserver 115.68.142.99

------------------------------------

 

이어서 master 노드를 설치합니다.

 

6. master 서버 설치

 

master 서버도 설치 방법은 bootstrap 서버와 같습니다.

설치에 사용되는 파일만 신경써서 작업해 줍니다.

- master 서버 : master.ign 파일 사용

 

설치 후 부팅이 완료되면 한국 표준시로 맞춰줍니다.

$ sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

 

그리고 master 서버들의 etcd 데몬 가동이 확인되고 네트워크 연결 (5분 이상) 이상없음이 확인되면

OCP 서버에서 아까와 같은 모니터링 명령으로 현재 상황을 확인해 봅니다. (최대 30분)

 

# ./openshift-install --dir installation_directory wait-for bootstrap-complete --log-level=info
INFO Waiting up to 20m0s (until 2:09PM) for the Kubernetes API at https://api.az1.sysdocu.kr:6443... 
INFO API v1.25.4+77bec7a up                       
INFO Waiting up to 30m0s (until 2:19PM) for bootstrapping to complete... 

INFO It is now safe to remove the bootstrap resources 
INFO Time elapsed: 15m7s 

 

master 3대 모두 설치하여 클러스터 구성이 완료되면 위와 같이 파란색으로 표시한 메세지가 출력됩니다.

이 시점에서 haproxy 내에 bootstrap 정보를 제거하고 bootstrap 서버를 종료 합니다. (더 이상 사용 안함)

- 로드밸런서에서 bootstrap 서버 정보 삭제

   > haproxy.conf 에서 bootstrap 관련 라인 2줄 주석 처리, 데몬 재시작

      # sed -i '/bootstrap/s/^/#/' /etc/haproxy/haproxy.cfg

      # systemctl restart haproxy
- bootstrap 서버 제거 (서버 종료)

 

OCP 로그인시 자동으로 쿠버네티스 관리자 계정을 설정하게 조치하고 현재 세션에도 적용합니다.

(OCP 서버에서)

# echo "export KUBECONFIG=/root/installation_directory/auth/kubeconfig" >> ~/.bash_profile

# export KUBECONFIG=/root/installation_directory/auth/kubeconfig

 

Openshift CLI 로 현재 사용자를 확인합니다.

# oc whoami
system:admin

 

연결된 노드를 확인합니다.
# oc get nodes
NAME                       STATUS   ROLES                  AGE   VERSION
master01.az1.sysdocu.kr   Ready    control-plane,master   50m   v1.25.4+77bec7a
master02.az1.sysdocu.kr   Ready    control-plane,master   37m   v1.25.4+77bec7a
master03.az1.sysdocu.kr   Ready    control-plane,master   21m   v1.25.4+77bec7a

 

7. worker 서버 설치

 

worker 서버도 설치 방법은 bootstrap 서버와 같습니다.

설치에 사용되는 파일만 신경써서 작업해 줍니다.

- worker 서버 : worker.ign 파일 사용

 

설치 후 부팅이 완료되면 한국 표준시로 맞춰줍니다.

$ sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

 

worker 서버는 master 서버와 달리 부팅 후 자동으로 bootstrap 서버와 연결되지 않기때문에 수동으로 연결을 해주어야 합니다.

worker 노드가 부팅 되면 보류중인 CSR (Certificate Signing Requests) 의 이름 (맨 앞 NAME 값) 을 확인합니다.

(OCP 서버에서)

# oc get csr |grep Pending |grep node-bootstrapper
csr-c4zbq                                        9m10s   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending
csr-j29kg                                        13m     kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper         <none>              Pending

 

이름을 이용하여 보류중인 CSR 을 승인합니다.

# oc adm certificate approve csr-c4zbq

certificatesigningrequest.certificates.k8s.io/csr-c4zbq approved
# oc adm certificate approve csr-j29kg

certificatesigningrequest.certificates.k8s.io/csr-j29kg approved

 

참고로 보류 중인 모든 CSR 을 승인하려면 다음 명령을 수행합니다.

# oc get csr -o go-template='{{range .items}}{{if not .status}}{{.metadata.name}}{{"\n"}}{{end}}{{end}}' | xargs --no-run-if-empty oc adm certificate approve

 

전체 승인에서 처리되지 않은 요청은 개별 승인을 진행해야 합니다.

 

CSR 값이 많을 경우 승인한 CSR 에 대해서 삭제하는것을 고려해볼 수 있을텐데, 만약 Approved 또는 Issued 상태의 CSR을 삭제하면 해당 CSR로 발급된 인증서는 여전히 유효하지만 해당 CSR에 대한 기록은 클러스터에서 삭제됩니다. 이는 나중에 인증서를 관리하거나 디버깅할 때 문제가 될 수 있습니다. 따라서 일반적으로 Approved 또는 Issued 상태의 CSR을 삭제하기 전에 해당 CSR을 사용하여 발급된 인증서를 확인하고 이후에 CSR을 삭제하는 것이 좋습니다.

- 한개의 CSR 을 삭제

# oc delete csr <CSR 이름>

- 모든 CSR 을 삭제

# oc delete csr --all

 

연결된 전체 노드를 출력합니다.

worker 노드가 NotReady 상태라 하더라도 시간이 조금 지나면 Ready 상태로 변경됩니다.

# oc get nodes
NAME                       STATUS   ROLES                  AGE    VERSION
master01.az1.sysdocu.kr   Ready    control-plane,master   131m   v1.25.4+77bec7a
master02.az1.sysdocu.kr   Ready    control-plane,master   118m   v1.25.4+77bec7a
master03.az1.sysdocu.kr   Ready    control-plane,master   102m   v1.25.4+77bec7a
worker01.az1.sysdocu.kr   Ready    worker                 39m    v1.25.4+77bec7a
worker02.az1.sysdocu.kr   Ready    worker                 33m    v1.25.4+77bec7a

 

아래와 같은 명령을 수행하여 클러스터 구성 요소가 모두 연결되었는지 확인합니다.

(AVAILABLE : True, PROGRESSING : False, DEGRADED : False)

시간이 걸려 값이 정상적으로 돌아오는 경우가 있으므로 조금 기다려 봅니다.

(PROGRESSING 항목이 True 인 경우 프로세스가 동작중이라는 뜻)

 

# oc get clusteroperators 또는

# oc get co

NAME                                       VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
authentication                             4.12.0    True        False         False      29m     
baremetal                                  4.12.0    True        False         False      123m    
cloud-controller-manager                   4.12.0    True        False         False      130m    
cloud-credential                           4.12.0    True        False         False      3h38m   
cluster-autoscaler                         4.12.0    True        False         False      122m    
config-operator                            4.12.0    True        False         False      129m    
console                                    4.12.0    True        False         False      35m     
control-plane-machine-set                  4.12.0    True        False         False      123m    
csi-snapshot-controller                    4.12.0    True        False         False      129m    
dns                                        4.12.0    True        False         False      93m     
etcd                                       4.12.0    True        False         False      114m    
image-registry                             4.12.0    True        False         False      93m     
ingress                                    4.12.0    True        False         False      37m     
insights                                   4.12.0    True        False         False      99m     
kube-apiserver                             4.12.0    True        False         False      103m    
kube-controller-manager                    4.12.0    True        False         False      113m    
kube-scheduler                             4.12.0    True        False         False      105m    
kube-storage-version-migrator              4.12.0    True        False         False      93m     
machine-api                                4.12.0    True        False         False      123m    
machine-approver                           4.12.0    True        False         False      122m    
machine-config                             4.12.0    True        False         False      103m    
marketplace                                4.12.0    True        False         False      123m    
monitoring                                 4.12.0    True        False         False      24m     
network                                    4.12.0    True        False         False      129m    
node-tuning                                4.12.0    True        False         False      93m     
openshift-apiserver                        4.12.0    True        False         False      93m     
openshift-controller-manager               4.12.0    True        False         False      93m     
openshift-samples                          4.12.0    True        False         False      88m     
operator-lifecycle-manager                 4.12.0    True        False         False      124m    
operator-lifecycle-manager-catalog         4.12.0    True        False         False      129m    
operator-lifecycle-manager-packageserver   4.12.0    True        False         False      93m     
service-ca                                 4.12.0    True        False         False      129m    
storage                                    4.12.0    True        False         False      129m  

 

* 참고

insights 항목에 오류가 발생될 수 있으나, 이것은 운영중 버그나 오류 데이터를 redhat 에 보내 개선하기 위한 용도로 사용되는 항목으로써 클러스터 서비스에 영향 주는 부분은 아니니 무시하셔도 됩니다.

다만, 이 경우 모든 항목이 완료된 것이 아니기 때문에 아래 명령 결과는 출력되지 않습니다.

 

또는 다음 명령으로 모든 클러스터 구성이 완료되었는지 확인 할 수 있습니다.

모든 구성이 완료 되면 관리 콘솔 URL 과 접속 계정이 출력 됩니다. 이 정보는 다른 명령으로도 확인이 가능합니다.

# ./openshift-install --dir installation_directory/ wait-for install-complete
INFO Waiting up to 40m0s (until 4:28PM) for the cluster at https://api.az1.sysdocu.kr:6443 to initialize... 
INFO Checking to see if there is a route at openshift-console/console... 
INFO Install complete!                            
INFO To access the cluster as the system:admin user when using 'oc', run 'export KUBECONFIG=/root/installation_directory/auth/kubeconfig' 
INFO Access the OpenShift web-console here: https://console-openshift-console.apps.az1.sysdocu.kr 
INFO Login to the console with user: "kubeadmin", and password: "2DBdU-YmKbC-Cn5xF-tVvdF
INFO Time elapsed: 0s                             

 

웹콘솔 URL 주소는 아래 명령으로도 확인이 되고

# oc whoami --show-console
https://console-openshift-console.apps.az1.sysdocu.kr

 

비밀번호는 아래 파일에서 찾을 수도 있습니다.

# cat installation_directory/auth/kubeadmin-password

2DBdU-YmKbC-Cn5xF-tVvdF

 

웹콘솔 계정명은 kubeadmin 입니다.

 

이제 브라우저를 통해 웹 콘솔 접근이 가능합니다.

실제 존재하지 않는 도메인을 테스트로 설정하였을 경우, 접근하려는 작업 PC 에서 아래와 같이

OpenShift web-console 에 접근하기 위해 사용하는 도메인 두개와 서버 IP 를 hosts 에 추가하면 됩니다.

# vi /etc/hosts

...
115.68.142.99 console-openshift-console.apps.az1.sysdocu.kr oauth-openshift.apps.az1.sysdocu.kr

 

* 참고

오퍼레이터 설정이 초기화 되지 않은 경우에는 아래와 같이 출력될 수 있으니 조금 더 기다려 보도록 합니다.

INFO Waiting up to 40m0s (until 4:55PM) for the cluster at https://api.az1.sysdocu.kr:6443 to initialize...

 

이제 설치에 사용되는 ignition 파일을 모두 배포하고 클러스터 구성을 마쳤으므로 nginx 는 중지해도 됩니다.

# systemctl stop nginx

 

반응형

댓글()