9 minute read

개요

이번에는 컨테이너 오케스트레이션의 동작원리와 기술에 대해 정리를 해보고자 한다.

OpenShift

소개

RedHat OpenShift Container Platform, 줄여서 RHOCP는 Kubernetes 오픈소스 프로젝트를 기반으로 제작된 컨테이너 오케스트레이션이다.

Red Hat OpenShift Container Platform
베어 메탈 서버를 포함하여 퍼블릭/온프레미스 데이터센터에서 컨테이너 기반 App을 구축/배포/관리 기능을 엔터프라이즈급 Kubernetes 환경으로서 제공한다.

Red Hat OpenShift 전용
AWS/GCP/Azure/IBM Cloud와 같은 퍼블릭 클라우드에서 관리형 OpenShift 환경을 제공한다. RHOCP에서 제공하는 모든 기능을 이용할 수 있으며 RedHat에서 클러스터를 관리한다.

Red Hat OpenShift Online
클라우드 환경에서 App을 개발/빌드/배포/호스팅 하는 솔루션을 제공하는 호스팅된 공용 컨테이너 오케스트레이션 플랫폼을 제공한다. RedHat에서 클러스터를 관리한다.

Red Hat OpenShift Kubernetes 엔진
RHOCP 에 있는 하위 기능 집합(RHEL CoreOS/CRI-O/Kubernetes Platform/Core Cluster Service)를 제공한다.

Red Hat Code Ready Containers
로컬 개발/시험을 위해 랩탑에서 실행할 수 있는 테스트용 Minimal 환경을 제공한다.

Architecture

RHOCP Architecture

RHOCP에서 통합하는 요소

  • RHEL CoreOS
  • CRI-O, OCI(Open Container Initiative) 컨테이너 런타임 엔진으로 컨테이너를 실행시키기 위해 고안된 매우 가벼운 엔진이다.
  • Kubernetes, 오픈소스 컨테이너 오케스트레이션 플랫폼
  • GUI환경, 셀프 서비스 웹 콘솔.
  • 내부 컨테이너 이미지 레지스트리 및 모니터링 프레임워크와 같은 사전 설치된 App 서비스
  • 프로그래밍 언어 런타임, 데이터베이스, 기타 소프트웨어 패키지의 공인 컨테이너 이미지

선언적 아키텍처

  • OpenShift는 Kubernetes의 선언적 특성을 기반한다.
  • 선언형 아키텍처는 사용자가 시스템 상태를 변경하면, 시스템에서 상태를 업데이트하고 반영하는 구조를 뜻한다.
  • 명령형 아키텍처보다 관리하기 쉽다는 장점이있다.

Control Plane

  • Kubernetes 클러스터는 kubelet 시스템 서비스와 컨테이너 엔진을 실행하는 노드 세트로 구성된다.
  • OpenShift에서는 CRI-O 컨테이너 엔진을 통해 실행한다.

openshift-control-plane

OpenShift 기능

architecture-openshift-kubernetes-engine
OpenShift에서는 App을 자동화,확장 및 유지 관리하는 기능을 제공한다. BYO(Build-Your-Own) Kubernetes 설정에서 추가하고 구성해야 하는 추가 구성 요소가 필요하다.

고가용성

  • Kubernetes는 내부 구성 요소 및 사용자 App 모두의 고가용성을 염두에 두고 설계됬다.
  • etcd 클러스터에서 OpenShift 클러스터 및 해당 App의 상태를 저장한다.
  • etcd에 저장된 배포 구성 등의 리소스에서는 컨테이너를 종료하기 위해 컨테이너를 자동으로 다시 시작하는 기능을 제공한다.
  • App뿐만 아니라 웹 콘솔과 내부 이미지 레지스트리와 같이 클러스터를 구성하는 컨테이너화된 서비스에도 적용된다.

경량 운영체제

  • 민첩성, 이식성, 보안에 중점을 둔 Red Hat의 경량 운영 체제인 Red Hat Enterprise Linux CoreOS에서 실행된다.

부하분산
클러스터에서 3가지 유형의 로드 밸런서를 제공한다.

  • 외부 로드 밸런서, OpenShift API에 대한 액세스를 관리한다.
  • HAProxy 로드 밸런서, 외부에서 내부 App에 액세스하는데 사용되는 HAProxy 기반 로드 밸런서이다.
  • 내부 로드 밸런서, 내부에서 App과 서비스에 액세스하는데 Netfilter 규칙을 사용하는 내부 로드 밸런서이다.

확장 자동화
OpenShift 클러스터는 새 컨테이너를 자동 시작/종료하여 App 트래픽에 맞게 자동 조절 할 수 있다.

로깅 및 모니터링
RHOCP에는 클러스터에 관한 지표를 Prometheus를 기반으로 모니터링하는 기능이 포함되어 있다.

서비스 검색
내부 DNS 서비스를 통해 컨테이너를 이용할 수 있도록 구성되어 있다.

스토리지
Kubernetes에서는 블록/파일 스토리지를 사용할 수 있다.

App 관리
RHOCP를 사용하면 개발자가 APP 개발 및 배포를 자동화 할 수 있다. OpenShift S2I(Source-to-Image) 기능을 사용하여 소스 코드를 기반으로 컨테이너를 자동 빌드 및 배포한다. Python,Ruby,Java,Nodejs 와 같은 런타임 언어와 DB/메시징 서버를 지원한다. App 및 운영자 설치를 통한 카탈로그 확장이 가능한다.

클러스터 확장성

  • 확장 API 및 사용자 지정 리소스 정의와 같은 Kubernetes의 표준 확장 메커니즘을 사용하여 업스트림 Kubernetes에서 제공하지않는 기능이 추가할 수 있다.
  • OLM(Operator Lifecycle Manager)을 통해 운영자로 패키징된 App 및 인프라 구성 요소 검색, 설치, 업데이트 및 관리를 쉽게할 수 있다.
  • operatorhub.io, 공용 리포지토리 및 마켓플레이스로서 OpenShift/OLM을 포함한다.
  • Marketplace, OpenShift클러스터에 배포할 수 있도록 Kubernetes 운영자로 패키징된 소프트웨어에 액세스 할 수 있는 플랫폼이다.

운영자

Kubernetes 운영자

  • Kubernetes 운영자는 Kubernetes API를 호출하여 Kubernetes 리소스를 관리하는 App이다.
  • Kubernetes App의 경우 Kubernetes 리소스에 직접 액세스 해야 하므로 보안 설정이 필요하다.

OpenShift 클러스터 운영자

클러스터 운영자의 경우 openshift-* 프로젝트에 있다.
클러스터 운영자 종류는 아래와 같다.

  • network
  • ingress
  • storage
  • authentication
  • console
  • monitoring
  • image-registry
  • cluster-autoscaler
  • openshift-apiserver
  • dns
  • openshift-controller-manager
  • cloud-credential

실습정리

클러스터 관리

클러스터 노드 확인

[student@workstation ~]$ oc get nodes
NAME       STATUS   ROLES           AGE   VERSION
master01   Ready    master,worker   2d    v1.19.3+012b3ec
master02   Ready    master,worker   2d    v1.19.3+012b3ec
master03   Ready    master,worker   2d    v1.19.3+012b3ec

클러스터 노드 리소스

[student@workstation ~]$ oc adm top node
NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
master01   499m         14%    3235Mi          21%
master02   769m         21%    4933Mi          33%
master03   1016m        29%    6087Mi          40%

포드 로그 확인

[student@workstation ~]$ oc logs --tail 3 -n openshift-image-registry \
>    cluster-image-registry-operator-564bd5dd8f-s46bz
I0614 15:31:29.316773       1 imageregistrycertificates.go:97] ImageRegistryCertificatesController: event from workqueue successfully processed
I0614 15:31:29.317055       1 controllerimagepruner.go:323] event from image pruner workqueue successfully processed
I0614 15:31:29.341756       1 controller.go:333] event from workqueue successfully processed

클러스터 로그 확인

[student@workstation ~]$ oc adm node-logs --tail 1 -u kubelet master01
-- Logs begin at Tue 2021-05-25 16:53:09 UTC, end at Thu 2021-06-10 16:14:58 UTC. --
Jun 09 21:26:11.244996 master01 systemd[1]: kubelet.service: Consumed 6min 24.649s CPU time
-- Logs begin at Tue 2021-05-25 16:53:09 UTC, end at Thu 2021-06-10 16:14:58 UTC. --
Jun 10 16:14:58.104396 master01 hyperkube[1892]: I0610 16:14:58.104356    1892 prober.go:126] Readiness probe for "console-operator-6d89b76984-wd5t8_openshift-console-operator(6e9ddc9d-aacd-462d-81c3-cfe154e8287f):console-operator" succeeded

디버그 모드

[student@workstation ~]$ oc debug node/master01
Creating debug namespace/openshift-debug-node-5zsch ...
Starting pod/master01-debug ...
To use host binaries, run `chroot /host`
Pod IP: 192.168.50.10
If you do not see a command prompt, try pressing enter.
sh-4.4# chroot /host
sh-4.4#

서비스 확인

sh-4.4# systemctl status kubelet
● kubelet.service - Kubernetes Kubelet
   Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/kubelet.service.d
           └─10-mco-default-env.conf, 20-nodenet.conf
   Active: active (running) since Thu 2021-06-10 15:22:22 UTC; 1h 2min ago
...output omitted...

sh-4.4# systemctl status cri-o
● crio.service - Open Container Initiative Daemon
   Loaded: loaded (/usr/lib/systemd/system/crio.service; disabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/crio.service.d
           └─10-mco-default-env.conf, 20-nodenet.conf
   Active: active (running) since Thu 2021-06-10 15:21:56 UTC; 1h 5min ago
...output omitted...
q
q

sh-4.4# crictl ps --name openvswitch
CONTAINER ID    ...   STATE     NAME          ATTEMPT   POD ID
13f0b0ed3497a   ...   Running   openvswitch   0         4bc278dddf007

sh-4.4# exit
exit
sh-4.4# exit
exit

Removing debug pod ...
[student@workstation ~]$

프로젝트 이벤트확인

[student@workstation ~]$ oc get events
LAST SEEN   TYPE      REASON              OBJECT                      MESSAGE
112s        Normal    Scheduled           pod/psql-7d4cc9d6d-m5r59    Successfully assigned install-troubleshoot/psql-7d4cc9d6d-m5r59 to master03
112s        Normal    AddedInterface      pod/psql-578f78ccb-nbm8q    Add eth0 [10.9.0.87/23]
21s         Normal    Pulling             pod/psql-7d4cc9d6d-m5r59    Pulling image "registry.redhat.io/rhel8/postgresq-13:1"
21s         Warning   Failed              pod/psql-7d4cc9d6d-m5r59    Failed to pull image "registry.redhat.io/rhel8/postgresq-13:1": rpc error: code = Unknown desc = Error reading manifest 1 in registry.redhat.io/rhel8/postgresq-13: unknown: Not Found
21s         Warning   Failed              pod/psql-7d4cc9d6d-m5r59    Error: ErrImagePull
8s          Normal    BackOff             pod/psql-7d4cc9d6d-m5r59    Back-off pulling image "registry.redhat.io/rhel8/postgresq-13:1"
8s          Warning   Failed              pod/psql-7d4cc9d6d-m5r59    Error: ImagePullBackOff
112s        Normal    SuccessfulCreate    replicaset/psql-7d4cc9d6d   Created pod: psql-7d4cc9d6d-m5r59
112s        Normal    ScalingReplicaSet   deployment/psql             Scaled up replica set psql-7d4cc9d6d to 1

컨테이너 이미지정보 확인

[student@workstation ~]$ skopeo inspect \
>    docker://registry.redhat.io/rhel8/postgresq-13:1
FATA[0000] Error parsing image name "docker://registry.redhat.io/rhel8/postgresq-13:1": Error reading manifest 1 in registry.redhat.io/rhel8/postgresq-13: unknown: Not Found

클러스터 배포상태 확인

[student@workstation ~]$ oc status
...output omitted...
  deployment #2 running for 10 seconds - 0/1 pods
  deployment #1 deployed 5 minutes ago

[student@workstation ~]$ oc get pods
NAME                             READY   STATUS    RESTARTS   AGE
psql-544c9c666f-btlw8  1/1     Running   0          55s

스토리지 관리

스토리지 클래스 확인

[student@workstation ~]$ oc get storageclass
NAME                    PROVISIONER               RECLAIMPOLICY   ...
nfs-storage (default)   nfs-storage-provisioner   Delete          ...

영구 볼륨(PV) 관리

PV 생성

[student@workstation ~]$ oc get pv \
>   -o custom-columns=NAME:.metadata.name,CLAIM:.spec.claimRef.name
NAME                                       CLAIM
pvc-26cc804a-4ec2-4f52-b6e5-84404b4b9def   image-registry-storage
pvc-65c3cce7-45eb-482d-badf-a6469640bd75   postgresql-storage

영구 볼륨 클레임(PVC) 관리

PVC 확인

[student@workstation ~]$ oc get pvc
NAME                 STATUS   ...  CAPACITY   ACCESS MODES   STORAGECLASS   AGE
postgresql-storage   Bound    ...  10Gi       RWO            nfs-storage    25s

PVC 배포

[student@workstation ~]$ oc set volumes deployment/postgresql-persistent \
>   --add --name postgresql-storage --type pvc --claim-class nfs-storage \
>   --claim-mode rwo --claim-size 10Gi --mount-path /var/lib/pgsql \
>   --claim-name postgresql-storage
deployment.apps/postgresql-persistent volume updated

볼륨 배포

[student@workstation ~]$ oc new-app --name postgresql-persistent \
>   --docker-image registry.redhat.io/rhel8/postgresql-13:1-7 \
>   -e POSTGRESQL_USER=redhat \
>   -e POSTGRESQL_PASSWORD=redhat123 \
>   -e POSTGRESQL_DATABASE=persistentdb
...output omitted...
--> Creating resources ...
    imagestream.image.openshift.io "postgresql-persistent" created
    deployment.apps "postgresql-persistent" created
    service "postgresql-persistent" created
--> Success
...output omitted...

[student@workstation install-storage]$ oc set volumes \
>   deployment/postgresql-persistent \
>   --add --name postgresql-storage --type pvc \
>   --claim-name postgresql-storage --mount-path /var/lib/pgsql
deployment.apps/postgresql-persistent volume updated

볼륨 삭제
리소스 삭제

[student@workstation install-storage]$ oc delete all -l app=postgresql-persistent
service "postgresql-persistent" deleted
deployment.apps "postgresql-persistent" deleted
imagestream.image.openshift.io "postgresql-persistent" deleted

볼륨 삭제

[student@workstation install-storage]$ oc delete pvc/postgresql-storage
persistentvolumeclaim "postgresql-storage" deleted

인증 및 권한

ID 프로바이더

사용자 및 그룹

  • User : API서버와 상호 작용하는 엔터티 역할을 한다.
  • ID : Identity 프로바이더에 등록된 ID 리소스(계정)를 의미한다.
  • Service Account : 사용자 자격증명에 이용한다. 사용자 자격증명이란 root권한을 포함한다.
  • Group : 특정 유저의 권한을 그룹단위로 묶어서 관리하는 단위이다.
  • Role : 역할을 할당하여 사용자, 그룹, 서비스계정에 권한을 부여한다.

인증 방법

  • OAuth 액세스 토큰
  • X509 클라이언트 인증서

요청에 액세스 토큰 이나 인증서가 없으면 system:anonymous/system:unauthenticated를 할당한다.

HTPasswd
htpasswd 명령을 사용하여 자격증명을 생성하고 삭제 등 관리를 할 수 있다.

KeyStone
OpenStack Keystone 서버를 인증 매체로 구성할 수 있다.

LDAP
LDAPv3를 인증 매체로 구성할 수 있다.

GitHub
Github/Github Enterprise Oauth 인증 서버를 인증 매체로 구성할 수 있다.

클러스터 관리자
ID 프로바이더를 구성하고 관리하려면 클러스터 관리자로 액세스할 수 있어야 한다.

  • kubeadmin 가상 사용자로 인증 후 OAuth 액세스 토큰을 부여
  • X509 클라이언트 인증서가 포함된 kubeconfig파일을 사용

환경변수
kubeconfig 파일을 사용하여 oc 명령을 인증하기 위해서 아래 환경 변수를 설정해야한다.

[user@host ~]$ export KUBECONFIG=/home/user/auth/kubeconfig
[user@host ~]$ oc get nodes

혹은

[user@host ~]$ oc --kubeconfig /home/user/auth/kubeconfig get nodes

가상 사용자

  • OpenShift를 설치하면 kubeadmin 이라는 가상 사용자를 기본값으로 생성한다.
  • kube-system 네임스페이스의 kubeadmin 시크릿에서 관리한다.
  • 기본 패스워드는 설치 로그에서 확인해야한다.
...output omitted...
INFO The cluster is ready when 'oc login -u kubeadmin -p shdU_trbi_6ucX_edbu_aqop'
...output omitted...
INFO Access the OpenShift web-console here: https://console-openshift-console.apps.ocp4.example.com
INFO Login to the console with user: kubeadmin, password: shdU_trbi_6ucX_edbu_aqop

가상 사용자 삭제
어드민 정의 사용자에 cluster-admin 역할을 할당 후, 보안을 우해 가상 사용자를 삭제하는 것이 권고된다.

[user@host ~]$ oc delete secret kubeadmin -n kube-system

htpasswd 설정
1.htpasswd 파일 생성 및 id : admin , pw: redhat 이라는 계정정보를 생성

[student@workstation ~]$ htpasswd -c -B -b ~/DO280/labs/auth-provider/htpasswd \
>    admin redhat
Adding password for user admin

-c 생성
-B bcrypt 암호화사용 | 지정없을시 기본값으로 MD5로 암호화한다.

2.htpasswd에 id : developer, pw: developer 라는 계정정보를 생성 및 추가

[student@workstation ~]$ htpasswd -b ~/DO280/labs/auth-provider/htpasswd \
>    developer developer
Adding password for user developer

3.파일내용확인

[student@workstation ~]$ cat ~/DO280/labs/auth-provider/htpasswd
admin:$2y$05$QPuzHdl06IDkJssT.tdkZuSmgjUHV1XeYU4FjxhQrFqKL7hs2ZUl6
developer:$apr1$0Nzmc1rh$yGtne1k.JX6L5s5wNa2ye.

4.시크릿 생성, openshift-config 네임스페이스에 등록하는것을 명심하자

[student@workstation ~]$ oc create secret generic localusers \
>    --from-file htpasswd=/home/student/DO280/labs/auth-provider/htpasswd \
>    -n openshift-config
secret/localusers created

5.cluster-admin 역할 할당

[student@workstation ~]$ oc adm policy add-cluster-role-to-user \
>    cluster-admin admin
...output omitted...
clusterrole.rbac.authorization.k8s.io/cluster-admin added: "admin"

6-1.클러스터의 oauth정보를 yaml형식으로 내려받기

[student@workstation ~]$ oc get oauth cluster \
>    -o yaml > ~/DO280/labs/auth-provider/oauth.yaml

6-2.클러스터 oauth 파일 수정

[student@workstation ~]$ vi ~/DO280/labs/auth-provider/oauth.yaml
apiVersion: config.openshift.io/v1
kind: OAuth
...output omitted...
<아래와 같이 내용추가>
spec:
  identityProviders:
  - htpasswd:
      fileData:
        name: localusers <- 4)에서 등록한 시크릿의 이름
    mappingMethod: claim
    name: myusers <- identity에 등록할 이름
    type: HTPasswd

6-3.파일 업로드 및 갱신

[student@workstation ~]$ oc replace -f ~/DO280/labs/auth-provider/oauth.yaml
oauth.config.openshift.io/cluster replaced

갱신이 성공하면 openshift-authentication네임스페이스의 포드가 정상적으로 재배포 된다. 아래 명령어를 참고

[student@workstation ~]$ oc get pod -n openshift-authentication

7.oauth 활성화 확인

[student@workstation ~]$ oc login -u admin -p redhat
Login successful.
...output omitted...

7-1.cluster-admin 역할 확인

[student@workstation ~]$ oc get nodes
NAME       STATUS   ROLES           AGE    VERSION
master01   Ready    master,worker   2d2h   v1.19.0+d856161
master02   Ready    master,worker   2d2h   v1.19.0+d856161
master03   Ready    master,worker   2d2h   v1.19.0+d856161

cluster-admin역할이 할당된경우 위와 같이 정상적으로 출력된다.

[student@workstation ~]$ oc get users
NAME       UID                                   FULL NAME  IDENTITIES
admin      31f6ccd2-6c58-47ee-978d-5e5e3c30d617             myusers:admin
developer  d4e77b0d-9740-4f05-9af5-ecfc08a85101             myusers:developer

[student@workstation ~]$ oc get identity
NAME                IDP NAME   IDP USER NAME   USER NAME   USER UID
myusers:admin       myusers    admin           admin       31f6ccd2-6c58-47...
myusers:developer   myusers    developer       developer   d4e77b0d-9740-4f...

7-2.일반계정으로 확인

[student@workstation ~]$ oc login -u developer -p developer
Login successful.
...output omitted...

[student@workstation ~]$ oc get nodes
Error from server (Forbidden): nodes is forbidden: User "developer" cannot list
resource "nodes" in API group "" at the cluster scope

8-1.HTPasswd 기존 파일 내려받기

[student@workstation ~]$ oc extract secret/localusers -n openshift-config \
>    --to ~/DO280/labs/auth-provider/ --confirm
/home/student/DO280/labs/auth-provider/htpasswd

8-2.HTPasswd 파일에 계정추가/삭제/정보수정 하기

[student@workstation ~]$ htpasswd -b ~/DO280/labs/auth-provider/htpasswd \
>    manager redhat
Adding password for user manager

8-3.데이터 갱신하기

[student@workstation ~]$ oc set data secret/localusers \
>    --from-file htpasswd=/home/student/DO280/labs/auth-provider/htpasswd \
>    -n openshift-config
secret/localusers data updated

참고자료
1.htpasswd 사용자 제거

[student@workstation ~]$ htpasswd -D ~/DO280/labs/auth-provider/htpasswd manager
Deleting password for user manager

2.htpasswd 기존 계정정보 수정

[student@workstation ~]$ htpasswd -b ~/DO280/labs/auth-provider/htpasswd admin newPasswd
Deleting password for user manager

3.모든 사용자리소스 삭제

[student@workstation ~]$ oc delete user --all
user.user.openshift.io "admin" deleted
user.user.openshift.io "developer" deleted

4.모든 ID리소스 삭제

[student@workstation ~]$ oc delete identity --all
identity.user.openshift.io "myusers:admin" deleted
identity.user.openshift.io "myusers:developer" deleted

RBAC

역할 기반 액세스 제어(RBAC)

보안구성

시크릿

보안 컨텍스트

네트워킹

App 노출시키기

정책 구성

스케줄링 제어

포드 스케줄링 동작 제어

App 리소스 사용제한

스케일 조정

##

Leave a comment