NodePort 타입의 서비스_서비스를 이용해 pod외부에 노출

모든 노드의 특정 포트를 개방해서 서비스에 접근하는 방식

  1. 매니패스트 파일
vagrant@ubuntu:~/kub01$ vi hostname-svc-nodeport.yml

'YAML
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-nodeport
spec:
  ports:
    - name: web-port
      port: 8080
      targetPort: 80
  selector:
    app: webserver
  type: NodePort
'
  1. 서비스 생성 및 확인
vagrant@ubuntu:~/kub01$ kubectl apply -f hostname-svc-nodeport.yml
service/hostname-svc-nodeport created

vagrant@ubuntu:~/kub01$ kubectl get services
NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
hostname-svc-nodeport   NodePort    10.111.29.91   <none>        8080:30309/TCP   7s
kubernetes              ClusterIP   10.96.0.1      <none>        443/TCP          3d1h

vagrant@ubuntu:~/kub01$ kubectl get nodes -o wide
NAME       STATUS   ROLES    AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION       CONTAINER-RUNTIME
minikube   Ready    master   3d1h   v1.19.0   172.17.0.2    <none>        Ubuntu 20.04 LTS   4.15.0-117-generic   docker://19.3.8
  1. 노드(172.17.0.2)에서 서비스 포트(30309)로 접근
vagrant@ubuntu:~/kub01$ curl http://172.17.0.2:30309 -s | grep Hello
        <p>Hello,  hostname-deployment-7dfd748479-rtgzv</p>     </blockquote>
vagrant@ubuntu:~/kub01$ curl http://172.17.0.2:30309 -s | grep Hello
        <p>Hello,  hostname-deployment-7dfd748479-pp8x4</p>     </blockquote>
  1. ClusterIP 타입의 서비스와 같이 내부 IP와 서비스 이름으로 접근도 가능
vagrant@ubuntu:~/kub01$ kubectl run -it --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
If you don't see a command prompt, try pressing enter.
root@debug:/#
root@debug:/# curl http://10.111.29.91:8080 -s | grep Hello
        <p>Hello,  hostname-deployment-7dfd748479-pp8x4</p>     </blockquote>
root@debug:/# curl http://10.111.29.91:8080 -s | grep Hello
        <p>Hello,  hostname-deployment-7dfd748479-7zdv7</p>     </blockquote>
root@debug:/# exit
exit
pod "debug" deleted

 

반응형

서비스(Service)

쿠버네티스 클러스터 안에서 pod의 집합에 대한 경로나 서비스 디스커버리를 제공하는 리소스

타입

서비스 타입에 따라 파드에 접근하는 방법이 다르다.

  • ClusterIP 타입 : 쿠버네티스 내부에서만 pod에 접근할 때 사용. 외부로 파드를 노출하지 않기 때문에 쿠버네티스 클러스터 내부에서만 사용되는 파드에 적합
  • NodePort 타입 : 파드에 접근할 수 있는 포트를 클러스터의 모드 노드에 동일하게 개방
    외부에서 파드에 접근할 수 있는 서비스 타입, 접근할 수 있는 포트는 랜덤으로 정해지지만, 특정 포트로 접근하도록 설정할 수 있음
  • LoadBalancer 타입 : 클라우드 플랫폼에서 제공하는 로드 밸러서를 동적으로 프로비저닝해서 파드에 연결, 외부에서 파드에 접근할 수 있는 서비스 타입, 일반적으로 AWS, GCP, … 등과 같은 클라우드 플랫폼 환경에서 사용

디플로이먼트 생성

  1. 매니페스트 파일 정의(yml)
vagrant@ubuntu:~/kub01$ vi deployment-hostname.yml
`YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostname-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webserver
  template:
    metadata:
      name: my-webserver
      labels:
        app: webserver
    spec:
      containers:
      - name: my-webserver
        image: alicek106/rr-test:echo-hostname
        ports:
        - containerPort: 80
`

# alicek106/rr-test:echo-hostname 이미지로 컨테이너를 실행
# host name을 보여주는 web이 뜬다.
vagrant@ubuntu:~$ docker run -itd --name test -p 80:80  alicek106/rr-test:echo-hostname
346c0be44baebdd8be42a281fc4bd7fa56b157ffaf6ee62c6726857825df71e0

vagrant@ubuntu:~$ docker container ls
CONTAINER ID        IMAGE                               COMMAND                   CREATED             STATUS              PORTS                                                                                                      NAMES
346c0be44bae        alicek106/rr-test:echo-hostname     "/bin/sh -c /entrypo…"   6 seconds ago       Up 4 seconds        0.0.0.0:80->80/tcp                                                                                         test

vagrant@ubuntu:~$ docker container exec -it test /bin/bash
root@346c0be44bae:/# exit

vagrant@ubuntu:~$ curl http://localhost:80

`html
<!DOCTYPE html>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="./css/layout.css" />
3.3.2/css/bootstrap.min.css">

<div class="form-layout">
        <blockquote>
        <p>Hello,  346c0be44bae</p>     </blockquote>        ⇐ 컨테이너 ID = 호스트 이름
</div>
`
  1. 디플로이먼트 생성

kubectl apply -f deployment-hostname.yml

  1. 디플로이먼트를 통해서 생성된 pod 조회

kubectl get pods

  1. -o wide 옵션을 이용해서 각 pod 에 할당된 IP 확인

kubectl get pods -o wide o, --output='' : 출력 포맷을 지정

  1. 임시 pod 를 생성하여 hostname-deployment 디플로이먼트로 생성된 파드로 HTTP 요청

ClusterIP 타입의 서비스 _ 쿠버네티스 내부에서만 pod 접근 가능

  1. 매니페스트 파일 작성
vagrant@ubuntu:~/kub01$ vi hostname-svc-clusterip.yml
`YAML
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-clusterip
spec:
  ports:
    - name: web-port
      port: 8080   
      targetPort: 80
  selector:
    app: webserver
  type: ClusterIP
`

port : 서비스의 IP에 접근할 때 사용할 포트

targetPort : selector 항목에서 정의한 라벨에 의해 접근 대상이 된 pod 내부에서 사용하고 있는 포트

selector : 어떤 라벨을 가지는 pod에 접근할 수 있게 만들지 결정

type : 서비스 타입

  1. 서비스 생성 및 확인
vagrant@ubuntu:~/kub01$ kubectl apply -f hostname-svc-clusterip.yml
service/hostname-svc-clusterip created

vagrant@ubuntu:~/kub01$ kubectl get services
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
hostname-svc-clusterip   ClusterIP   10.110.56.159   <none>        8080/TCP   8s
kubernetes               ClusterIP   10.96.0.1       <none>        443/TCP    3d
# NAME : kubernetes 쿠버네티스 API에 접근하기 위한 서비스
  1. 임시 pod 생성해서 요청 전송
kubectl run -it --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash

vagrant@ubuntu:~/kub01$ kubectl run -it --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
If you don't see a command prompt, try pressing enter.

root@debug:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
82: eth0@if83: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:12:00:06 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.6/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever

root@debug:/# curl http://10.110.56.159:8080 --silent | grep Hello
        <p>Hello,  hostname-deployment-7dfd748479-pp8x4</p>     </blockquote>
root@debug:/# curl http://10.110.56.159:8080 --silent | grep Hello
        <p>Hello,  hostname-deployment-7dfd748479-pp8x4</p>     </blockquote>

서비스 확인

kubectl get services : 서비스 목록 보여줌

서비스의 IP와 PORT를 통해 pod에 접근, 서비스와 연결된 pod에 로드밸런싱 수행

서비스 삭제

kubectl delete service hostname-svc-clusterip
반응형

디플로이먼트(Deployment)

https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/

레플리카셋을 관리하고 컨트롤한다. 애플리케이션의 업데이트와 배포를 쉽게 하기 위해 만든 개념

디플로이먼트 생성 확인

vagrant@ubuntu:~/kub01$ vi deployment-nginx.yml
`YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-nginx
  template:
    metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.10
        ports:
        - containerPort: 80
`
vagrant@ubuntu:~/kub01$ kubectl apply -f deployment-nginx.yml
deployment.apps/my-nginx-deployment created

vagrant@ubuntu:~/kub01$ kubectl get deployment
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
my-nginx-deployment   3/3     3            3           17s

vagrant@ubuntu:~/kub01$ kubectl get replicasets
NAME                             DESIRED   CURRENT   READY   AGE
my-nginx-deployment-7484748b57   3         3         3       30s

vagrant@ubuntu:~/kub01$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
my-nginx-deployment-7484748b57-dlhbn   1/1     Running   0          38s
my-nginx-deployment-7484748b57-sc6bk   1/1     Running   0          38s
my-nginx-deployment-7484748b57-vr74n   1/1     Running   0          38s

디플로이먼트를 삭제했을 때, replicaset, pod도 함께 삭제됨 확인

vagrant@ubuntu:~/kub01$ kubectl delete deployment my-nginx-deployment
deployment.apps "my-nginx-deployment" deleted

vagrant@ubuntu:~/kub01$ kubectl get deployment
No resources found in default namespace.

vagrant@ubuntu:~/kub01$ kubectl get replicasets
No resources found in default namespace.

vagrant@ubuntu:~/kub01$ kubectl get pods
No resources found in default namespace.

디플로이먼트 사용 이유?

디플로이먼트는 컨테이너 애플리케이션을 배포하고 관리하는 역할

애플리케이션을 업데이트 할 때 레플리카셋의 변경 사항을 저장하는 리비전을 남겨 롤백 가능하게 해 주고, 무중단 서비스를 위한 파드의 롤링 업데이트 전략을 지정할 있음

--record 옵션을 추가해 디플로이먼트 생성

vagrant@ubuntu:~/kub01$ kubectl apply -f deployment-nginx.yml --record
deployment.apps/my-nginx-deployment created

vagrant@ubuntu:~/kub01$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
my-nginx-deployment-7484748b57-8ph87   1/1     Running   0          8s
my-nginx-deployment-7484748b57-fkc2q   1/1     Running   0          8s
my-nginx-deployment-7484748b57-v7hkr   1/1     Running   0          8s

kubectl set image 명령으로 pod 이미지 변경

vagrant@ubuntu:~/kub01$ kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record
                                                     디플로이먼트 이름    컨테이너 이름
deployment.apps/my-nginx-deployment image updated

vagrant@ubuntu:~/kub01$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
my-nginx-deployment-556b57945d-mlj7s   1/1     Running   0          14s
my-nginx-deployment-556b57945d-sklj2   1/1     Running   0          6s
my-nginx-deployment-556b57945d-tdg2t   1/1     Running   0          4s

pods 의 NAME을 보면 바뀐것을 확인 할 수 있다. 실습 예제에선 nginx 버전을 바꿨기 때문에 기존 pod이 전부 내려가고 새로운 pod 가 replicasetd규칙에 의해 3개가 올라옴

replicas 값만 변경해서는 레플리카셋의 교체가 일어나지는 않는다.

리비전 정보를 확인

--record=true 옵션으로 디플로이먼트를 변경하면 변경 사항을 기록하여 해당 버전의 레플리카셋을 보관할 수 있다.

vagrant@ubuntu:~/kub01$ kubectl rollout history deployment my-nginx-deployment
deployment.apps/my-nginx-deployment
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=deployment-nginx.yml --record=true
2         kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record=true

이전 버전의 레플리카셋으로 롤백

vagrant@ubuntu:~/kub01$ kubectl rollout undo deployment my-nginx-deployment --to-revision=1
deployment.apps/my-nginx-deployment rolled back

vagrant@ubuntu:~/kub01$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
my-nginx-deployment-7484748b57-2mks2   1/1     Running   0          12s
my-nginx-deployment-7484748b57-2xpsw   1/1     Running   0          15s
my-nginx-deployment-7484748b57-ngcd4   1/1     Running   0          14s

vagrant@ubuntu:~/kub01$ kubectl get replicasets
NAME                             DESIRED   CURRENT   READY   AGE
my-nginx-deployment-556b57945d   0         0         0       11m
my-nginx-deployment-7484748b57   3         3         3       15m

vagrant@ubuntu:~/kub01$ kubectl rollout history deployment my-nginx-deployment
deployment.apps/my-nginx-deployment
REVISION  CHANGE-CAUSE
2         kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record=true
3         kubectl apply --filename=deployment-nginx.yml --record=true

디플로이먼트 상세 정보 확인

vagrant@ubuntu:~/kub01$ kubectl describe deploy my-nginx-deployment
Name:                   my-nginx-deployment
Namespace:              default
CreationTimestamp:      Mon, 21 Sep 2020 04:13:55 +0000
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 3
                        kubernetes.io/change-cause: kubectl apply --filename=deployment-nginx.yml --record=true
Selector:               app=my-nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=my-nginx
  Containers:
   nginx:
    Image:        nginx:1.10
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   my-nginx-deployment-7484748b57 (3/3 replicas created)
Events:
  Type    Reason             Age                  From                   Message
  ----    ------             ----                 ----                   -------
  Normal  ScalingReplicaSet  15m                  deployment-controller  Scaled up replica set my-nginx-deployment-556b57945d to 1
  Normal  ScalingReplicaSet  15m                  deployment-controller  Scaled down replica set my-nginx-deployment-7484748b57 to 2
  Normal  ScalingReplicaSet  15m                  deployment-controller  Scaled up replica set my-nginx-deployment-556b57945d to 2
  Normal  ScalingReplicaSet  14m                  deployment-controller  Scaled down replica set my-nginx-deployment-7484748b57 to 1
  Normal  ScalingReplicaSet  14m                  deployment-controller  Scaled up replica set my-nginx-deployment-556b57945d to 3
  Normal  ScalingReplicaSet  14m                  deployment-controller  Scaled down replica set my-nginx-deployment-7484748b57 to 0
  Normal  ScalingReplicaSet  3m43s                deployment-controller  Scaled up replica set my-nginx-deployment-7484748b57 to 1
  Normal  ScalingReplicaSet  3m42s                deployment-controller  Scaled down replica set my-nginx-deployment-556b57945d to 2
  Normal  ScalingReplicaSet  3m42s                deployment-controller  Scaled up replica set my-nginx-deployment-7484748b57 to 2
  Normal  ScalingReplicaSet  3m40s (x2 over 19m)  deployment-controller  Scaled up replica set my-nginx-deployment-7484748b57 to 3
  Normal  ScalingReplicaSet  3m40s                deployment-controller  Scaled down replica set my-nginx-deployment-556b57945d to 1
  Normal  ScalingReplicaSet  3m37s                deployment-controller  Scaled down replica set my-nginx-deployment-556b57945d to 0

 

반응형

레플리카셋(Replica Set)

똑같은 pod의 레플리케이션 개수를 관리 및 제어하는 리소스.

보장하는 개수의 기준은 LABELS을 보고 판단한다. NAME이 아님

minikube status
# minikube 의 상태 확인

minikube start
minikube status
# minikube 시작 후 다시 확인

kubectl get pods
# 실행중인 파드 확인
kubectl delets pods <POD_NAME>
# 실행중인 파드 삭제

# pod 삭제 방법1
kubectl delete -f <YAML_FILE_NAME>
# pod 생성
kubectl apply -f <YAML_FILE_NAME>

# pod 삭제 방법2
kubectl delete pods <POD_NAME>

레플리카셋 정의

실습을 위한 세팅 생성 vim replicaset-nginx.yml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-nginx-pods-label
  template:
    metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx-pods-label
    spec:
      containers:
      - name: my-nginx-container
        image: nginx:latest
        ports:
        - containerPort: 80
          protocol: TCP

레플리카셋 생성 및 확인

kubectl apply -f replicaset-nginx.yml
kubectl get pod
kubectl get replicase

vagrant@ubuntu:~/kub01$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
replicaset-nginx-df4nw   1/1     Running   0          25m
replicaset-nginx-qf8cq   1/1     Running   0          25m
replicaset-nginx-spzvx   1/1     Running   0          25m
vagrant@ubuntu:~/kub01$ kubectl get replicaset
NAME               DESIRED   CURRENT   READY   AGE
replicaset-nginx   3         3         3       25m

Pod 개수를 늘려 실행

yml 파일의 spec 어트리뷰트의 replicas 수를 변경

kubectl apply -f YAML_FILE_NAME

레플리카셋을 삭제

레플리카셋을 삭제하면 Pod 도 함께 삭제된다.

kubectl delete replicaset <REPLICASET_NAME>
# 또는
kubectl delete rs <REPLICASET_NAME>

# YAML 파일을 이용한 삭제 방법
kubectl delete -f <YAML_FILE_NAME>

레플리카셋은 셀렉터로 정의한 pod 가 일정 개수가 되도록 유지

  1. my-nginx-pods-label 라벨을 가지는 파드를 생성
vagrant@ubuntu:~/kub01$ vi nginx-pod-without-rs.yml

`YAML
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-pod
  labels:
    app: my-nginx-pods-label
spec:
  containers:
  - name: my-nginx-container
    image: nginx:latest
    ports:
    - containerPort: 80
`

vagrant@ubuntu:~/kub01$ kubectl apply -f nginx-pod-without-rs.yml
pod/my-nginx-pod created

vagrant@ubuntu:~/kub01$ kubectl get pods --show-labels
NAME           READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-pod   1/1     Running   0          19s   app=my-nginx-pods-label
  1. my-nginx-pods-label 라벨을 가지는 파드 3개를 생성하는 레플리카셋을 생성
vagrant@ubuntu:~/kub01$ vi replicaset-nginx.yml
```YAML
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-nginx-pods-label
  template:
    metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx-pods-label
    spec:
      containers:
      - name: my-nginx-container
        image: nginx:latest
        ports:
        - containerPort: 80
          protocol: TCP

vagrant@ubuntu:~/kub01$ kubectl apply -f replicaset-nginx.yml
replicaset.apps/replicaset-nginx created

vagrant@ubuntu:~/kub01$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
my-nginx-pod 1/1 Running 0 4m12s app=my-nginx-pods-label
replicaset-nginx-59992 1/1 Running 0 27s app=my-nginx-pods-label
replicaset-nginx-gbzrr 1/1 Running 0 27s app=my-nginx-pods-label

3. pod 수동으로 삭제해보고 조회

```bash
vagrant@ubuntu:~/kub01$ kubectl delete pods my-nginx-pod
pod "my-nginx-pod" deleted

vagrant@ubuntu:~/kub01$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
replicaset-nginx-59992   1/1     Running   0          4m40s
replicaset-nginx-gbzrr   1/1     Running   0          4m40s
replicaset-nginx-vfjqn   1/1     Running   0          14s
  1. 레플리카셋이 생성한 pod의 라벨 변경

라벨 주석처리 해본다.

vagrant@ubuntu:~/kub01$ kubectl edit pods replicaset-nginx-59992
`YAML
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2020-09-21T02:18:06Z"
  generateName: replicaset-nginx-
  #  labels:
  #    app: my-nginx-pods-label
  name: replicaset-nginx-59992
<이하생략>
`

vagrant@ubuntu:~/kub01$ kubectl get pods --show-labels
NAME                     READY   STATUS    RESTARTS   AGE     LABELS
replicaset-nginx-59992   1/1     Running   0          9m31s   <none>
replicaset-nginx-bhz8w   1/1     Running   0          56s     app=my-nginx-pods-label
replicaset-nginx-gbzrr   1/1     Running   0          9m31s   app=my-nginx-pods-label
replicaset-nginx-vfjqn   1/1     Running   0          5m5s    app=my-nginx-pods-label
  1. 레플리카셋 삭제

결과 예상 : 같은 라벨 pod 삭제

vagrant@ubuntu:~/kub01$ kubectl get replicaset
NAME               DESIRED   CURRENT   READY   AGE
replicaset-nginx   3         3         3       12m

vagrant@ubuntu:~/kub01$ kubectl get pods --show-labels
NAME                     READY   STATUS    RESTARTS   AGE     LABELS
replicaset-nginx-59992   1/1     Running   0          12m     <none>
replicaset-nginx-bhz8w   1/1     Running   0          3m49s   app=my-nginx-pods-label
replicaset-nginx-gbzrr   1/1     Running   0          12m     app=my-nginx-pods-label
replicaset-nginx-vfjqn   1/1     Running   0          7m58s   app=my-nginx-pods-label

vagrant@ubuntu:~/kub01$ kubectl delete replicasets replicaset-nginx
replicaset.apps "replicaset-nginx" deleted

vagrant@ubuntu:~/kub01$ kubectl get replicaset
No resources found in default namespace.

vagrant@ubuntu:~/kub01$ kubectl get pods --show-labels
NAME                     READY   STATUS    RESTARTS   AGE   LABELS
replicaset-nginx-59992   1/1     Running   0          13m   <none>
  1. 라벨이 삭제된 파드는 직접 삭제
vagrant@ubuntu:~/kub01$ kubectl delete pods replicaset-nginx-59992
pod "replicaset-nginx-59992" deleted

vagrant@ubuntu:~/kub01$ kubectl get pods --show-labels
No resources found in default namespace.
반응형

파드(pod)

컨테이너 애플리케이션의 기본 단위

1개 이상의 컨테이너로 구성된 컨테이너의 집합

여러 개의 컨테이너를 추상화해서 하나의 애플리케이션으로 동작하도록 묶어 놓은 컨테이너의 묶음

nginx 컨테이너로 구성된 파드를 생성

nginx-pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-container
spec:
  containers:
  - name: my-nginx-container
    image: nginx:latest
    ports:
    - containerPort: 80
      protocol: TCP
# YAML 파일에서 정의한 오브젝트의 API 버전
# 리소스의 종류
# 라벨, 주석, 이름과 같은 리소스의 부가 정보

# 컨테이너 리소스 생성을 위한 정보

파드 생성

kubectl apply -f <YML_FILE_NAME>

# 새로운 파드 생성
vagrant@ubuntu:~/kub01$ kubectl apply -f nginx-pod.yml
pod/my-nginx-container created

모든 파드 확인

kubectl get pods

# 파드 확인
vagrant@ubuntu:~/kub01$ kubectl get pods
NAME                 READY   STATUS    RESTARTS   AGE
my-nginx-container   1/1     Running   0          63s

# 축약어를 사용할 수 있다
vagrant@ubuntu:~/kub01$ kubectl get po
NAME                 READY   STATUS    RESTARTS   AGE
my-nginx-container   1/1     Running   0          68s

상세 정보 조회

kubectl describe pods <POD_NAME>

# 생성된 리소스의 자세한 정보 확인
vagrant@ubuntu:~/kub01$ kubectl describe pods my-nginx-container
Name:         my-nginx-container
Namespace:    default
Priority:     0
Node:         minikube/172.17.0.3
Start Time:   Fri, 18 Sep 2020 06:39:13 +0000
Labels:       <none>
Annotations:  <none>
Status:       Running
IP:           172.18.0.3
IPs:
  IP:  172.18.0.3
Containers:
  my-nginx-container:
# <이하생략>

파드 컨테이너 생성과 확인 실습

# 클러스터 내부에 테스트를 위한 임시 파드를 생성
# alicek106/ubuntu:curl 이미지를 이용해서 debug 이름의 파드를 생성
vagrant@ubuntu:~/kub01$ kubectl run -it --rm debug --image=alicek106/ubuntu:curl --restart=Never bash
If you don't see a command prompt, try pressing enter.
root@debug:/#
# debug 파드가 생성 된 상태에서 파드 조회
vagrant@ubuntu:~/kub01$ kubectl get pod
NAME                 READY   STATUS    RESTARTS   AGE
debug                1/1     Running   0          73s
my-nginx-container   1/1     Running   0          8m36s

# nginx 파드의 동작을 확인 (172.18.0.3)
root@debug:/# curl 172.18.0.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
# <이하생략>

kubectl exec 명령으로 파드의 컨테이너에 명령을 전달

kubectl exec -it <POD_NAME> -- <COMAND>

vagrant@ubuntu:~/kub01$ kubectl exec -it my-nginx-container -- bash
root@my-nginx-container:/# whoami
root
root@my-nginx-container:/# exit
exit

kubectl logs 명령으로 파드 로그 확인

kubectl log <POD_NAME>

vagrant@ubuntu:~/kub01$ kubectl logs my-nginx-container
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
172.18.0.4 - - [18/Sep/2020:06:48:42 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.35.0" "-"

쿠버네티스 오브젝트를 YAML을 이용해 삭제

kubectl delete -f <YAML_FILE_NAME>

vagrant@ubuntu:~/kub01$ kubectl delete -f nginx-pod.yml
pod "my-nginx-container" deleted

# 모든 pod 조회
vagrant@ubuntu:~/kub01$ kubectl get pods
No resources found in default namespace.
vagrant@ubuntu:~/kub01$

1개의 pod안에 여러개의 컨테이너가 있는 경우 실습

nginx-pod-with-ubuntu.yml

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-pod
spec:
  containers:
- name: my-nginx-container
    image: nginx:latest
    ports:
    - containerPort: 80
      protocol: TCP

  - name: ubuntu-sidecar-container
    image: alicek106/rr-test:curl
    command: [ "tail" ]
    args: [ "-f", "/dev/null" ]

pod 생성

vagrant@ubuntu:~/kub01$ kubectl apply -f nginx-pod-with-ubuntu.yml
pod/my-nginx-pod created
vagrant@ubuntu:~/kub01$ kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
my-nginx-pod   2/2     Running   0          20s
  • pod로 명령어를 전달할 때 실행할 컨테이너를 지정 안하면 default 설정 컨테이너가 실행됨
vagrant@ubuntu:~/kub01$ kubectl exec -it my-nginx-pod -- bash
Defaulting container name to my-nginx-container.
Use 'kubectl describe pod/my-nginx-pod -n default' to see all of the containers in this pod.
root@my-nginx-pod:/# exit
exit
  • 특정 컨테이너에게 명령어를 전달 할 때는 -c 옵션을 사용한다.
vagrant@ubuntu:~/kub01$ kubectl exec -it my-nginx-pod -c ubuntu-sidecar-container -- bash
root@my-nginx-pod:/#

root@my-nginx-pod:/# curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>

# 이 실습으로 알 수 있는점: 하나의 Pod 내에서는 네트워크 네임스페이스를 공유하는것을 알 수 있다.

 

반응형

도커에서 나아가 쿠버를 써야하는 이유?

멀티호스트의 상황에서 효율적인 스케줄링을 하기 위해서. 컨테이너를 할당하는 식

레플리케이션 컨트롤러 레플리카셋 등을 이용해 장애에 대응

  • 노드가 죽으면 통째로 복사해서 새로운 노드를 만듦
  • 팟이 죽으면 새 팟을 실행 사용자 정의에 의한 대응

컨테이너교체 편리 - 롤링업데이트 제공. 오래된것 교체. 신규 팟 생성후 옛것을 삭제.

팟이란? 그릇이란 뜻으로 컨테이너를 담고있음 1개 이상 가능. 보통 1개

여행으로 보는 인프라 환경

온프레미스 : 내가 다 준비

IaaS : 바닥은 있다. EC2

PaaS : 취향따라 먹을것만 싸간다. 공통부분. 미들웨어 EC2 등..

SaaS : 다 준비해준다. 돈만있으면 된다. 아이디 비밀번호 제공 받아

컨테이너?

전체 OS가 아닌 SW가 필요로 하는 라이브러리와 설정만 포함한다.

단일 Linux 호스트에서 Container 독립 실행을 위한 OS 가상화 기술

Linux kernel의 cgroups, namespace를 공유한다.

파일 실행은 호스트에서 직접 실행하여 빠르다.

도커 컨테이너

Linux Container 기술을 적용한 도커엔진으로 도커 Hub Registry를 통한 Docker Image를 관리한다.

어디서나 이미지를 빌드하여 쉽게 배포/운영 할 수 있게 하는것이 목표이다.

컨테이너 오케스트레이션

컨테이너 호스트 여러개를 관리하는 방법으로

  1. 스케줄링
  2. 클러스터 관리
  3. 서비스 디스커버리
  4. 모니터링

이 있다.

쿠버네티스

컨테이너 오케스트레이터로 google borg에서 시작되어 오픈소스화 되었다. ( go언어로 작성 )

장점

  • Automatic binpacking : 가용성의 희생없이 리소스 사용과 제약사항을 기준으로 자동으로 컨테이너 를 스케줄링.
  • self-healing : 자동으로 문제가 발생한 노드의 컨테이너를 해제
  • horizontal scaling : CPU와 메모리 같은 리소스 사용에 따라 자동으로 애플리케이션을 확장. 경우에 따라 사용자 정의 측정값을 기준으로 한 동적인 확장 가능.

service discovery and Load balancing

  • caontainer에 고유 IP 부여 : 여러개의 container를 묶어 단일 service로 부여하는 경우 단일 dns name으로 접근하도록 로드 밸런싱을 제공

Automatic rollouts and rollbacks

다운 타임 없이 애플리케이션의 버전별 롤백, 롤아웃 가능.

Secret and configuration management

애플리케이션의 secret과 configuration 정보를 이미지와 독립적으로 구분하여 별도의 이미지 재생성 없이 관리

Storage Orchestration

Batch execution CI워크로드와 같은 batch성 작업지원, crontab 형식으로 스케줄링 가능

쿠버네티스 마스터 : API server. Controller Manager Server. Scheduler Server : 팀장 역할. 워크로드를 워크노드에 할당 등..

  • Kube - apiserver : cluster와 상호작용을 위한 k8s 서버.
  • Kube - scheduler : worker node에 있는 pod를 스케줄링
  • Kube - Controller - manager: Deploymenents 나 Replication controller 등 관리
  • Kube - cloud -manager : public cloud provider관리.
  • etcd : master cluster에서 k8s object 저장소로 사용

쿠버네티스 노드

  • Container runtime : 컨테이너 실행을 위한 Docker engine 포함
  • kubelet : master 명령 수행 에이전트
  • kube-proxy : 워커가 받은 트래픽에 대한 네트워크 프록시. 어떤 pods에 전달? (외부요청을 받아)

→ 인터넷을 통해 들어오는 요청을 Ingress controller를 거쳐 kube-proxy로

  • CAdvisor : 리소스 사용 / 성능 통계 제공 나바쁘다 . 한가하다.

Kubernetes Object Model

k8s object에 대한 manifest를 YAML형식으로 작성. Master 노드의 API Server를 통해 클러스터에 k8s Object 생성

k8s object API Version

Alpha → Beta → stable

Basic Objects

  • pod -중요
  • service -중요
  • volume
  • namespace

controllers

  • ReplicaSet
  • ReplicationController
  • Deployment -중요
  • StatefulSets
  • DaemonSet
  • Garbage Collection
  • Jobs
  • CronJob

Pod ( 내부에선 마치 서버처럼 이용 )

  • worker 노드에서 실행되는 컨테이너의 집합 ( 보통 1개의 컨테이너 )
  • 하나의 Pod에는 한개 이상의 서비스로 지정 될 수 있다.
  • 각각의 pod 에는 고유한 IP가 할당된다 (내부 IP)
  • 하나의 pod 내에서는 PID namespace, network와 hostname 공유

Service ( 외부에 노출시킬 때)

  • Label selector로 선택하여 하나의 endpoint로 노출되는 pod의 집합
  • Type : cluster IP, Node Port, Load Balancer, Exteral Name
    ExternalTrafficPolicy

service.spec.externalTrafficPolicy-이 서비스가 외부 트래픽을 노드 로컬 또는 클러스터 전체 엔드 포인트로 라우팅 하려는지 여부를 나타냅니다. 사용 가능한 옵션에는 클러스터 (기본값)와 로컬의 두 가지가 있습니다. 클러스터는 클라이언트 소스 IP를 모호하게하고 다른 노드로 두 번째 홉을 유발할 수 있지만 전체적인로드 확산이 좋아야합니다. Local은 클라이언트 소스 IP를 보존하고 LoadBalancer 및 NodePort 유형 서비스에 대한 두 번째 홉을 피하지만 잠재적으로 불균형 트래픽 확산 위험이 있습니다.

  • Cluster 정책: 트래픽이 클러스터의 정상 GKE 노드로 부하 분산된 다음 kube-proxy가 트래픽을 pod가 있는 노드로 전송합니다.
  • Local 정책: 백엔드 pod 중 하나가 없는 노드는 TCP/UDP 부하 분산기에 비정상으로 표시됩니다. 트래픽은 pod가 있는 나머지 정상 클러스터 노드 중 하나로만 전송됩니다. 트래픽은 kube-proxy에 의해 다시 라우팅되지 않고 대신 IP 헤더 정보가 그대로 있는 로컬 pod로 직접 전송됩니다.

https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip

Ingress

밖에서 접속시 IP : 포트로 접속할 수 있지만 도메인/디렉터리 형식으로

서비스에 대한 [공백] (애플리케이션 레이어) 라우터 정의

사용자가 직접 서비스에 접근하지 않고 Ingress를 통해 접근

ConfigMap

pod에 담겨진 container에서 사용되는 구성 값

Secret

컨테이너에서 읽혀지거나 사용되는 소량의 민감한 정보. 특수한 Volume이 자동으로 연결되어 container에서 사용 가능. 수동으로 Secret을 생성하고 연결하여 사용가능. Base64로 encoding 될 뿐 암호화 x, volume으로 연결된 file형식 또는 변수 형식으로 사용가능

Deployment Controller

  • pod 의 배포 및 관리에 사용
  • ReplicaSet을 자동으로 생성 ( 같은 기능을 하는 단위로 버전 집합 )
  • pod에 대한 rolling 업데이트 관리

ReplicaSet ( 같은 기능을 하는 pod의 집합 )

  • Replication Controller의 새로운 버전
  • 가용성과 확장성 보장
  • 사용자의 요청에 따른 pod의 숫자를 유지하고 관리
  • 각각의 pod가 필요로하는 정보 명세가 있는 template을 이용

StatefulSet

  • Deployment와 유사하나 pod별 고정된 identity(name, network Id등) 할당

DaemonSet

  • 모든 Node에 배포되어 실행(Node Selector로 정의하는 경우 일부 Node에서만 실행)

Job (배치랑 비슷)

  • 특정 task 실행을 위해 하나 혹은 그 이상의 pod을 생성하고 실행
  • pod가 실행 완료하는 것을 보장. (실패시 재시도, deadline 설정 가능 )
  • Job 실행시 pod의 순차실행 또는 동시 실행 가능
  • pod의 모든 실행 완료시 Job의 완료로 인식하고 사용한 pod 제거

Volume

  • pod에 연결되어 디렉터리 형태로 데이터를 저장할 수 있도록 제공
  • pod의 container들끼리 공유
  • pod와 Life-cycle이 동일하게 적용. pod 삭제시 같이 삭제

PersistenVolume

클러스터 관리자에 의해 제공되는 저장소 일부 pod과 독립적

저장소는 pv나 PVC에 저장해야 한다.

kubectl

k8s 클러스터 관리자를 위한 CLI 도구

kubernetes Helm

  • k8s chart 패키지 관리 (조회, 설치, 갱신 및 삭제)
  • Linux의 yum 또는 apt와 유사
  • tiler : k8s 클러스터 내부에 설치된 서버
  • helm : 외부에서 접근하는 클라이언트
반응형

쿠버네티스

대부분의 리소스를 오브젝트 라고 불리는 형태로 관리한다.

쿠버네티스에서는 컨테이너의 집합(pods), 컨테이너의 집합을 관리하는(replica set), 사용자(service account), 노드(node) 까지도 하나의 오브젝트로 사용할 수 있다.

kubectl 명령어 또는 YAML 파일로 정의하여 쿠버네티스를 사용한다.

쿠버네티스 실습 환경 설정 (우분투)

가상머신 생성 - Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
  config.vm.hostname = "ubuntu"
  config.vm.network "private_network", ip: "192.168.111.110"
  config.vm.synced_folder ".", "/home/vagrant/sync", disabled: true
  config.vm.provider "virtualbox" do |vb|
    vb.cpus = 2
    vb.memory = 2048
  end
end

패키지 최신화 및 도커 설치, 설정

sudo apt update
sudo apt upgrade

sudo apt install docker.io -y
sudo usermod -a -G docker $USER
sudo service docker restart
sudo chmod 666 /var/run/docker.sock
docker version

kubectl 설치

# https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/

# 공식 레퍼 따른다. 끝난 후 확인
kubectl version

Minikube 설치

# https://kubernetes.io/ko/docs/tasks/tools/install-minikube/

# 공식 레퍼 따른다.
# 클러스터 시작
minikube start

# 클러스터 정지
minikube stop

#클러스터 전부 삭제
minikube delete

# 확인
minikube status

kubectl version --short

쿠버네티스에서 사용할 수 있는 오브젝트 확인

kubectl api-resources

반응형

프림 알고리즘 (Prim's algorithm)

특정 연결 노드를 선택 했을때 탐욕 알고리즘에 따라 진행하는 방법으로 현재 선택된 그래프 중에서 가장 작은 값을 선택하며 노드를 연결해 나가는 방식

  1. 임의의 정점 선택
  2. 연결된 노드 집합에 선택된 노드를 넣고 그 노드의 간선 중 가장 값이 적은 걸 선택함.
  3. 선택해서 연결된 노드가 연결된 노드 집합에 없으면 그 간선을 채택 ( 사이클 체크 )
  4. 간선 리스트에 간선이 없을 때까지 반복

코딩 팁 : 엣지 먼저 구현한다

 

from heapdict import heapdict
def prim(graph, start):
	mst, keys, pip, total_weight = list(), heapdict(), dict(), 0
    for node in graph_keys():
    	keys[node] = float('inf')
        pip[node] = none
    keys[start], pip[start] = 0, start

    while keys:
        current_node, current_key = keys, popitem()
        mst.append([pip[current_node], current_node, current_key])
        total_weight += current_key
        for adjacent, weight in mygraph[current_node], items():
            if adjacent in keys and weight < keys[adjacent]:
                keys[adjacent] = weight
                pip[adjacent] = current_node
return mst, total_weight

heapdict() 을 사용하면 pop할때 항상 자동으로 최소값이 갱신된다.

반응형

+ Recent posts