이야기박스

Kubernetes 2. Docker 본문

Computer & Data/Orchestration

Kubernetes 2. Docker

박스님 2019. 5. 6. 17:35
반응형

# Docker 설치 & Hello World 실행

busybox라고 repository에 예제 라이브러리로 사용하라고 주어진 게 있는 것 같습니다.

docker run *** 을 사용하면 바로 해당 이미지를 pulling 테스트를 진행할 수 있습니다.

root@jw-ubuntu01:~# docker run busybox echo "Hello world"
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
fc1a6b909f82: Pull complete 
Digest: sha256:954e1f01e80ce09d0887ff6ea10b13a812cb01932a0781d6b0cc23f743a874fd
Status: Downloaded newer image for busybox:latest
Hello world

로그를 살펴보니, locally를 먼저 검색해보고 repository에서 버전 명시가 없기 때문에 최신 버전을 가져오고 있네요.

그리고 pulling 한 정보를 표출합니다. 실제 동작도 그러합니다.

## docker run

  1. 최신 이미지가 로컬 시스템에 제공되고 있는지 확인
  2. 최신 이미지가 아니라면 도커 허브 레지스트리에서 최신 이미지를 가져옴 (http://docker.io)
  3. 이미지가 다운로드 되면 도커는 그 안에 컨테이너 생성하고 명령을 실행
  4. echo 명령은 텍스트 stdout에 출력한 다음 프로세스 종료 --> 컨테이너 중지

출처 : https://act-coe.github.io/kubernetes-in-action-01/

최신 버전 이미지를 가져오는 경우

docker run <image>

특정 버전 이미지를 가져오는 경우

docker run <image>:<tag>

 

# 이미지 만들기

이후 테스트는 GCP의 쿠버네티스 엔진을 통하여 진행하였습니다.

책에서는 간단한 Node.js 웹 앱 예제가 제공되고 있습니다. 쿠버네티스 엔진 클러스터를 생성하고 'dockerTest'라는 디렉토리를 생성하여 테스트를 진행하였습니다.

## app.js

var http = require('http');

var handleRequest = function(request, response) {
  console.log('Received request for URL: ' + request.url);
  response.writeHead(200);
  response.end('Hello World!');
};
var www = http.createServer(handleRequest);
www.listen(8080);

## Dockerfile

FROM node:7
ADD app.js /app.js
ENTRYPOINT ["node", "app.js"]

위 두개의 파일을 같은 경로에 두고 아래 명령어 실행하면 됩니다.

docker build -t kubia .

그러면 빌드가 진행되는데 여러 이미지로 나누어서 Pull이 이루어지는 것을 확인할 수 있습니다.

Sending build context to Docker daemon 3.072 kB
Step 1/3 : FROM node:7
7: Pulling from library/node
ad74af05f5a2: Pull complete 
2b032b8bbe8b: Pull complete 
a9a5b35f6ead: Pull complete 
3245b5a1c52c: Pull complete 
afa075743392: Pull complete 
9fb9f21641cd: Pull complete 
3f40ad2666bc: Pull complete 
49c0ed396b49: Pull complete 
Digest: sha256:af5c2c6ac8bc3fa372ac031ef60c45a285eeba7bce9ee9ed66dad3a01e29ab8d
Status: Downloaded newer image for node:7
 ---> d9aed20b68a4
Step 2/3 : ADD app.js /app.js
 ---> a6cf819de029
Removing intermediate container 5e0e8706f340
Step 3/3 : ENTRYPOINT node app.js
 ---> Running in 8802a3d42cdc
 ---> 94b29684340f
Removing intermediate container 8802a3d42cdc
Successfully built 94b29684340f

빌드 프로세스의 다이어그램은 아래와 같습니다.

출처 : https://act-coe.github.io/kubernetes-in-action-01/

빌드는 Docker client가 아닌 Docker daemon에서 진행되고 데몬은 VM 내부에서 실행되기 때문에 호스트 OS가 굳이 리눅스가 아니어도 크게 문제 되지 않습니다. 단, 빌드 디렉토리에 모든 파일을 데몬에 올리기 때문에, 데몬이 로컬로 실행되지 않으면 업로드에 오랜 시간이 걸릴 수 있습니다.

## 이미지 레이어

위 빌드 로그에서 보면 알 수 있듯이, 이미지는 크기가 큰 하나의 바이너리가 아닌 여러 개의 레이어로 구성되어 있습니다.

출처 : https://act-coe.github.io/kubernetes-in-action-01/

장점 

  • 여러 레이어 중, 이전에 다운 받지 않았던 레이어만 다운 받음

## 이미지 확인

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
kubia               latest              a2c66a0a819d        33 seconds ago      660MB
node                7                   d9aed20b68a4        20 months ago       660MB

## 이미지 실행

아래 명령어를 통하여 kubia 이미지를 백그라운드에서 실행하도록 하겠습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker run --name kubia-container -p 8080:8080 -d kubia
d4d437794aeeee1eaddfa22d1d087878d7a89a7b90f33d7cc6fb7dc850784852
  • '--name kubia-container' : kubia-container라는 이름의 새 컨테이너를 실행
  • '-d' : 백그라운드 실행
  • '-p 8080:8080' : 로컬 컴퓨터의 포트 8080과 컨테이너 내부 포트 8080을 매핑시킨다는 의미 

실행되고 있는 프로세스는 아래 명령어로 확인 가능합니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
d4d437794aee        kubia               "node app.js"       14 minutes ago      Up 14 minutes       0.0.0.0:8080->8080/tcp   kubia-container

상세 정보 확인이 필요하시다면 아래 명령어를 사용하시면 됩니다.

docker inspect kubia-container > inspect.log

로그

...더보기

[
    {
        "Id": "d4d437794aeeee1eaddfa22d1d087878d7a89a7b90f33d7cc6fb7dc850784852",
        "Created": "2019-05-06T06:10:07.337846829Z",
        "Path": "node",
        "Args": [
            "app.js"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 465,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2019-05-06T06:10:07.861314632Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:a2c66a0a819d4fa8cb44f30a4d881591f737cd8a6923e65fbfee4fb029f4f159",
        "ResolvConfPath": "/var/lib/docker/containers/d4d437794aeeee1eaddfa22d1d087878d7a89a7b90f33d7cc6fb7dc850784852/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/d4d437794aeeee1eaddfa22d1d087878d7a89a7b90f33d7cc6fb7dc850784852/hostname",
        "HostsPath": "/var/lib/docker/containers/d4d437794aeeee1eaddfa22d1d087878d7a89a7b90f33d7cc6fb7dc850784852/hosts",
        "LogPath": "/var/lib/docker/containers/d4d437794aeeee1eaddfa22d1d087878d7a89a7b90f33d7cc6fb7dc850784852/d4d437794aeeee1eaddfa22d1d087878d7a89a7b90f33d7cc6fb7dc850784852-json.log",
        "Name": "/kubia-container",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "docker-default",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {
                "8080/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "8080"
                    }
                ]
            },
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "shareable",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DiskQuota": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": 0,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/04da1e6d9c4facaede680d5d57942174b16ae3b5891b6a1a7e87dd2454ac5577-init/diff:/var/lib/docker/overlay2/bd5dd8ac0a50245b5995ec3ec828d856373de4f07a2f3236b4b1906832b8955e/diff:/var/lib/docker/overlay2/dbbed4331df60c6dcd88702254b19aa87a6f5fbd86f07eb9ae7475acfdb8d092/diff:/var/lib/docker/overlay2/47c0a1bfba48033a189f230403dec17d03b40a0f78e26ac1691beb7a4e93c0cf/diff:/var/lib/docker/overlay2/707888fce8a8eb3b5d116f99e163a69641fe48d8fad27a2f44d7bfad3db36f79/diff:/var/lib/docker/overlay2/91e1b6cbaad879970ddd65fb454c997f5c3670926e7c7174691aa91259ec53e7/diff:/var/lib/docker/overlay2/494e0a0fdd986cb35be26fd1731abc2ec32ada9ccbed9d4b3ede577e0c55ab8d/diff:/var/lib/docker/overlay2/2d15c3150e2afca518c80e68f225331f8bca8b11059413c729f46f045ffb2338/diff:/var/lib/docker/overlay2/49cf4a9bb7df0e266d62f8cbfba0f7a0a308431918812da158532c6e07163aea/diff:/var/lib/docker/overlay2/67f9f6d544c974b2a1b45b77519c47bd1e885881fdddf1ca88202aa0a72b50a4/diff",
                "MergedDir": "/var/lib/docker/overlay2/04da1e6d9c4facaede680d5d57942174b16ae3b5891b6a1a7e87dd2454ac5577/merged",
                "UpperDir": "/var/lib/docker/overlay2/04da1e6d9c4facaede680d5d57942174b16ae3b5891b6a1a7e87dd2454ac5577/diff",
                "WorkDir": "/var/lib/docker/overlay2/04da1e6d9c4facaede680d5d57942174b16ae3b5891b6a1a7e87dd2454ac5577/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "d4d437794aee",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "8080/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NPM_CONFIG_LOGLEVEL=info",
                "NODE_VERSION=7.10.1",
                "YARN_VERSION=0.24.4"
            ],
            "Cmd": null,
            "ArgsEscaped": true,
            "Image": "kubia",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "node",
                "app.js"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "a348894d8d96390f61ef1138bcb088004740167803f2a495e540a5f697a8c8f5",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "8080/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "8080"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/a348894d8d96",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "2e8743da9b5b89732557036259185d4262973a448fc6ec9d9a9f76aad3affd63",
            "Gateway": "172.18.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.18.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:12:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "0e663bedae3e4ecdc4f86e020ea9d916c3efa3d330bbdaa9a2072b9f4f6afbc4",
                    "EndpointID": "2e8743da9b5b89732557036259185d4262973a448fc6ec9d9a9f76aad3affd63",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:12:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

앱의 액세스는 8080 포트로 접근하시면 됩니다!

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ curl localhost:8080
Hello World!

## 컨테이너 내부 확인

shell의 바이너리가 이미지에 포함되어 있다면, 쉘을 실행시킬 수 있습니다. 예를 들어 위에서 테스트한 Node.js의 경우 bash shell이 포함되어 있기 때문에 다음 명령어로 내부 쉘을 실행 가능합니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker exec -it kubia-container bash
  • '-i' : STDIN을 오픈 상태로 유지, 쉘에 명령어를 입력할 때 필요
  • '-t' : pseudo terminal(TTY) 할당

shell을 사용하고 싶다면 위 두 개의 옵션은 필수로 추가되어야 합니다!

위에서 실행한 쉘을 사용하여 내부 컨테이너의 프로세스를 확인해 보겠습니다.

root@d4d437794aee:/# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  1.5 614436 26336 ?        Ssl  06:10   0:00 node app.js
root          15  1.0  0.1  20248  2992 pts/0    Ss   06:35   0:00 bash
root          20  0.0  0.1  17504  2052 pts/0    R+   06:35   0:00 ps aux

3개의 프로세스만 확인이 가능하고 호스트 OS의 다른 프로세스는 확인되지 않는 것을 볼 수 있습니다.

반면에 호스트 OS에서는 내부 컨테이너의 프로세스를 확인할 수 있습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ ps aux | grep app.js
root         465  0.0  1.5 614436 26336 ?        Ssl  15:10   0:00 node app.js
oringnam     740  0.0  0.0  12780   924 pts/1    S+   15:40   0:00 grep --color=auto app.js

그런데! 자세히 보시면 서로 다른 두 namepsace에서 pid가 다르다는 것을 확인하실 수 있습니다. 

프로세스가 격리되어 동작하는 것처럼 각 컨테이너는 격리된 파일 시스템을 가지고 있습니다.

root@d4d437794aee:/# ls
app.js  boot  etc   lib    media  opt   root  sbin  sys  usr
bin     dev   home  lib64  mnt    proc  run   srv   tmp  var

## 컨테이너 중지 & 제거

중지 명령어

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker stop kubia-container
kubia-container

제거 명령어

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker rm kubia-container
kubia-container

위 두 명령어를 실행하고 'docker ps'을 실행해보면 리스트가 비어있는 것을 확인할 수 있습니다.

# 이미지 푸시

개인용 이미지 레지스트리 설정은 진행하지 않고 오픈 레지스트리인 도커 허브에 푸시를 진행하도록 하겠습니다.

푸시하기 위하여 해당 페이지에서 계정을 만드셔야 합니다! 아래 예제는 제 계정이 ID로 들어가게 되니, 해당 부분만 바꾸셔서 진행하시면 될 것 같습니다 :) (oringnam --> 독자님의 ID)

## 태그 지정

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker tag kubia oringnam/kubia

위 명령어를 사용하여도 태그의 이름이 변경되는 것이 아닙니다. 그저 새로 생길 뿐이죠..

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker images | head
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
kubia               latest              a2c66a0a819d        About an hour ago   660MB
oringnam/kubia      latest              a2c66a0a819d        About an hour ago   660MB
node                7                   d9aed20b68a4        20 months ago       660MB

보시다시피 'kubia'와 'oringnam/kubia'가 가리키는 'IMAGE ID'가 동일합니다.

## 이미지 푸시

푸시하시기 전에 로그인을 먼저 진행하셔야 합니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker login

로그인을 진행하셨다면 oringnam/kubia 이미지를 도커 허브에 푸시할 수 있습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker push oringnam/kubia
The push refers to repository [docker.io/oringnam/kubia]
3230dfc501b1: Pushed
ab90d83fa34a: Mounted from library/node
8ee318e54723: Mounted from library/node
e6695624484e: Pushed
da59b99bbd3b: Mounted from library/node
5616a6292c16: Mounted from library/node
f3ed6cb59ab0: Mounted from library/node
654f45ecb7e3: Mounted from library/node
2c40c66f7667: Mounted from library/node
latest: digest: sha256:a25e318137c450542781dc52c72b03fb019d617f92fdeb68f5edd2e17f300e7f size: 2213

푸시가 완료되었다면 이제 도커를 실행하는 컴퓨터에서 해당 이미지를 실행할 수 있습니다. 명령어는 아래와 같습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ docker run -p 8080:8080 -d oringnam/kubia
75c292f51c8011c65baa38ae96263b4aac11d0e6cc15ae59893ab524410488c8

# 쿠버네티스 클러스터 설정

도커를 통하여 이미지를 생성하고 배포하는 방법을 알게 되었으니 이제 쿠버네티스로 배포할 차례입니다. 쿠버네티스를 본격적으로 사용하기에 앞서 클러스터 설정을 먼저 알아봐야 하지만... 

2019/04/30 - [Computer Science/Docker] - Kubernetes 설치

 

Kubernetes 설치

지난번 Kubernetes Introduction에 이어서 쿠버네티스 설치를 진행해보았습니다. GCP의 Free tier로 Kubernetes Engine을 사용할 수도 있지만, 직접설치도 한번 해보면 구조를 잘 이해할 수 있을 것 같아서 설치..

box0830.tistory.com

여기서 잠깐 다루었듯이 굉장히 복잡합니다.

그리고 현재 GCP 쿠버네티스 엔진을 사용하고 있으니.. 그냥 이 부분은 넘어가도록 하겠습니다.

## 클러스터 확인

쿠버네티스 클러스터가 동작하고 있는지 확인하는 명령어입니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl cluster-info
Kubernetes master is running at http://localhost:8080

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
error: the server doesn't have a resource type "services"

## 세 개의 노드를 가진 쿠버네티스 클러스터 생성

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ gcloud container clusters create kubia --num-nodes 3 --machine-type f1-micro --region us-central1-a
WARNING: In June 2019, node auto-upgrade will be enabled by default for newly created clusters and node pools. To disable it, use the `--no-enable-autoupgrade` flag.
WARNING: Starting in 1.12, new clusters will have basic authentication disabled by default. Basic authentication can be enabled (or disabled) manually using the `--[no-]enable-basic-auth` flag.
WARNING: Starting in 1.12, new clusters will not have a client certificate issued. You can manually enable (or disable) the issuance of the client certificate using the `--[no-]issue-client-certificate` flag.
WARNING: Currently VPC-native is not the default mode during cluster creation. In the future, this will become the default mode and can be disabled using `--no-enable-ip-alias` flag. Use `--[no-]enable-ip-alias` flag to suppress this warning.
WARNING: Starting in 1.12, default node pools in new clusters will have their legacy Compute Engine instance metadata endpoints disabled by default. To create a cluster with legacy instance metadata endpoints disabled in the default node pool, run `clusters create` with the flag `--metadata disable-legacy-endpoints=true`.
WARNING: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s).
This will enable the autorepair feature for nodes. Please see https://cloud.google.com/kubernetes-engine/docs/node-auto-repair for more information on node autorepairs.
Creating cluster kubia in us-central1-a... Cluster is being health-checked (master is healthy)...done.
Created [https://container.googleapis.com/v1/projects/nodal-condition-238906/zones/us-central1-a/clusters/kubia].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-a/kubia?project=nodal-condition-238906
kubeconfig entry generated for kubia.
NAME   LOCATION       MASTER_VERSION  MASTER_IP      MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
kubia  us-central1-a  1.11.8-gke.6    35.232.196.87  f1-micro      1.11.8-gke.6  3          RUNNING

클러스터 생성을 진행하는 명령어입니다. us-central1-a region에 클러스터 생성을 하였습니다. 작업에는 몇 분 소요됩니다!

보통 kubectl get ** 명령어를 통하여 다양한 쿠버네티스 객체를 나열할 수 있습니다. 노드 정보를 확인하려고 한다면 아래처럼 사용하시면 됩니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl get nodes
NAME                                   STATUS     ROLES     AGE       VERSION
gke-kubia-default-pool-c619130b-9crx   NotReady   <none>    2m        v1.11.8-gke.6
gke-kubia-default-pool-c619130b-9d9f   Ready      <none>    2m        v1.11.8-gke.6
gke-kubia-default-pool-c619130b-j767   Ready      <none>    2m        v1.11.8-gke.6

객체의 세부 정보는 'kubectl descrive' 명령을 통하면 됩니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl describe node gke-kubia-default-pool-c619130b-j767

세부 로그는 너무 길기 때문에 생략하겠습니다. 보통 노드 상태, cpu, memory, system info 등을 포함하고 있습니다.

만약 'kubectl describe node' 명령을 수행하면 특정노드가 아닌 모든 노드의 정보가 표출됩니다.

## 별칭 생성하기

kubectl을 매번 치기 귀찮은 경우에 사용하시면 됩니다.

alias k=kubectl

## 자동완성 기능

리눅스에서 tab을 통한 자동완성을 지원하듯이 쿠버네티스도 마찬가지입니다. 애용하고 있습니다 ㅎㅎ 

# 쿠버네티스에서 앱 실행하기

보통 쿠버네티스에서 앱을 배포하기 위하여 매니페스트(JSON, YAML)이 필요하지만 이번 예제에서는 간단한 명령을 통하여 실행을 해보도록 하겠습니다.

## Node.js 앱 배포

kubectl 명령을 통하여 아까전에 docker hub에 등록해둔 이미지를 배포해보도록 하겠습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl run kubia --image=oringnam/kubia --port=8080 --generator=run/v1
replicationcontroller/kubia created

'--generator' 명령어는 replicationcontroller를 생성하도록 하는 명령어라고 합니다. default는 deployment를 생성한다고 하네요.

## 포드

실행한 컨테이너를 확인하고 싶네요. 하지만 이전 Introduction 포스트에서 다루었듯이 쿠버네티스는 Pod를 단위로 컨테이너를 관리합니다. 그렇기 때문에 Pod를 확인하는 명령어를 실행하여야 합니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
kubia-xhd5x   1/1       Running   0          4m

실행된지 4분된 pod가 확인되네요!

내부 동작을 확인해보면 다음과 같습니다. 

출처 : https://act-coe.github.io/kubernetes-in-action-02/

kubectl 명령을 통하여 쿠버네티스 API 서버에 REST HTTP 요청을 하고, 레플리케이션컨트롤러 객체를 생성합니다. 이 레플리케이션컨트롤러가 포드를 생성하고 워커 노드에 스케줄을 겁니다. kubelet에서는 레지스트리에서 이미지를 받아와 컨테이너를 생성/실행합니다.

## 웹 앱 접근

포드는 내부 클러스터에 있으며 외부에서 접근이 불가능합니다. 그렇다면 어떻게 외부에서 액세스하려면 어떠한 방법을 써야할까요?

LoadBalancer처럼 특별한 서비스를 만들면 됩니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl expose rc kubia --type=LoadBalancer --name kubia-http
service/kubia-http exposed

로그를 보시면 kubia-http expsed라고 나타납니다. 서비스 또한 하나의 객체이므로 kubectl get 명령어를 통하여 확인이 가능합니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)          AGE
kubernetes   ClusterIP      10.55.240.1     <none>         443/TCP          24m
kubia-http   LoadBalancer   10.55.246.236   34.66.22.166   8080:31859/TCP   1m

EXTERNAL-IP 같은 경우 <pending> 이라고 표출되기도 하는데, 로드 밸런서를 생성하는데 시간이 걸리기 때문입니다. 잠시후에 다시 명령을 실행해보시면 위처럼 ip가 할당된 것을 확인하실 수 있습니다.

이제 LoadBalance를 통하여 접근을 확인해보시면 됩니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ curl 34.66.22.166:8080
Hello World!

# 쿠버네티스 시스템 논리적 부분

## 포드

주요 구성요소입니다. 다수의 컨테이너를 포함할 수 있습니다. 포드는 고유한 개인 IP와 호스트 네임을 가집니다.

## 레플리케이션 컨트롤러

포드 인스턴스를 정확히 하나만 실행하도록 되어 있습니다. 일반적으로 포드를 복제하여 계속 실행합니다. 위 예제에서는 replica 지정이 없기 때문에 단일 복제본을 계속 생성하게 될 것입니다. 어떠한 이유로 포드가 사라지게 되면 누락된 포드를 대체할 새로운 포드를 생성합니다.

## kubia-http

포드는 일시적인 객체입니다. 언제든지 사라질 수 있기 때문에 포드의 IP를 통하여 접근하는건 너무 위험합니다. 그렇기 때문에 kubia-http 서비스를 통하여 생성되는 정적 IP에 접근하도록 하여야 합니다.

# 수평 스케일링 

위 예제에서 실행중인 인스턴스의 수를 3개로 늘려보도록 하겠습니다.

포드는 위에서 설명했듯이 레플리케이션 컨트롤러가 관리합니다. 이를 확인해보도록 하겠습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl get replicationcontrollers
NAME      DESIRED   CURRENT   READY     AGE
kubia     1         1         1         28m
  • DESIRED : 유지해야 할 포드 복제본 수
  • CURRENT : 현재 포드 수

## 레플리카 수 증가

아래 명령어로 간단하게 늘릴 수 있습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl scale rc kubia --replicas=3
replicationcontroller/kubia scaled

보시면 쿠버네티스에게 직접 replica를 늘리라고 지시하지 않습니다. 그저 설정값을 늘리고 쿠버네티스가 자체적으로 요청된 상태를 달성하기 위하여 조치를 취하도록 합니다. 이것이 쿠버네티스의 기본 원칙입니다.

수행해야 할 작업을 알려주는 대신 원하는 상태를 선언적으로 변경, 쿠버네티스가 자체적으로 검토하고 원하는 상태로 조정하도록 한다.
oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
kubia     3         3         2         32m

보시면 실제로 포드 수가 3개로 증가하였습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl get pods
NAME          READY     STATUS              RESTARTS   AGE
kubia-j4kc8   0/1       ContainerCreating   0          3m
kubia-mhk6q   1/1       Running             0          3m
kubia-xhd5x   1/1       Running             0          33m

2개는 실행중이고 1개는 실행 준비중인 것 같네요. 잠시 후, 다시 확인하면 실행중인 내용을 확인할 수 있을 것 같습니다.

스케줄 되는 워커 노드에 관계없이 컨테이너 내부에서 실행되는 모든 앱의 OS 환경은 동일합니다. 각 포드는 자체 IP를 가지고 있기 때문에 포드들이 같은 노드에서 실행되는지, 다른 노드에서 실행되는지는 중요하지 않습니다.

포드의 자세한 정보를 원하신다면 아래 옵션을 추가하시면 됩니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl get pods -o wide
NAME          READY     STATUS              RESTARTS   AGE       IP          NODE                                   NOMINATED NODE
kubia-j4kc8   0/1       ContainerCreating   0          8m        10.52.1.6   gke-kubia-default-pool-c619130b-j767   <none>
kubia-mhk6q   1/1       Running             0          8m        10.52.2.5   gke-kubia-default-pool-c619130b-9d9f   <none>
kubia-xhd5x   1/1       Running             0          38m       10.52.2.4   gke-kubia-default-pool-c619130b-9d9f   <none>

특정 포드의 정보를 원하신다면 describe 명령어를 사용하시면 됩니다. (이 명령어는 로그가 길기 때문에 생략하도록 하겠습니다.)

# 대시보드

GKE에서는 cluster-info 명령을 통하여 대시보드 URL을 확인할 수 있습니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ kubectl cluster-info | grep dashboard
kubernetes-dashboard is running at https://35.232.196.87/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy

접속이 안되네요.. 원인은 찾아서 고쳐보도록 하겠습니다.

계정 정보 확인 법입니다.

oringnam@cloudshell:~/dockerTest (nodal-condition-238906)$ gcloud container clusters describe kubia --region us-central1-a | grep -E "(username|password):"

...

https://cloud.google.com/kubernetes-engine/docs/concepts/dashboards

 

GKE 대시보드  |  Kubernetes Engine  |  Google Cloud

이 페이지에서는 Google Cloud Platform 콘솔에서 제공되는 Google Kubernetes Engine 대시보드를 간략히 소개합니다. 주의: 2017년 9월을 기준으로 Kubernetes 대시보드는 GKE에서 더 이상 사용되지 않습니다. 이 페이지에 설명된 대시보드를 사용해서 클러스터 성능, 작업 부하, 리소스를 모니터링할 수 있습니다. 개요 GCP 콘솔은 프로젝트의 GKE 클러스터 및 그 리소스에 관한 유용한 대시보드를 제공합니다. 이러한

cloud.google.com

더 이상 지원하지 않는 것 같네요. 그냥 GKE 홈에서 관리해야 하나 봅니다.

Docker & k8s 첫 걸음 마무리하도록 하겠습니다.

반응형

'Computer & Data > Orchestration' 카테고리의 다른 글

Kubernetes. Anthos  (0) 2019.07.31
Kubernetes 3. Pod  (0) 2019.05.18
Kubernetes 설치  (1) 2019.04.30
YARN ; Yet Another Resource Negotiator  (0) 2019.04.26
Kubernetes vs Mesos with Marathon  (0) 2019.04.25