OpenShift origin 설치 방법(CentOS 기준)

|

OpenShift origin

OpenShift origin 설치 방법에 대한 자세한 내용은 여기를 참고하시면 됩니다.

아래 포스팅은 제가 직접 OpenShift origin을 구동시킨 방법입니다.

Docker를 이용한 컨테이너로 구동하는 방법과 Binary 파일을 직접받아 설치하는 방법이 있는데, 저는 후자를 선택했습니다. 또한 설치 OS는 ‘CentOS’를 선택했습니다.


Docker 설치 및 실행

sudo yum install -y yum-utils

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

sudo yum makecache fast

sudo yum install -y docker-ce

sudo systemctl start docker

sudo systemctl enable docker

sudo gpasswd -a centos docker


Docker insecure registry 설정

기본적으로 Docker는 Docker Registry 접속을 위해 https를 사용하도록 되어 있습니다. 하지만 http를 이용한 insecure registry 세팅을 해주어야 하는 경우가 있습니다.

CentOS 기준으로 다음과 같이 세팅해줍니다.

더 자세한 내용은 여기를 참조하세요.

sudo sysctl -w net.ipv4.ip_forward=1

sudo su

cat<<EOF>> /etc/docker/daemon.json
{
    "insecure-registries" : ["172.30.0.0/16"]
}
EOF

exit

sudo systemctl daemon-reload

sudo systemctl restart docker


OpenShift 설치

OpenShift 최신 버전은 여기에서 확인할 수 있습니다. 현재 최신 버전인 3.9.0은 알파 버전이라 저는 3.7.1 버전으로 설치를 진행했습니다.

wget https://github.com/openshift/origin/releases/download/v3.7.1/openshift-origin-server-v3.7.1-ab0f056-linux-64bit.tar.gz

tar -xvzf openshift-origin-server-v3.7.1-ab0f056-linux-64bit.tar.gz

mv openshift-origin-server-v3.7.1-ab0f056-linux-64bit openshift-v3.7.1

cd openshift-v3.7.1

sudo cp openshift oc kubectl /usr/local/bin


Cluster Up

그런 다음 다음 명령어를 이용해서 Cluster Up을 해줄 수 있습니다.

oc cluster up

하지만, 만약 AWS EC2의 가상 머신에서 작업하는 경우에는 다음과 같은 작업으로 해주어야 합니다.

metadata_endpoint="http://169.254.169.254/latest/meta-data"

public_hostname="$( curl "${metadata_endpoint}/public-hostname" )"

public_ip="$( curl "${metadata_endpoint}/public-ipv4" )"

oc cluster up --public-hostname="${public_hostname}" --routing-suffix="${public_ip}.nip.io"

다음과 같은 결과가 나오면 성공입니다.

$ oc cluster up --public-hostname="${public_hostname}" --routing-suffix="${public_ip}.nip.io"

Starting OpenShift using openshift/origin:v3.7.1 ...
OpenShift server started.

The server is accessible via web console at:
    https://ec2-13-125-14-154.ap-northeast-2.compute.amazonaws.com:8443

You are logged in as:
    User:     developer
    Password: <any value>

To login as administrator:
    oc login -u system:admin

이제 브라우저를 이용해서 위에 나온 Web Console 주소로 접속해서 사용해보면 됩니다.

ssh 접속시 WARNING - REMOTE HOST IDENTIFICATION HAS CHANGED! 발생하는 경우

|

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

$ ssh snowdeer@13.14.15.16

 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
 @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
 
 IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! 
 Someone could be eavesdropping on you right now (man-in-the-middle attack)! 
 It is also possible that a host key has just been changed. 
 The fingerprint for the RSA key sent by the remote host is
 SHA256:abcdefghijklmnopqrstuvwxyz.
 Please contact your system administrator. 
 Add correct host key in /home/snowdeer/.ssh/known_hosts to get rid of this message. 
 Offending RSA key in /home/snowdeer/.ssh/known_hosts:3 
   remove with:
   ssh-keygen -f "/home/snowdeer/.ssh/known_hosts" -R 13.14.15.16
   ECDSA host key for 13.14.15.16 has changed and you have requested strict checking.
 Host key verification failed.

이 오류는 기존에 접속한 IP Address의 서버와 공개키를 교환한 상태에서 같은 주소로 다른 서버에 접속했기 때문에 발생하는 오류입니다.

이 경우는 다음 명령어를 이용해서 해결할 수 있습니다.

ssh-keygen -R 13.14.15.16

Docker 실습 예제 (Redis)

|

Redis 공식 이미지 사용

Redis 이미지 다운로드(pull)

$ docker pull redis

Using default tag: latest
latest: Pulling from library/redis
d2ca7eff5948: Pull complete
1d1a2245aaa6: Pull complete
9a483dd2a28b: Pull complete
7b78ebdc44f0: Pull complete
79b76500ef26: Pull complete
b2991d9a5624: Pull complete
Digest: sha256:e55dff3a21a0e7ba25e91925ed0d926d959dac09f9099fd1bcc919263305f1e4
Status: Downloaded newer image for redis:latest


Redis 컨테이너 시작

앞에서 가져온 redis 임지를 이용해서 컨테이너를 시작합니다.

$ docker run --name myredis -d redis

a16226308354840de9dadda78bb83f2378dc5cdb0270c097942357b466bf023f

-d 옵션을 주면 컨테이너를 백그라운드에서 실행시킬 수 있습니다.


컨테이너간 연결

redis 컨테이너를 시작하긴 헀지만, 그 이후에 해야 할 일들이 있습니다. 어떻게든 데이터베이스로 연결을 해야 합니다.

redis-cli 도구를 설치하기 위해서 새로운 컨테이너를 생성하고 앞서 생성한 컨테이너와 연결을 해줍니다.

$ docker run --rm -it --link myredis:redis redis /bin/bash

root@c5706ca49d45:/data# redis-cli -h redis -p 6379
redis:6379> ping
PONG

redis:6379> set "abc" 123
OK

redis:6379> get "abc"
"123"

redis:6379> exit

root@c5706ca49d45:/data# exit

exit

--link 옵션을 이용하게 되면 새로운 도커 컨테이너와 기존의 myredis 이름의 컨테이너가 연결이 됩니다. 새로운 컨테이너 안에서 myredis 컨테이너를 redis라는 이름으로 참조합니다. 이러한 작업을 수행하려면 도커는 컨테이너 /etc/hosts에서 redis를 위한 진입점을 생성하고, myredis 컨테이너의 IP 주소를 가리키도록 합니다.

이렇게 하면 Redis 컨테이너의 IP 주소를 전달하거나 찾을 필요없이 redis-cli에서 redis라는 호스트 이름을 사용할 수 있게 됩니다.


볼륨 설정

컨테이너가 종료되면 컨테이너 내부의 데이터는 사라집니다. 따라서 컨테이너안의 데이터를 유지하고 백업하기 위해서는 호스트 또는 다른 컨테이너 간에 데이터를 공유할 수 있는 설정이 필요합니다. 도커에서는 볼륨(Volume)이라는 개념을 통해 컨테이너에 파일 또는 디렉토리를 마운트(Mount)할 수 있습니다.

도커에서 볼륨을 사용하는 방법은 다음과 같이 두 가지 방법이 있습니다.

  • Dockerfile 안에 VOLUME 설정을 사용
  • docker run 명령어를 사용할 때 -v 옵션을 활용

예를 들어 컨테이너 안에 /data라는 볼륨을 생성하고 싶으면 다음과 같이 할 수 있습니다.

VOLUME /data

또는

docker run -v /data redis

기본적으로 디렉토리나 파일은 호스트의 도커 설치 디렉토리(보통은 /var/lib/docker/)안에 마운트됩니다. -v 옵션을 이용해서 호스트의 특정 디렉토리를 컨테이너 안의 디렉토리로 마운트 할 수도 있습니다.

docker run -v [호스트 디렉토리]:[컨테이너 디렉토리] reids

ex) docker run -v /home/snowdeer/docker/data:/data redis


데이터 백업

앞서 만들었던 myredis 컨테이너가 실행 중일 때 백업을 하고 싶으면 다음 명령을 이용해서 백업을 할 수 있습니다.

$ docker run --rm --volumes-from myredis -v $(pwd)/redis-backup:/backup debian cp /data/dump.rdb /backup/

위 명령을 수행하면 현재 호스트 디렉토리에 redis-backup이라는 디렉토리를 만들고 컨테이너 안의 dump.rdb 파일을 호스트로 백업하게 됩니다.


컨테이너 종료와 삭제

컨테이너 종료와 삭제 방법은 다음과 같습니다.

$ docker stop myredis

$ docker rm myredis

만약 모든 컨테이너들을 삭제하고 싶으면 다음과 같이 명령어를 내리면 됩니다.

$ docker stop $(docker ps -aq)

$ docker rm $(docker ps -aq)

Label, Deployment, Service

|

Label

Kubenetes를 이용해 큰 규모의 서비스를 구동하게 되면 다수의 Pod들을 운영하게 될 수 있습니다. 이 경우 다수의 Pod들을 좀 더 편리하게 관리하기 위해서 Kubenetes에서는 Label이라는 기능을 제공하고 있습니다. Label은 key-value 데이터 쌍 형태로 되어 있습니다.

Pod definition에 Label을 추가하는 방법은 다음과 같습니다.

  labels:
    app: nginx


pod-nginx-with-label.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80


다음 명령어를 이용해 Pod를 생성하고 nginx라는 Label을 가진 Pod 리스트를 조회할 수 있습니다.

$ kubectl create -f ./pod-nginx-with-label.yaml

$ kubectl get pods -l app=nginx


Deployment

이제 다수의 컨테이너, Label이 붙은 Pod 등을 이용해서 App을 만들 수 있게 되었지만, 여전히 많은 의문점이 생길 수 있습니다. 예를 들어 Pod를 어떻게 Scaling 할 것인지, 새로운 릴리즈를 어떻게 Roll Out 할 것인지 등의 이슈가 발생할 수 있습니다.

이 경우 Deployment를 이용해서 Pod 들을 관리하거나 업데이트할 수 있습니다.

Deployment Object에는 Pod를 생성하는 템플릿이나 희망 Replica 개수를 정의할 수 있습니다. Label Selector를 이용해서 Pods를 생성하거나 제거하기도 하며, 새로운 업데이트나 릴리즈를 현재 구동중인 Pod들에 안전하게 반영할 수 있게 도와줍니다.


deployment.yaml

다음은 2개의 nginx Pod가 정의된 deployment.yaml 파일입니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template: # create pods using pod definition in this template
    metadata:
      # unlike pod-nginx.yaml, the name is not included in the meta data as a unique name is
      # generated from the deployment name
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80


Deployment 생성

다음 명령어를 이용해서 Deployment를 생성할 수 있습니다.

$ kubectl create -f ./deployment.yaml

$ kubectl get deployment

$ kubectl get pods -l app=nginx


Deployment 업그레이드하기

만약 위의 Deployment에서 nginx 컨테이너의 버전을 1.7.9에서 1.8로 업그레이드하는 경우 다음과 같은 작업을 수행하면 됩니다.

deployment-update.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.8 # Update the version of nginx from 1.7.9 to 1.8
        ports:
        - containerPort: 80


$ kubectl apply -f ./deployment-update.yaml

$ kubectl get pods -l app=nginx


Deployment 삭제

Deployment 삭제는 다음 명령어로 수행합니다.

$ kubectl delete deployment nginx-deployment


Services

service.yaml

Once you have a replicated set of Pods, you need an abstraction that enables connectivity between the layers of your application. For example, if you have a Deployment managing your backend jobs, you don’t want to have to reconfigure your front-ends whenever you re-scale your backends. Likewise, if the Pods in your backends are scheduled (or rescheduled) onto different machines, you can’t be required to re-configure your front-ends. In Kubernetes, the service abstraction achieves these goals. A service provides a way to refer to a set of Pods (selected by labels) with a single static IP address. It may also provide load balancing, if supported by the provider.

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - port: 8000 # the port that this service should serve on
    # the container on each pod to connect to, can be a name
    # (e.g. 'www') or a number (e.g. 80)
    targetPort: 80
    protocol: TCP
  # just like the selector in the deployment,
  # but this time it identifies the set of pods to load balance
  # traffic to.
  selector:
    app: nginx


Service 관리

$ kubectl create -f ./service.yaml

$ kubectl get services

$ kubectl delete service nginx-service

When created, each service is assigned a unique IP address. This address is tied to the lifespan of the Service, and will not change while the Service is alive. Pods can be configured to talk to the service, and know that communication to the service will be automatically load-balanced out to some Pod that is a member of the set identified by the label selector in the Service.

Pod, Volumes, Multiple Containers

|

Pod

Kubenetes에서 Pod는 하나 이상의 컨테이너 그룹을 의미합니다. 하나의 Pod 안에 있는 컨테이너들은 동시에 배포되며 시작, 정지, 교체(Replicated) 등의 작업도 동시에 이루어집니다.


Pod Definition

간단한 Pod 예제는 다음과 같습니다. yaml 형태의 파일로 표현합니다.

pod-nginx.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
    ports:
    - containerPort: 80


Pod Management

아래의 명령어로 Pod를 생성할 수 있습니다.

$ kubectl create -f ./pod-nginx.yaml

$ kubectl get pods


사용이 끝난 pod는 삭제를 해줍니다.

$ kubectl delete pod nginx


Volumes

일반적으로 컨테이너 안의 데이터는 컨테이너의 생명 주기가 끝나면 소멸됩니다. 영구적인 데이터 저장을 위해서 Pod에 호스팅 컴퓨터의 저장소를 Volume이라는 이름으로 마운트해서 사용할 수 있습니다.

Volume의 정의는 다음과 같이 할 수 있습니다.

volumes:
    - name: redis-persistent-storage
        emptyDir: {}

그리고 컨테이너 안에는 위에서 정의한 Volume과 동일한 이름으로 마운트할 수 있습니다.

volumeMounts:
    # name must match the volume name defined in volumes
    - name: redis-persistent-storage
      # mount path within the container
      mountPath: /data/redis


pod-redis.yaml

Volume 및 마운트를 정의한 Pod definition은 다음과 같습니다.

apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    volumeMounts:
    - name: redis-persistent-storage
      mountPath: /data/redis
  volumes:
  - name: redis-persistent-storage
    emptyDir: {}


Volume 타입으로는 다음과 같은 종류가 있습니다.

  • EmptyDir : Pod가 동작하는 동안 존재하는 새로운 디렉토리를 생성함. Pod가 죽거나 재시작되어도 데이터는 유지됨
  • HostPath : 호스트에 이미 존재하는 파일 시스템 (ex. /var/logs)


Multiple Containers

다음과 같이 Pod definition 안에는 복수의 컨테이너를 정의를 할 수 있습니다.

apiVersion: v1
kind: Pod
metadata:
  name: www
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /srv/www
      name: www-data
      readOnly: true
  - name: git-monitor
    image: kubernetes/git-monitor
    env:
    - name: GIT_REPO
      value: http://github.com/some/repo.git
    volumeMounts:
    - mountPath: /data
      name: www-data
  volumes:
  - name: www-data
    emptyDir: {}

Volume은 한 군데서 정의를 했지만 nginxgit-monitor라는 이름의 컨테이너에서 해당 Volume을 동시에 참고하고 있는 것을 확인할 수 있습니다.