글쓴이 보관물: totoli78

3-Tier container environment configuration using Kubernetes (NginX/Tomcat/MySQL)

쿠버네티스를 활용한 3-Tier 컨테이너 환경 구성을 해보고자 한다. 구성은 도커와 동일하게 아래와 같이 간다.

3-Tier container environment configuration using Docker(NginX/Tomcat/MySQL)

이번에는 구성 시에 1-Container에 WEB/WAS/DB Pod를 각각 띄울 예정이다.

동일한 컨테이너에서 기동하기 때문에 서로에 대한 IP는 변하지 않을 것이고 IP Address는 localhost로 설정해주어야 한다.

그렇기 때문에!!

– WEB-WAS 사이의 연동 설정에서 IP를 localhost로 변경

– WAS-DB 사이의 연동 설정(어플리케이션 부분)에서 DB IP를 localhost로 변경

해주어야한다.. 그렇다면 이미지 부터 다시 말아보자.

1. WEB 구성

1-1. NginX의 WAS 연동 설정 파일에서 IP Address를 localhost로 변경 후 다시 이미지 생성

> $ vi /root/nginx-for-petclinic/nginx/conf

17 http {
18     upstream was-list {
19         #server tomcat-petclinic:8080;
20         server localhost:8080;
21     }
22
23     include       mime.types;
24     default_type  application/octet-stream;

1-2. Dockerfile을 이용하여 이미지 생성

root@master:~/nginx-for-petclinic# pwd
/root/nginx-for-petclinic
root@master:~/nginx-for-petclinic# docker build -t nginx-petclinic:2.0 .

# 이미지 생성 후, 확인

root@master:~/nginx-for-petclinic# docker images
REPOSITORY                               TAG       IMAGE ID       CREATED         SIZE
nginx-petclinic                          2.0       1f34b3ccac6d   5 seconds ago   133MB

1-3. 이미지를 Dockerhub에 저장

> 내가 생성한 이미지를 이따 yaml파일에서 로드할  수 있도록..

root@master:~# docker tag nginx-petclinic:2.0 ghkd5216/nginx-petclinic:2.0
root@master:~# docker push ghkd5216/nginx-petclinic:2.0

The push refers to repository [docker.io/ghkd5216/nginx-petclinic]
52efdeec58ec: Pushed
201e7ba1790a: Pushed
9959a332cf6e: Layer already exists
f7e00b807643: Layer already exists
f8e880dfc4ef: Layer already exists
788e89a4d186: Layer already exists
43f4e41372e4: Layer already exists
e81bff2725db: Layer already exists
2.0: digest: sha256:15cf195c6e6575d744fa0eb07b429d0db3d99f61

2. WAS 구성

2-1. WAS에서는 AP쪽에 DB 설정이 있기 때문에 소스 빌드 및 해당 소스가 디플로이된 이미지를 다시 생성해야 한다.

> $vi /root/spring-framework-for-petclinic/pom.xml

> 515번 라인과 같이 localhost로 변경해주면 된다.

509             <id>MySQL</id>
510             <properties>
511                 <db.script>mysql</db.script>
512                 <jpa.database>MYSQL</jpa.database>
513                 <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName>
514                 <!–<jdbc.url>jdbc:mysql://mysql-petclinic:3306/petclinic?useUnicode=true</jdbc.url>–>
515                 <jdbc.url>jdbc:mysql://localhost:3306/petclinic?useUnicode=true</jdbc.url>
516                 <jdbc.username>root</jdbc.username>
517                 <jdbc.password>petclinic</jdbc.password>
518             </properties>

2-2. 소스 빌드를 위한 자바 변경

> 자바 버전이 1.8이 되도록 수정

root@master:~/spring-framework-for-petclinic# sudo update-java-alternatives –jre-headless –jre –set java-1.8.0-openjdk-amd64

root@master:~/spring-framework-for-petclinic# java -version
openjdk version “1.8.0_292”
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)

2-3. 소스 빌드

> 소스를 빌드하고 나면, 현 디렉토리에 target 안에 petclinic.war라는 소스 파일이 빌드되어 있을 것이다.

root@master:~/spring-framework-for-petclinic# mvn clean package -Dmaven.test.skip=true -P MySQL

…(중략)

[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time:  13.144 s
[INFO] Finished at: 2021-11-16T18:04:01+09:00
[INFO] ————————————————————————

2-4. WAS 이미지 생성

> 이제 만든 소스를 활용하여 tomcat 이미지를 만들어보도록 하자.

우선 이미지 생성을 위해 Dockerfile을 생성하고 위에서 만들었던 petclinic.war 파일을 Dockerfile 디렉토리에 위치시킨다.

root@master:/home/dockerfile/petclinic# pwd
/home/dockerfile/petclinic
root@master:/home/dockerfile/petclinic# ls -arlt
total 40644
drwxr-xr-x 5 root root     4096 11월  7 14:06 ..
-rw-r–r– 1 root root 41605349 11월  7 14:06 petclinic.war
-rw-r–r– 1 root root       64 11월  7 14:06 Dockerfile
drwxr-xr-x 2 root root     4096 11월  7 14:06 .

==================================================
하기는 Dockerfile 내용이다.
==================================================
root@master:/home/dockerfile/petclinic# cat Dockerfile
From tomcat:8-jre8
ADD petclinic.war /usr/local/tomcat/webapps/

위와 같이 준비가 되었다면 이제 해당 위치에서 이미지 빌드를 하면 된다.

커맨드는 아래와 같다.

root@master:/home/dockerfile/petclinic# docker build -t tomcat-petclinic:2.0 .
Sending build context to Docker daemon  41.61MB
Step 1/2 : From tomcat:8-jre8
—> cff25871f024
Step 2/2 : ADD petclinic.war /usr/local/tomcat/webapps/
—> 1c6d007012d5
Successfully built 1c6d007012d5
Successfully tagged tomcat-petclinic:2.0

2-5. 이미지를 Dockerhub에 저장

> 내가 생성한 이미지를 이따 yaml파일에서 로드할  수 있도록..

root@master:~# docker tag tomcat-petclinic:2.0 ghkd5216/tomcat-petclinic:2.0
root@master:~# docker push ghkd5216/tomcat-petclinic:2.0
The push refers to repository [docker.io/ghkd5216/tomcat-petclinic]
3fe16f1fe077: Pushed
7a1149e8d0d8: Layer already exists
f3d15ade5c54: Layer already exists
80ac7083a323: Layer already exists
01de28a83f3f: Layer already exists
74a293db1084: Layer already exists
68c1e7509c65: Layer already exists
6ccd0e6bdf7a: Layer already exists
9f9f651e9303: Layer already exists
0b3c02b5d746: Layer already exists
62a747bf1719: Layer already exists
2.0: digest: sha256:7ee8909691df00b211aa42f1605062019422b0d93d52053d4ad01034390e04a7 size: 2631

3. YAML 파일 생성

이제 이미지도 준비되었고, yaml 파일만 생성하여 기동해보면 된다.
도커와는 다르게 쿠버네티스의 경우에는 쿠버네티스 클러스터 내에서 동작하기 때문에 생성된 컨테이너의 IP 또한 클러스터 내의 CNI 네트워크 대역으로 할당된다.

그렇기 때문에 외부에서 해당 컨테이너에 접근하여 서비스를 호출하려면 Service를 통해 가능하다. AWS나 GCP같은 Public Cloud의 경우에는 Service에서 LoadBalnancer를 제공하여 외부로 노출할 IP를 할당 받지만, 우리가 테스트하는 방식과 같이 Baremetal(On-Premise) 환경에서는 LoadBalancer 기능이 없다. 그래서 LoadBalancer타입을 지원하게끔 하기 위해 MetalLB라는 놈을 사용해주어야 한다.

먼저 metalb을 설치해보면 아래와 같다.

root@master:~/yaml# kubectl apply -f  https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml

=================================
metallb.yaml 파일을 이용하여 파드와 기타 등등의 서비스를 실행한다.
이후, metallb-system 네임스페이스에 있는 리소스들을 조회해본다.
=================================

root@master:~/yaml# kc get all -n metallb-system

NAME                              READY   STATUS    RESTARTS   AGE
pod/controller-675d6c9976-d5k57   1/1     Running   0          9s
pod/speaker-h4l8n                 1/1     Running   0          9s
pod/speaker-rm54l                 1/1     Running   0          9s

NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                 AGE
daemonset.apps/speaker   2         2         2       2            2           beta.kubernetes.io/os=linux   9s

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/controller   1/1     1            1           9s

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/controller-675d6c9976   1         1         1       9s

이제 3-Tier환경의 컨테이너를 생성할 차례다.

yaml 파일의 경우 아래와 같다.

모든 항목들을 세세히 설명할 수는 없고 하나씩 찾아보면 기본적인 설정(포트/환경변수)만 되어있음을 볼 수 있다.

이 글에서는 가볍게 구성해보는 것이기 때문에 다음 글에서 좀 더 yaml 문법이나 파라미터 값을 공부해보아야 겠다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: petclinic-deployment
  namespace: default
  labels:
    app: petclinic-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
       app: petclinic-app
  template:
    metadata:
      labels:
        app: petclinic-app
    spec:
      containers:
      - image: mysql:5.7.8
        imagePullPolicy: Always
        name: mysql-petclinic
        ports:
        - containerPort: 3306
          protocol: TCP
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: petclinic
        - name: MYSQL_DATABASE
          value: petclinic
      - image: docker.io/ghkd5216/nginx-petclinic:2.0
        imagePullPolicy: Always
        name: nginx-petclinic
        ports:
        - containerPort: 80
          protocol: TCP
      - image: docker.io/ghkd5216/tomcat-petclinic:2.0
        imagePullPolicy: Always
        name: tomcat-petclinic
        env:
        - name: JAVA_OPTS
          value: "-Xms512m -Xmx512m"
        ports:
        - containerPort: 8080
          protocol: TCP
      restartPolicy: Always

---

apiVersion: v1
kind: Service
metadata:
  name: petclinic-svc
spec:
  type: LoadBalancer
  selector:
    app: petclinic-app
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80


---

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.1.240-192.168.1.250

> 제일 하단에 metallb 관련 설정을 보면 addresses 범위 안에서 외부로 노출할 ExternalIP 대역을 설정할 수 있다.

이제 만든 yaml 파일을 실행하여 보자!!

4. Kubernetes를 통한 컨테이너 배포

root@master:~/yaml# kc apply -f petclinic-app.yaml
deployment.apps/petclinic-deployment created
service/petclinic-svc created
configmap/config created

root@master:~/yaml# kc get all
NAME                                        READY   STATUS    RESTARTS   AGE
pod/petclinic-deployment-86dc87794d-j69mm   3/3     Running   0          24s

NAME                    TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
service/kubernetes      ClusterIP      10.96.0.1        <none>           443/TCP        13d
service/petclinic-svc   LoadBalancer   10.109.251.153   192.168.56.240   80:30560/TCP   24s

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/petclinic-deployment   1/1     1            1           24s

NAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/petclinic-deployment-86dc87794d   1         1         1       24s

> 위와 같이 LoadBalancer 타입의 Service가 생성되어 External-IP를 할당하여 외부로 노출하는 것을 볼 수 있다.

이제 모든 준비가 끝났다.

실제로 외부의 웹 브라우저에서 클라이언트 입장으로 서비스를 호출해보자. 호출 url은 EXTERNAL_IP:[LB PORT]/petclinic 이다.

나의 경우에는 http://192.168.56.240:80/petclinic/으로 호출하면 된다.

5. 서비스 호출

 

 

> 외부 노출 IP로 정상적으로 접근 가능하다. 몇 가지 업무 테스트를 해보면,

 

 

정상적으로 데이터가 DB에 저장되는 것을 볼 수 있다.

3-Tier container environment configuration using Docker(NginX/Tomcat/MySQL)

이번 글에서는 Docker를 사용하여 간단한 3-Tier 컨테이너 환경을 구성해보고자 한다.

– WEB = NginX

– WAS = Tomcat

– DB = MySQL

구성은 WAS -> WEB -> DB 순으로 하도록 한다.

우선,  WAS 부터 구성해보도록 하자.

1. WAS 구성

1-1. Github에 올라가 있는 어플리케이션 소스 다운로드

> 소스를 다운받을 디렉토리 생성 후 Git 저장소에서 소스를 Pull 한다.

root@master:~# mkdir -p /home/src
root@master:~# cd /home/src
root@master:/home/src#

root@master:/home/src# git clone https://github.com/Hwang-sangyeon/spring-framework-for-petclinic.git
Cloning into ‘spring-framework-for-petclinic’…
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 4 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), 1.89 MiB | 4.96 MiB/s, done.

1-2. JDK와 Maven 설치

> 소스를 컴파일 하기 위해 OpenJDK와 Maven을 설치한다.

root@master:~# sudo apt-get install openjdk-8-jdk maven

(중략)

update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/bin/unpack200 to provide /usr/bin/unpack200 (unpack200) in auto mode
update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/lib/jexec to provide /usr/bin/jexec (jexec) in auto mode
Setting up libxdmcp-dev:amd64 (1:1.1.3-0ubuntu1) …
Setting up x11proto-core-dev (2019.2-1ubuntu1) …
Setting up libxcb1-dev:amd64 (1.14-2) …
Setting up libx11-dev:amd64 (2:1.6.9-2ubuntu1.2) …
Setting up libxt-dev:amd64 (1:1.1.5-1) …

1-3. JAVA_HOME 설정

> 현재 java -version으로 버전 확인 시 설치한 자바로 설정되어 있지 않기 때문에 아래와 같이 변경이 필요하다.

root@master:/home/src# sudo update-java-alternatives –list
java-1.11.0-openjdk-amd64      1111       /usr/lib/jvm/java-1.11.0-openjdk-amd64
java-1.8.0-openjdk-amd64       1081       /usr/lib/jvm/java-1.8.0-openjdk-amd64
root@master:/home/src#
root@master:/home/src#
root@master:~# sudo update-java-alternatives –jre-headless –jre –set java-1.8.0-openjdk-amd64

root@master:/home/src# java -version
openjdk version “1.8.0_292”
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)

1-4. 소스 Build

> 이제 소스와 컴파일 할 JDK와 maven도 준비되었기 때문에 Compile을 해보도록 하자

소스 경로에 들어가 압축을 풀고 아래와 같이 빌드를 진행해준다.

빌드 전에 잠시 소스 수정이 필요하다.
pom.xml에 mysql 연동 부분에 localhost:3306을 mysql-petclinic:3306으로 수정하자.
was와 db가 다른 컨테이너로 기동되기 때문에 localhost를 인식할 수 없다.
그러나 mysql-petclinic은 컨테이너 명으로 link가 걸려 통신이 가능하다..

root@master:/home/src/spring-framework-for-petclinic/spring-framework-for-petclinic# mvn clean package -Dmaven.test.skip=true -P MySQL

…(중략)

[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time:  16.802 s
[INFO] Finished at: 2021-11-07T13:54:37+09:00
[INFO] ————————————————————————

=========================================================================
빌드를 하고 나면, 소스 경로 하위의 target 디렉토리에 petclinic.war 소스 파일이 생성된다.

root@master:/home/src/spring-framework-for-petclinic/spring-framework-for-petclinic/target# ls -arlt|grep petclinic.war
-rw-r–r– 1 root root 41605349 11월  7 13:54 petclinic.war

1-5. WAS 이미지 생성

> 이제 만든 소스를 활용하여 tomcat 이미지를 만들어보도록 하자.

우선 이미지 생성을 위해 Dockerfile을 생성하고 이전에 만들었던 petclinic.war 파일을 같은 디렉토리에 위치시킨다.

root@master:/home/dockerfile/petclinic# pwd
/home/dockerfile/petclinic
root@master:/home/dockerfile/petclinic# ls -arlt
total 40644
drwxr-xr-x 5 root root     4096 11월  7 14:06 ..
-rw-r–r– 1 root root 41605349 11월  7 14:06 petclinic.war
-rw-r–r– 1 root root       64 11월  7 14:06 Dockerfile
drwxr-xr-x 2 root root     4096 11월  7 14:06 .

하기는 Dockerfile 내용이다.
root@master:/home/dockerfile/petclinic# cat Dockerfile
From tomcat:8-jre8
ADD petclinic.war /usr/local/tomcat/webapps/

위와 같이 준비가 되었다면 이제 해당 위치에서 이미지 빌드를 하면 된다.

커맨드는 아래와 같다.

root@master:~/docker/tomcat-test# docker build -t tomcat-petclinic .
Sending build context to Docker daemon  41.61MB
Step 1/2 : From tomcat:8-jre8
8-jre8: Pulling from library/tomcat
bb7d5a84853b: Pull complete
f02b617c6a8c: Pull complete
d32e17419b7e: Pull complete
ab18cfab55f9: Pull complete
793716e93ecb: Pull complete
3b9b14f7678b: Pull complete
4dc2d594b57d: Pull complete
3f275ee15a3d: Pull complete
15b0db619216: Pull complete
c0aa838e7a3a: Pull complete
Digest: sha256:47165dabe7c092c61ef2726a7fdc70dda0ce9dea07ca68bda0aea6ecfaba2873
Status: Downloaded newer image for tomcat:8-jre8
—> cff25871f024
Step 2/2 : ADD petclinic.war /usr/local/tomcat/webapps/
—> f27039d77fc4
Successfully built f27039d77fc4
Successfully tagged tomcat-petclinic:latest

2. WEB 구성

2-1. NginX 리소스 다운로드

> Git에 올라가 있는 NginX 리소스를 다운받는다.

root@master:/home/src# git clone https://github.com/Hwang-sangyeon/nginx-for-petclinic.git
Cloning into ‘nginx-for-petclinic’…

리소스 다운로드 후,

nginx.conf 파일에서 was 연동 포트 확인 및 nginx listen-port를 확인한다.

2-2. 이미지 생성

> Dockerfile이 있는 디렉토리에서 이미지를 빌드한다.

root@master:/home/src/nginx-for-petclinic/nginx-for-petclinic# docker build -t nginx-petclinic .
Sending build context to Docker daemon  6.656kB

2-3. WEB/WAS 이미지 확인

root@master:/home/src/nginx-for-petclinic/nginx-for-petclinic# docker images|grep petclinic
nginx-petclinic                          latest    952aff9083ee   19 seconds ago   133MB
tomcat-petclinic                         latest    39e56a91e5e7   9 minutes ago    334MB

3. 컨테이너 기동

이제부터는 필요한 이미지가 준비되었기 때문에 WEB/WAS/DB 컨테이너를 기동하여 3-Tier를 구성을 해보려고 한다.

여기서 중요한 점은 WAS가 기동되기 전에 (소스 빌드) DB가 먼저 떠있어야 하기 때문에 DB 컨테이너를 반드시 먼저 기동시켜야 한다는 것이다.

3-1. DB 컨테이너 기동

> mysql-petclinic 컨테이너 명으로 mysql 이미지를 바로 받아 컨테이너를 실행한다.

docker run --name mysql-petclinic -e MYSQL_ROOT_PASSWORD=petclinic -e MYSQL_DATABASE=petclinic -p 3306:3306 mysql:5.7.8

Initializing database 이후 docker container ps로 확인

root@master:~# docker container ps | grep mysql
d286f5c59a6c   mysql:5.7.8            “/entrypoint.sh mysq…”   57 seconds ago      Up 56 seconds      0.0.0.0:3306->3306/tcp, :::3306->3306/tcp   mysql-petclinic

3-2. WAS 컨테이너 기동

docker run -it --rm -p 8080:8080 --name tomcat-petclinic --link mysql-petclinic:mysql-petclinic tomcat-petclinic

> tomcat 컨테이너에서 mysql 컨테이너의 ip로 접속할 수 있겠지만, static ip가 아니기 때문에 mysql 컨테이너의 이름으로 접속을 해야 할 필요가 있다. 이럴 경우 link 옵션을 통해 컨테이너를 구동하면 tomcat 컨테이너에서 mysql 컨테이너로 이름으로 접속할 수 있다. link 옵션으로 구동하면 톰캣 컨테이너 안의 /etc/hosts에 링크된 mysql 컨테이너 hostname과 ip가 들어간다.

3-3. WEB 컨테이너 기동

docker run -it --rm -p 80:80 --name nginx-petclinic --link tomcat-petclinic:tomcat-petclinic nginx-petclinic

4. 서비스 호출

 

192.168.56.200은 VM의 IP

 

이상 도커를 활용하여 3-Tier 컨테이너 환경을 구성해보았다..

DiskPart command concept and how to use.

Diskpart 개념과 사용 방법 안내

Windows OS에서 디스크 파티션을 조작할려면 [컴퓨터 관리]에 있는 [저장소] → [디스크 관리]를 사용하는 것이 일반적일 것입니다. 하지만 diskpart.exe라는 명령어를 이용해서도 똑같은 작업을 할 수 있습니다.

※ Diskpart는 파티션 작업 명령으로 데이터가 삭제되므로 중요 데이터 백업 및 확인후 사용토록 주의하시기 바랍니다.

Diskpart 란?

– Windows98이나 Windows ME에서 사용하던 Fdisk를 대체하는 파티션 툴로 동적 디스크를 지원하고, 디스크 관리 스냅인에서 지원하는 것보다 더 많은 작업을 수행할 수 있습니다. 디스크 관리 스냅인은 사용자가 실수로 데이터 손실을 초래할 수 있는 작업을 수행하지 못하도록 하지만, Diskpart를 사용하면 파티션과 볼륨을 명시적으로 제어할 수 있으며, 이런 기능 때문에 신중히 사용해 주셔야 합니다.

– 윈도우 XP, 2000, Vista, 7 이상 OS에서 사용 가능합니다. (위치 : C:\Windows\****32 폴더내 있습니다.)

Diskpart 사용 방법

1] Diskpart 모드 진입하기

  • 1. **** 모드로 CMD 콘솔 실행합니다.
  • 방법 : 시작 > 프로그램 및 파일 검색(또는 Windows 검색) 창에 ‘CMD’ 입력 > CMD 항목에 마우스 오른쪽 버튼 클릭 후 ‘**** 권한으로 실행’ 선택

    시작을 눌러 검색창에 cmd 입력하여 검색후 마우스 오른쪽 버튼을 눌러 **** 권한으로 실행을 클릭하는 예시 화면

  •  
  • 2. diskpart 입력 후 엔터를 칩니다.

    diskpart 입력하고 엔터 치는 창

  •  
  • 3. DISKPART> 프롬프트 발생하면 이후 사용 가능합니다.

    diskpart 명령프롬프트 떠 있는 창

2] 디스크 초기화하기

Diskpart 모드 진입 상태에서 명령어를 이용하여 하드디스크의 파티션을 모두 초기화합니다.

  •  
  • 1. list disk : 디스크목록 보기
  •  
  • 2. select disk 1 : 초기화할 disk를 선택합니다. (“sel disk 1” 와 동일)
  •  
  • 3. list partition : 파티션정보 확인 (“list part” 와 동일)
  •  
  • 4. clean : 선택된 디스크의 파티션정보를 전부 초기화
  •  
  • 5. list partition : 파티션 정보 사라짐 확인
  • 위 5가지 목록에 대하여 명령어를 입력하고 진행한 화면창

  • ※ 여기서 포커스란 개념이 나옵니다. select 명령을 이용해 작업하고자 하는 객체에 포커스를 주어야 합니다. select disk 1 이라고 주고 list disk 하자 disk 1 옆에 * 가 붙었습니다. 앞으로 disk 1 이 작업대상이 된 겁니다. (select disk=1이라고 해도 됩니다.)

3] 디스크 파티션 분할하기

하드디스크의 파티션을 분할(주, 확장, 논리) 합니다.

  •  
  • 1. list disk : 디스크 목록 보기
  •  
  • 2. select disk 1 : 초기화할 disk를 선택합니다.
  •  
  • 3. list partition : 파티션 정보 확인
  •  
  • 4. create partition primary size = 120000 : 주파티션을 120GB만큼 생성하는 명령어
  •  
  • 5. create partition extended : 확장파티션 생성
  •  
  • 6. create partition logical : 논리파티션 생성
  • 위의 6가지 항목을 차례대로 명령어 입력해서 진행한 창

※ create partition primary size = 120000

120000M 크기(size=120000)의 주파티션(primary partition)을 만들라(create)는 명령입니다. size 지정을 안하게 되면 이용가능한 모든 용량을 잡습니다. 파티션을 1개만 잡을 때 또는 마지막 파티션을 잡을 때는 size 옵션을 생략하면 됩니다. 주파티션은 4개까지 만들 수 있고, 그 이상을 만들려면 주파티션 1개 대신 확장파티션을 잡아야 합니다. 즉, 최대 주파티션 3개 확장파티션 1개가 됩니다. 확장파티션은 디스크당 1개만 만들 수 있습니다. 확장파티션에서 원하는 개수만큼 논리드라이브를 만듭니다.

※ 확장 파티션 설정

create partition extended : 확장파티션(extended partition)을 만들라(create)는 의미입니다. size 지정이 없으면 disk의 남은 용량을 전부 이용합니다. 확장 파티션에서는 반드시 1개 이상의 논리드라이브를 지정해 주어야 합니다. create partition logical size = 250 라고 하면 250메가의 논리드라이브(partition logical)가 생성되고, create partition logical size = 100 하면 100메가의 논리드라이브(partition ligical)가 추가 생성됩니다. create partition logical 이라고만 하면 나머지 용량을 모두 잡습니다. list partition을 입력하면 선택한 디스크의 파티션 정보를 볼 수 있습니다.

디스크관리의 디스크1의파티션에 포맷과 드라이브 문자 할당이 안되어있는 화면
※ create partition 이후 디스크 관리에서 디스크1의 파티션에 포맷과 드라이브 문자 할당이 안 되어 있습니다.

4] 파티션 포맷하기

분할된 파티션을 포맷합니다.

  •  
  • 1. format fs=ntfs quick : 현재 선택되어 있는 파티션을 ntfs로 빠른 포맷한다.
  •  
  • 2. list partition : 파티션 선택 확인
  •  
  • 3. select partition 1 : 포맷할 파티션 선택
  •  
  • 4. format fs=ntfs quick : 선택한 파티션을 ntfs로 빠른 포맷합니다.
    ※ 참고로 fs=fat32로 하면 FAT32로 포맷합니다. (단, 30GB 이하일 경우에만 진행해야 합니다.)

    위 4번항목에 대한 명령어를 모두 입력한 상태창

  •  
  • 5. 디스크 관리에서 포맷 완료는 확인되나, 아직 드라이브 문자 할당은 안된 상태로 보이게 됩니다.

    디스크관리에서 포맷완료는 했으나 드라이브 할당이 안된 상태창

5] 파티션[드라이브] 문자 할당

분할된 파티션에 드라이브명을 할당합니다.

  •  
  • 1. assign letter=x : 선택되어 있는 파티션에 X 드라이브명 할당
  •  
  • 2. list partition : 선택된 파티션을 확인

    위 2가지 항목에 대한 명령어 실행 화면창

  •  
  • 3. select partition 2 : 문자를 할당할 파티션을 선택
  •  
  • 4. assign letter=Z : 선택되어있는 파티션에 Z드라이브명 할당

    select partition 2 입력하고 list patition입력후 assign letter=Z 명령어 입력창

  •  
  • 5. 디스크1의 파티션에 드라이브명이 할당된 것을 확인할 수 있습니다.

    디스크1의 파티션에 드라이브명이 x와 z로 할당된 상태창

  • ※ assign letter=X 명령어에서, letter=X 옵션을 안쓰면 차례로 미사용 문자가 할당됩니다. list volume을 입력하면 선택한 디스크의 볼륨(드라이브명)을 확인할 수 있습니다.

6] 파티션 삭제하기

분할된 파티션을 삭제합니다.

  •  
  • 1. 파티션 4,5,6(볼륨 3,4,5)에 각각 X:, Y:, Z: 가 할당된 파티션입니다.

    파티션 4,5,6에 각각 X:, Y:, Z: 할당된 파티션 창

  •  
  • 2. 파티션을 삭제합니다. 볼륨으로 지정하는 경우 드라이브명이 지정되어 있다면, 드라이브명을 쓸 수 있습니다. 볼륨 번호랑 파티션 번호가 다르니 혼동하지 않도록 주의하세요.
  • select volume z 볼륨 z에 포커스를 맞춥니다. (select volume=z 도 같음 “=” 생략 가능)
  • delete partition 파티션을 삭제합니다. 마찬가지로 볼륨 y(파티션 5), 볼륨 3 (볼륨 x, 파티션 4)를 삭제합니다.

    select volume z입력후 delete partition후 select partition y입력후 select partition 5 입력 delete partition입력후 select volume 3입력후 delete partition 입력 확인창

    select partition 3입력후 delete partition에서 delete partition override입력후 확인

  •  
  • ※ 파티션 3번의 확장파티션에 포커스를 주고 삭제하려는데 잘 안될수 있습니다. 이럴 때 위 그림의 입력 내용처럼 delete partition override 라고 override 옵션을 주면 됩니다.(히든 영역 삭제 가능)
  • ※ 브랜드 PC에서 별도 영역으로 구성한 파티션, 즉 [OEM 파티션]을 삭제할 때도 대상 파티션에 포커스를 주고, delete partition override 로 삭제합니다. 삼성 PC에서는 복원영역이 OEM 파티션 영역입니다.

    oem파티션 영역을 표시한 디스크관리 창

7] Diskpart 나가기

diskpart를 종료하는 방법은, exit를 입력합니다.

exit명령어로 나가기 실행

Synology RAID Volume 단일 Volume으로 변경하기

시놀로지는 볼륨 관리를 위해 md라고 불리는 software raid를 사용합니다.
raid를 관리하기 위해 사용하는 명령어가 mdadm 입니다.

보통은, /dev/md0가 OS 파티션, /dev/md1이 swap 파티션, 그리고 사용자가 사용하는 첫번째 볼륨 파티션이 /dev/md2로 생성되는데요..

“cat /proc/mdstat” 명령을 치시면 현재 사용하고 있는 md raid 정보가 출력됩니다.

?? ??2.png

이중 md 구성 별 blocks 수를 대략 비교 해보며 Disk Size 별로 어떤 Volume 인지 확인합니다.

mdadm –grow –raid-devices=1 –force /dev/[md2] <— 분리 하고자 하는 md 번호

상기 명령을 통해 원하는 Volume Raid를 분리 할 수 있습니다.

[Tomcat] 리눅스의 톰캣 로그에서 한글깨지는 문제 해결방법

리눅스의 톰캣 로그에서 한글이 깨져나오네요.

톰캣의 인코딩에 문제가 생겨서 그러겠죠?

[톰캣설치 폴더 > bin] 디렉토리로 가면 catalina.sh 파일이 있습니다.

그 파일을 편집기로 여시구요.

-Djava.io.tmpdir=”$CATALINA_TMPDIR” \
이 부분 찾아서 그 아래에 아래 소스를 모두 추가합니다.

-Djava.io.tmpdir=”$CATALINA_TMPDIR” \
-Dfile.encoding=”utf-8″\

수정한 파일을 저장하고, 톰캣을 재시작하면 아래처럼 로그에 한글이 잘 나옵니다.

Kubernetes Monitoring : HPA (Horizontal Pod Autoscaler)

Overview

쿠버네티스 클러스터에서 hpa를 적용해 시스템 부하상태에 따라 pod을 autoScaling시키는 실습을 진행하겠습니다.

참고 링크 : Kubernetes.io/Horizontal Pod Autoscaler

Prerequisites

먼저 쿠버네티스 클러스터를 생성해주세요.

참고링크 : 호롤리한하루/Install Kubernetes on CentOS/RHEL

본 실습에서 사용한 spec :
OS : CentOS v7.6
Arch : x86

Kubernetes : v1.16.2
Master : 4cpu, ram16G (1개)
Node : 4cpu, ram16G (2개)

Step

그림1

1. Metrics-Server 배포

먼저 top명령어를 입력해봅시다.

$ kubectl top node

Error from server (NotFound): the server could not find the requested resource (get services http:heapster:)

현재는 에러메세지가 뜹니다.
이유는 노드의 system metric들을 수집하는 서비스가 없기 때문입니다.

system metric을 수집하는 Metrics-Server를 배포해주도록 합시다.

$ git clone https://github.com/kubernetes-sigs/metrics-server.git
$ cd metrics-server

쿠버네티스에서 공식으로 서포트하고있는 add-on 컴포넌트인 metrics-server를 클론받고, 배포하기 이전에 yaml파일을 수정해주어야합니다.
클러스터 내에서 사용하는 인증서가 신뢰되지 않은 경우와 호스트 이름을 찾지 못하는 경우를 방지하기 위함입니다

$ vim deploy/kubernetes/metrics-server-deployment.yaml

image
위 그림과 같이 argument들을 수정해줍니다.

args:
  - --kubelet-insecure-tls
  - --kubelet-preferred-address-types=InternalIP
  - --cert-dir=/tmp
  - --secure-port=4443

그리고 나서 metrics-server를 배포하면 :

$ kubectl apply -f deploy/kubernetes/

clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
serviceaccount/metrics-server created
deployment.apps/metrics-server created
service/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created

중간에 metrics.k8s.io라는 API가 생성되어 Api server에 등록된 것을 확인할 수 있습니다.

이제 top명령어를 사용할 수 있게 됩니다.

$ kubectl top nodes

NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
kube-m     248m         6%     1656Mi          10%
kube-n01   112m         2%     760Mi           4%
kube-n02   112m         2%     724Mi           4%

각 노드의 cpu와 memory사용량을 확인할 수 있습니다.

2. 부하테스트를 위한 이미지 작성

이제 시스템의 부하테스트를 위한 이미지를 작성해보겠습니다.

$ mkdir php
cd php

스크립트 작성 :

$ vim index.php

<?php
  $x = 0.0001;
  for ($i = 0; $i <= 1000000; $i++) {
    $x += sqrt($x);
  }
  echo "OK!";
?>

스크립트를 포함하는 도커 이미지 작성 :

$ vim Dockerfile

FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php

도커 이미지 빌드 :

$ docker build --tag {docker id : totoli78}/php-apache .

$ docker images |grep php

totoli78/php-apache                    latest              39e1797ad29c        23 seconds ago      355MB

생성한 이미지를 본인의 docker hub에 push해줍니다.

$ docker login
...
Login Succeeded

$ docker push totoli78/php-apache

부하테스트를 위해 쿠버네티스 클러스터에 pod으로 배포해줍니다.

$ vim hpa-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: totoli78/php-apache
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache

yaml을 작성한 뒤에는 배포!

$ kubectl apply -f hpa-test.yaml

deployment.apps/php-apache created
service/php-apache created

3. HPA 배포

이제 오토스케일러를 생성해주면 됩니다.

$ vim autoscaler.yaml

위에서 만든 부하테스트용 pod인 php-apache의 평균 cpu사용량을 50%로 맞추기 위해 레플리카의 개수를 늘리고 줄입니다. (1개~10개)

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50
$ kubectl apply -f autoscaler.yaml
horizontalpodautoscaler.autoscaling/php-apache created

hpa커맨드를 통해 현재 hpa에 감지되는 시스템 부하정도와 관리하는 pod의 개수를 확인할 수 있습니다.

$ kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        1          18s

아직은 서버로 어떠한 요청도 하지 않았기 때문에, 현재 cpu소비량은 0%임을 알 수 있습니다. (TARGET은 deployment에 의해 제어되는 pod들의 평균을 뜻합니다.)

부하테스트

부하가 증가함에 따라 오토스케일러가 어떻게 반응하는지 살펴보겠습니다.

창을 하나 더 띄워서 php-apache 서비스에 무한루프 쿼리를 전송합니다.

$ kubectl run -it --rm load-generator --image=busybox /bin/sh

If you don't see a command prompt, try pressing enter.
/ #
/ # while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done
OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!...

1~2분 지난 뒤에 hpa커맨드로 부하상태를 살펴보면 TARGET의 수치가 높아진 것을 확인할 수 있습니다.

$ kubectl get hpa

NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   248%/50%   1         10        1          9m7s

그리고 deployment 컨트롤러를 확인해보면 pod의 replica수가 5개까지 늘어난 것을 확인할 수 있습니다.

$ kubectl get deploy php-apache

NAME         READY   UP-TO-DATE   AVAILABLE   AGE
php-apache   5/5     5            5           12m

busybox컨테이너를 띄운 터미널에서 Ctrl+C로 부하 발생을 중단시키고, 몇 분 후에 결과를 확인합니다.

$ kubectl get hpa

NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        5          11m

cpu의 사용량이 0%까지 떨어졌고, deployment의 pod replica수도 1개로 줄어든 것을 확인할 수 있습니다.

$ kubectl get deploy php-apache

NAME         READY   UP-TO-DATE   AVAILABLE   AGE
php-apache   1/1     1            1           19m

replica autoscaling은 몇 분 정도 소요됩니다. (체감상 3~5분)

Installing Helm on Ubuntu for Kubernetes

Ubuntu에 Helm을 설치하려면:

1. 다음 명령을 사용하여 최신 버전의 Helm을 다운로드합니다.

wget https://get.helm.sh/helm-v3.4.1-linux-amd64.tar.gz

다운로드가 완료되면 단말기에서 확인 메시지를 출력합니다.

터미널에서 Helm을 다운로드합니다.

2. 다음으로 Linux tar 명령 을 사용하여 Helm 파일의 압축을 풉니다 .

tar xvf helm-v3.4.1-linux-amd64.tar.gz

출력에는 압축이 풀린 4개의 파일이 표시됩니다.

3. linux-amd64/helm파일을 /usr/local/bin디렉터리로 이동합니다.

sudo mv linux-amd64/helm /usr/local/bin

명령이 올바르게 실행된 경우 출력이 없습니다.

투구 풀기.

4. 다음 명령을 사용하여 다운로드한 파일을 제거합니다.

rm helm-v3.4.1-linux-amd64.tar.gz

5. linux-amd64다음을 실행하여 공간을 정리할 디렉터리를 제거합니다.

rm -rf linux-amd64

프로세스가 성공적으로 완료되면 출력이 없습니다.

필요하지 않은 파일을 제거합니다.

6. 마지막으로 소프트웨어 버전을 확인하여 Helm을 성공적으로 설치했는지 확인합니다.

helm version

터미널은 소프트웨어의 버전 번호와 GitCommit, GitTreeState 및 GoVersion의 릴리스 번호를 인쇄합니다.

Helm 설치 완료를 확인합니다.

 

수동으로 최신 버젼의 chart 정보를 레파지토리에 갱신 할 수 있습니다.

$ helm repo add stable https://charts.helm.sh/stable
$ helm repo update  

[kubernetes] kubeadm 사용 고 가용성(HA) 클러스터 설정

kubernetes에서 HA를 구성하는 방법으로 stacked etcd, external etcd 두가지 방법이 있다. 그림 1의 stacked etcd는 control plane node에서 etcd가  작동하는 반면, 그림 2의 external etcd는 control plane node와 etcd가 다른 노드에서 작동한다. HA를 구성하기 위해서는 쿼럼이 과반수를 초과해야만 하기 때문에 최소 3대 이상(3,5,7,…)의 노드를 필요로 한다. 이번 시간에는 stacked etcd 를 구성하는 방법에 대해 알아보고자 한다.

 

[그림 1] HA 토폴로지 – stacked etcd
[그림 1] HA 토폴로지 – external etcd

 

구성환경

Ubuntu 18.04.1, Docker 19.03.8, Kubernet v1.17.4

사전 준비

Docker, Kubernet이 미리 설치 되어 있어야한다.

로드 발란서(Load Balancer)

– dns 로드 발란서 사용, apisvr 라운드로빈(round-robin) 활용, 참고로 도메인은 hoya.com

apisvr    IN      A       192.168.0.160
IN      A       192.168.0.161
IN      A       192.168.0.162

 

첫번째 Control plane node

1. Control plane 초기화

shell> sudo kubeadm init –control-plane-endpoint apisvr.hoya.com:6443 –upload-certs

** apisvr.hoya.com:6443 은 자기 환경에 맞게 설정한다.

–upload-certs : control plane 인스턴스에서 공유해야 하는 인증서를 업로드(자동배포), 수동으로 인증서를 복사할 경우는 이 옵션 생략

control plane 초기화(kubeadm init)를 진행하면 아래와 같은 내용이 출력될 것이다. 아래 내용을 복사해 놓도록 한다. 이 명령어를 이용하여 클러스터에 조인(join) 할수 있다. 파란색글씨(위쪽)는 control plane 노드에서 실행, 주황색 글씨(아래)는 worker node에서 실행

You can now join any number of control-plane node by running the following command on each as a root:
kubeadm join apisvr.hoya.com:6443 –token 9vr73a.a8uxyaju799qwdjv –discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 –control-plane –certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use kubeadm init phase upload-certs to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:
kubeadm join apisvr.hoya.com:6443 –token 9vr73a.a8uxyaju799qwdjv –discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866

참고: certificate-key를 지정하여 나중에 조인에서 사용할 수 있습니다.

shell> sudo kubeadm alpha certs certificate-key
f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07

참고: worker node에서 토큰을 사용하여 클러스터에 가입하는 데 필요한 전체 ‘kubeadm join’ 플래그를 출력

shell> sudo kubeadm token create –print-join-command

참고: 인증서를 다시 업로드하고 새 암호 해독 키를 생성하려면 이미 클러스터에 연결된 control plane 노드에서 다음 명령을 사용하십시오.

shell> sudo kubeadm init phase upload-certs –upload-certs
W0322 16:20:40.631234  101997 validation.go:28] Cannot validate kube-proxy config – no validator is available
W0322 16:20:40.631413  101997 validation.go:28] Cannot validate kubelet config – no validator is available
[upload-certs] Storing the certificates in Secret “kubeadm-certs” in the “kube-system” Namespace
[upload-certs] Using certificate key:
7f97aaa65bfec1f039c4dbdf3a2073de853c708bd4d9ff9d72b776b0f9874c9d

참고 :  클러스터를 control plane 조인(join)하는 데 필요한 전체 ‘kubeadm join’ 플래그를 출력

shell> sudo kubeadm token create –print-join-command –certificate-key \  7f97aaa65bfec1f039c4dbdf3a2073de853c708bd4d9ff9d72b776b0f9874c9d

2. CNI(Container Network Interface) 플러그인 설치

– 여기서는 weave CNI 플러그인 설치(그외 flannel, Calico, ….)

shell> kubectl apply -f “https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d ‘\n’)”

 

나머지 Control plane 노드

1. 첫번째 Control plane 노드에서 kubeadm init 결과(파란색 글씨)를 실행한다.

shell> kubeadm join apisvr.hoya.com:6443 –token 9vr73a.a8uxyaju799qwdjv –discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 –control-plane –certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07

2. 확인

– 노드 상태가 Ready인지 확인

shell> kubectl get nodes
NAME        STATUS   ROLES    AGE     VERSION
master1    Ready    master   41s     v1.17.4
master2    Ready    master   3m59s   v1.17.4
master3    Ready    master   92s     v1.17.4
shell>

– pods의 상태(Status)가 모두 Running 상태인지 확인

shell> kubectl get pods –all-namespaces
NAMESPACE     NAME                                READY   STATUS    RESTARTS   AGE
kube-system   coredns-6955765f44-7jk6m            1/1     Running   0          3m42s
kube-system   coredns-6955765f44-vgw2j            1/1     Running   0          3m42s
kube-system   etcd-master3                       1/1     Running   0          31s
kube-system   etcd-master1                       1/1     Running   0          3m44s
kube-system   etcd-master2                      1/1     Running   0          83s
kube-system   kube-apiserver-master3             1/1     Running   0          33s
kube-system   kube-apiserver-master1             1/1     Running   0          3m44s
kube-system   kube-apiserver-master2            1/1     Running   0          84s
kube-system   kube-controller-manager-master3    1/1     Running   0          33s
kube-system   kube-controller-manager-master1    1/1     Running   1          3m44s
kube-system   kube-controller-manager-master2   1/1     Running   0          84s
kube-system   kube-proxy-hd8vq                    1/1     Running   0          84s
kube-system   kube-proxy-v9s8h                    1/1     Running   0          3m42s
kube-system   kube-proxy-z76td                    1/1     Running   0          33s
kube-system   kube-scheduler-master3             1/1     Running   0          33s
kube-system   kube-scheduler-master1             1/1     Running   1          3m44s
kube-system   kube-scheduler-master2            1/1     Running   0          84s
kube-system   weave-net-6dkt6                     2/2     Running   3          84s
kube-system   weave-net-9zswx                     2/2     Running   0          3m3s
kube-system   weave-net-fvf9q                     2/2     Running   0          33s

woker node

1. 첫번째 Control plane 노드에서 kubeadm init 결과(주황색 글씨)를 실행한다.

kubeadm join apisvr.hoya.com:6443 –token 9vr73a.a8uxyaju799qwdjv –discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866

 

HA에서 control plane 노드 제거

 방법 1) 제거 할 노드에서 아래 명령어(kubeadm reset) 실행

shell> sudo kubeadm reset

** kubectl delete node로 control plane노드 를 제거하지 않도록 한다. 만약 kubectl delete node로 삭제하는 경우 이후 추가 되는 control plane 노드들은 HA에 추가 될수 없다. 그 이유는 kubeadm reset은 HA내 다른  control plane 노드의 etcd에서 etcd endpoint 정보를 지우지만 kubectl delete node는 HA 내의 다른 controle plane 노드에서 etcd endpoint 정보를 지우지 못하기 때문이다. 이로 인해 이후 HA에 추가되는 control plane 노드는 삭제된 노드의 etcd endpoint 접속이 되지 않기 때문에 etcd 유효성 검사 과정에서 오류가 발생하게 된다.

– control plane 노드를 kubectl delete node 로 삭제후 control plane 노드 추가시 오류 메시지

shell> kubeadm join ….. –control-plane –certyficate-key
… 생략 …
[check-etcd] Checking that the etcd cluster is healthy
error execution phase check-etcd: etcd cluster is not healthy: failed to dial endpoint https://192.168.0.159:2379 with maintenance client: context deadline exceeded
To see the stack trace of this error execute with –v=5 or higher

 방법 2) etcd member 삭제 진행 절차

  step 1. 유효한 control plane 노드에서 etcd member id 확인

shell> etcdctl –cacert=/etc/kubernetes/pki/etcd/ca.crt \ 
 –cert=/etc/kubernetes/pki/etcd/peer.crt \ 
 –key=/etc/kubernetes/pki/etcd/peer.key  member list 81ce68f24db8ced, started, master1, https://192.168.0.159:2380, https://192.168.0.159:2379, false
5364415ff53d0975, started, master3, https://192.168.0.158:2380, https://192.168.0.158:2379, false
b27f6573a770c244, started, master2, https://192.168.0.149:2380, https://192.168.0.149:2379, false
shell>

  step 2. 멤버 제거

shell> etcdctl -cacert=/etc/kubernetes/pki/etcd/ca.crt  \ 
–cert=/etc/kubernetes/pki/etcd/peer.crt \  
–key=/etc/kubernetes/pki/etcd/peer.key member remove 81ce68f24db8cedMember  81ce68f24db8ced removed from cluster  88707d65fd36eb2
shell>

 

TroubleShooting

참고 : 아래 환경에서 etcdctl 을 이용하여 접속하면 오류가 발생하여 etcd 버전을 업그레이드(v3.4.5)하여 진행, 아마 etcd, etcdctl 은 마이너 버전까지 일치해야만 정상 작동하는듯 하다.

– kubernetes etcd 버전 : 3.4.3-0

– etcdctl 버전

shell> etcdctl –version
etcdctl version: 3.2.10
API version: 2

 

증상 1) etcdctl version 3.2.10 으로 실행 오류 #1 – 404 오류 발생

shell> etcdctl -C https://192.168.0.149:2379 –ca-file=/tmp/pki/ca.crt  \
–cert-file=/tmp/pki/peer.crt  \
–key-file=/tmp/pki/peer.key member list
unexpected status code 404
shell>

증상 2) etcdctl version 3.2.10 으로 실행시 오류 #2( /etc/kubernetes/pki/etcd 디폴트 위치한 인증서 사용시)

shell> etcdctl -C https://192.168.0.149:2379 –ca-file=/etc/kubernetes/pki/etcd/ca.crt  \
–cert-file=/etc/kubernetes/pki/etcd/peer.crt  \
–key-file=/etc/kubernetes/pki/etcd/peer.key member list
open /etc/kubernetes/pki/etcd/peer.crt: permission denied
shell>

[Docker SWARM] Configuring a cluster environment using SWARM

manager : docker swarm 클러스터의 manager 노드

worker01, worker02, worker03 : docker swarm의 worker노드들 (3개)

registry : docker private registry 서비스

registry-web : docker private registry에 어떤 이미지가 올라가 있는지 web UI로 확인하는 서비스

dashboard : docker swarm 클러스터의 노드들을 web UI로 확인할 수 있는 서비스

 

대충 최종 모습(?)

 

준비사항

$ docker -v
Docker version 20.10.5, build 55c4c88

docker가 설치되어 있어야 한다.

$ docker-compose -v
docker-compose version 1.28.5, build c4eb3a1f

docker-compose도 설치되어 있어야 한다.

서비스 파일 작성

– docker-compose.yml

$ cat docker-compose.yml
version: "3"
services:
  registry-web:
    container_name: registry-web
    image: hyper/docker-registry-web
    ports:
      - 8080:8080
    volumes:
      - "./config.yml:/conf/config.yml:ro"

  registry:
    container_name: registry
    image: registry:2.6
    ports:
      - 5000:5000
    volumes:
      - "./registry-data:/var/lib/registry"

  manager:
    container_name: manager
    image: docker:18.05.0-ce-dind
    privileged: true
    tty: true
    ports:
      - 8000:80
      - 9000:9000
      - 8081:8081
      - 4567:4567
    depends_on:
      - registry
    expose:
      - 3375
    command: "--insecure-registry registry:5000"
    volumes:
      - "./stack:/stack"
      - "./dashboard:/dashboard"

  worker01:
    container_name: worker01
    image: docker:18.05.0-ce-dind
    privileged: true
    tty: true
    depends_on:
      - manager
      - registry
    expose:
      - 7946
      - 7946/udp
      - 4789/udp
    command: "--insecure-registry registry:5000"

  worker02:
    container_name: worker02
    image: docker:18.05.0-ce-dind
    privileged: true
    tty: true
    depends_on:
      - manager
      - registry
    expose:
      - 7946
      - 7946/udp
      - 4789/udp
    command: "--insecure-registry registry:5000"

  worker03:
    container_name: worker03
    image: docker:18.05.0-ce-dind
    privileged: true
    tty: true
    depends_on:
      - manager
      - registry
    expose:
      - 7946
      - 7946/udp
      - 4789/udp
    command: "--insecure-registry registry:5000"

manager와 worker 노드들은 dind(docker in docker) 이미지로 생성한다. dind는 간단히 말하자면 docker 컨테이너 안에서 docker cli를 사용하는 것이다.

registry와 registry를 web UI로 보여주는 서비스들을 추가한다. registry-web은 8080 포트로 접속할 것이다.

– config.yml

$ cat config.yml
registry:
  # 기존에 설치한 docker private registry
  url: http://registry:5000/v2
  # Docker registry name
  name: localhost:5000
  # docker 권한 부여
  readonly: false
  auth:
  eabled: false

registry-web에 사용될 yml 파일이다. private registry가 사용하는 5000번 포트로 url을 설정한다.

– dashbaord.yml

$ cat dashboard/dashboard.yml
version: "3"

services:
  dashboard:
    image: charypar/swarm-dashboard
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    ports:
      - 8081:8081
    environment:
      PORT: 8081
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager

docker-compose.yml 파일을 보면 manager 노드에 /dashboard 디렉토리를 마운트 해주었는데 즉, docker-compose.yml이 있는 곳에 dashboard라는 디렉토리를 만들고, 그 안에 dashboard.yml을 작성하였다.

dashboard 서비스는 manager 노드에만 생성되고, 브라우저에서 8081포트로 접속한다.

swarm-dashboard에 대한 github 주소는 아래와 같다. 개발자 분에게 감사합니다.

github.com/charypar/swarm-dashboard

– 디렉토리 상태

$ ls
config.yml  dashboard  docker-compose.yml

dashboard만 디렉토리이고, dashboard 디렉토리 안에 dashboard.yml 파일이 있다.

docker compose 실행

– docker-compose up -d

$ docker-compose up -d
Creating network "swarm_default" with the default driver
Creating registry     ... done
Creating registry-web ... done
Creating manager      ... done
Creating worker01     ... done
Creating worker03     ... done
Creating worker02     ... done

-d 옵션은 백그라운드로 시작하는 뜻이다.

– 디렉토리 재확인

$ ls
config.yml  dashboard  docker-compose.yml  registry-data  stack

docker-compose up을 실행하면 위처럼 registry-data와 stack 디렉토리가 생기는걸 확인할 수 있다. registry-data 디렉토리를 registry 서비스의 /var/lib/registry 디렉토리와 마운트 시켜놓으면, registry 서비스가 중지되어도 데이터가 그대로 유지된다.

– localhost:8080 접속

 

registry-web 접속

 

registry-web에 접속하면, 현재 registry 상태를 web UI를 통해 확인할 수 있다.

private registry에 이미지 업로드

docker swarm service에 사용할 이미지를 다운로드 받고, 직접 private registry에 이미지를 업로드 해본다.

– docker pull

$ docker image pull subicura/whoami:1

위의 이미지를 받는다. 브라우저로 접속하면 hostname을 출력해주는 docker 이미지이다.

– docker tag

$ docker image tag subicura/whoami:1 localhost:5000/example/whoami:latest

private registry의 포트가 5000이므로, 위와같이 docker image tag 명령어를 통해 이미지 이름과 tag 정보를 변경한다. 이미지의 첫 항목이 image pull 진행 시, 이미지가 올라가는 도메인 정보이다.

– docker image push

$ docker image push localhost:5000/example/whoami:latest
The push refers to repository [localhost:5000/example/whoami]
6304fb0017b0: Pushed
bcd68c905028: Pushed
5f4ed2a4afd7: Pushed
1fad3fef68ba: Pushed
42e63b663df9: Pushed
71d7318763a9: Pushed
7d7e183520a5: Pushed
7cbcbac42c44: Pushed
latest: digest: sha256:6239cd2462f9dd7a0317db107724a101deca600d30e39465515ba632e0982f4a size: 1989

이미지가 푸쉬되는걸 확인할 수 있다.

– registry web 확인

 

registry-web

 

이미지가 올라간것을 확인할 수 있다. 이제 docker swarm 노드에서 이미지를 다운받아 사용할 수 있다.

docker swarm 구성하기

– docker swarm init

$ docker exec -it manager docker swarm init
Swarm initialized: current node (5ywj85cw3tdz8ioe71v1xlyzn) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-1gxj86agzmecefcd6mwjproa96hw7e3gu0plsdhuw9110fuc1r-7q4434lsegri8la2n9qgggsrd 172.22.0.4:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

manager 컨테이너에서 docker swarm init 명령어를 입력한다. 위처럼 docker swarm join 부분 전체를 복사한다. worker 노드들에서 전부 입력하면 된다.

– docker swarm join

$ docker exec -it worker01 docker swarm join --token SWMTKN-1-1gxj86agzmecefcd6mwjproa96hw7e3gu0plsdhuw9110fuc1r-7q4434lsegri8la2n9qgggsrd 172.22.0.4:2377
This node joined a swarm as a worker.

$ docker exec -it worker02 docker swarm join --token SWMTKN-1-1gxj86agzmecefcd6mwjproa96hw7e3gu0plsdhuw9110fuc1r-7q4434lsegri8la2n9qgggsrd 172.22.0.4:2377
This node joined a swarm as a worker.

$ docker exec -it worker03 docker swarm join --token SWMTKN-1-1gxj86agzmecefcd6mwjproa96hw7e3gu0plsdhuw9110fuc1r-7q4434lsegri8la2n9qgggsrd 172.22.0.4:2377
This node joined a swarm as a worker.

Swarm dashboard 서비스 실행

– swarm dashboard stack deploy

$ docker exec -it manager docker stack deploy -c /dashboard/dashboard.yml dashboard
Creating network dashboard_default
Creating service dashboard_dashboard

컨테이너에 마운트해둔 /dashboard/dashboard.yml을 사용해 dashboard서비스를 실행한다.

– dashboard 접속

 

dashboard 접속

 

localhost:8081로 접속하면, 위처럼 현재 Swarm cluster의 상태를 확인할 수 있다. 현재 manager 노드에 dashboard 서비스 한개만 올라가 있는 상태이다.

Swarm 클러스터에 서비스 등록

private registry에 올려놨던 image를 manager 노드에서 pull 받아서 swarm 클러스에서 서비스로 등록해본다.

– docker pull image

$ docker exec -it manager docker pull registry:5000/example/whoami:latest
latest: Pulling from example/whoami
d1426d011624: Pull complete
1659ef4c811e: Pull complete
47bd5f3578fc: Pull complete
5e03057c6ddf: Pull complete
d58f420d5777: Pull complete
d65d30e11c7f: Pull complete
c9d3f35ab05f: Pull complete
fb24e6aeba3f: Pull complete
Digest: sha256:6239cd2462f9dd7a0317db107724a101deca600d30e39465515ba632e0982f4a
Status: Downloaded newer image for registry:5000/example/whoami:latest

– docker service create

$ docker exec -it manager docker service create --name whoami -p 4567:4567 registry:5000/example/whoami:latest
wkkg33d93qity2dustm8dkxvf
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

– docker service 확인

$ docker exec -it manager docker service ls
ID                  NAME                  MODE                REPLICAS            IMAGE                                 PORTS
isro3osqfsn5        dashboard_dashboard   replicated          1/1                 charypar/swarm-dashboard:latest       *:8081->8081/tcp
wkkg33d93qit        whoami                replicated          1/1                 registry:5000/example/whoami:latest   *:4567->4567/tcp

dashboard 서비스와 whoami 서비스를 확인할 수 있다.

 

 

dashboard에서도 whoami 서비스 하나가 추가된 것을 확인할 수 있다.

– service scale 조절

$ docker exec -it manager docker service scale whoami=6
whoami scaled to 6
overall progress: 6 out of 6 tasks
1/6: running   [==================================================>]
2/6: running   [==================================================>]
3/6: running   [==================================================>]
4/6: running   [==================================================>]
5/6: running   [==================================================>]
6/6: running   [==================================================>]
verify: Service converged

docker service scale 명령어로 서비스의 스케일링을 간단하게 진행할 수 있다. whoami 서비스가 원래 1개였는데, 6개로 늘렸다.

 

 

dashboard에서도 whoami 서비스가 6개로 증가한 것을 확인할 수 있다.

curl test

$ curl localhost:4567
444593584a03
$ curl localhost:4567
fb1e399ac4ed
$ curl localhost:4567
a8948b879833
$ curl localhost:4567
f565b65a22ab
$ curl localhost:4567
7160d9d9e250
$ curl localhost:4567
d7c6861c57e0
$ curl localhost:4567
444593584a03
$ curl localhost:4567
fb1e399ac4ed
$ curl localhost:4567
a8948b879833
$ curl localhost:4567
f565b65a22ab
$ curl localhost:4567
7160d9d9e250
$ curl localhost:4567
d7c6861c57e0

노드들의 hostname이 적절히 분배되어 출력되는걸 확인할 수 있다. docker swarm의 경우 ingress 네트워크가 트래픽 분산을 자동으로 해준다.

VM Workstation로 Xpenology DSM7 설치

사전준비물

ESXi용 7.0.1-42218 image
OSFMount
Starwind V2V Converter
IP Scanner

시리얼 생성

群晖系列产品序列号计算器

 

위에서 받은 sn과 mac을 이미지로 변경해주세요.

osfmount로 이미지 수정

반드시 Read-Only 체크해제

마운트 되면 아래경로에서 grub.cfg 파일 수정

 

위에서 받은 sn과 mac으로 수정

저장 후 언마운트 해주고 Starwind V2V Converter 실행
이미지 파일을 넣고 vmdk로 변경

준비 끝

VM Workstation으로 VM 생성하기

VMware 실행 후 Create a New Virtual Machine 선택

처음 ISO는 Noimage로 맨 아래꺼 선택하고 넘어가주세요.
OS는 Linux – Linux 4.x kernel 64-bit 입니다.

가상머신 이름입니다.

디스크는 어차피 한번날리고 다시만들꺼라 대충만들고 next

아래처럼 되면 일단 Finish해줍니다.

이제 생성한 VM을 바로 실행시키지는 마시고 VM을 선택 후 설정으로 갑니다.

그리고 기존 Disk와 불필요한 CD 드라이브도 모두 Remove해주고 메모리 CPU설정을 하신뒤에 아래처럼 새로 Hard Disk를 추가해줍니다.

Disk Type은 SATA 디스크로

부트로더를 넣어줘야하기때문에 기존 디스크를 넣어준다고합니다.

만든 부트로더 디스크를 넣어주세요.

Keep Existing Format을 선택해줍니다.

이제 데이터저장을 위한 HDD를 만들어줍니다.

동일하게 SATA 타입으로 만들어주세요

이제 네트워크 설정입니다. 아래처럼 NAT -> Bridged로 변경해주고
Configure Adapters에서 사용하고계신 LAN 어댑터를 선택 후 OK눌러주세요.

그리고 Advanced…를 눌러서 아까 생성한 MAC주소를 넣어줍니다.

그리고 OK를 누르고 저장해주신뒤 VM의 설정파일이 있는곳으로 이동해서 파일을 아래처럼 수정해주세요.

문서->Virtual Machines -> VM이름 -> VM이름.vmx 파일을 메모장으로 열어주시고 e1000을 검색해서 e1000e로 변경 아래 firmware = “efi” 항목이 있다면 삭제해주세요.

이제 저장을 하고 VM을 실행시켜줍니다.

아래 SATA 부팅

위 화면이 뜨면 IP Scanner로 사용하고 계신 네트워크 대역을 스캔해주세요.

변경한 MAC주소의 이름으로 기기가 검색됩니다.

ip로 접속하면 아래처럼 잘 뜨는것을 확인할 수 있습니다.

설치도 공홈에서 받은 pat파일을 통해 바로 됩니다.