반응형

웹 페이지를 개설했다면, 그리고 외부에서 접근가능하려면 어떻게 해야할까?

이를 위해 많은 분들이 Service와 Ingress를 혼동한다. 그래서 이에 대해 짧게 알아보도록 하자.

 

 

NodePort type의 Service를 통해 포트를 정의해줘서 외부로부터 접근이 가능하게 만들 수 있다.

그리고, 포트를 외우기 귀찮으니(원래는 http://my-online-store.com:38080으로로 접근)

proxy server를 이용함으로써 URL을 통해 접근 가능하게 한다.

 

만약 GCP등의 Cloud platform을 사용한다면 LoadBalancer Type의 service를 사용하면 된다.

그럼 K8s가 알아서 포트, 외부 ip등을 다 할당해준다.

 

 

자, 그런데 비즈니스가 잘 되어서 /watch라는 또 다른 app을 만든다고 치자.

그럼 기존 my-online-store.com은 my-online-store.com/wear로 바꾸어야할 것이다.

 

 

그럼 동일한 클러스터 내 오른쪽 노란색 표기와 같이 새로운 인스턴스들을 만든다.

그럼, wear app에 접근 또는 video 앱에 각각 접근하기 위해 어떻게 해야할까?

가장 상단에 새로운 service를 만들어서 이 두개 app에 대한 정의를 해야하고, SSL enable도 시켜야 한다.

그런데 이건, app level과 다른 level이다.

 

그런데, app이 더 늘어날 경우?

계속 파일을 수정해줘야하고 SSL도 처리해야하고, 경로와 포트등을 계속 만들어줘야 한다.

 

그래서 Ingress라는 개념이 나왔다.

 

 

 

Ingress는 K8s에 built-in된 7계층 LoadBalancer로,

하나의 외부 URL을 이용해서 클러스터 내 다른 서비스로 라우팅을 시켜줄 수 있고, SSL Security또한 실행해줄 수 있다.

 

하지만, 이 또한 외부에서 클러스터로 접근하기 위해

node port 또는 cloud native LB를 사용해서 외부로 노출시켜줘야 한다.

다만, 이건 단 한번만 하면 된다. 

 

 

1. Deploy = Ingress controller

Ingress를 위한 solution으로는 nginx, haproxy, traefik 등을 사용하면 된다.

이렇게 deploy하게되는 솔루션들을 ingress controller라고 부르고,

 

2. Configure = Ingress resources

설정하는 rule들을 ingress resource라고 부른다.

이건 기존 우리가 생성했던 pod deploy처럼 definition file을 이용해서 생성된다.

 

그런데, ingress controller는 defualt로 built-in 되어있지 않다. 

그래서 이걸 무조건 deploy 해줘야 하는데, 어떤 걸 deploy 해줘야할까?

 

 

위와 같이 많은 종류의 사용 가능한 솔루션이 있다.

이 강의에서는 nginx를 예시로 사용하고 있고, 이건 기존에 사용하던 LB나 nginx 서버와는 다르다.

Ingress controller에서 LB 컴포넌트는 단지 일부일뿐이고, K8s 클러스터를 모니터링 할 수 있는 기능이 포함되어 있다.

 

Controller는 다른 deployment와 동일한 방식으로 deploy 되는데, definition file을 한번 확인해보자.

 

 

nginx program은 /nginx-ingress-controller라는 경로에 저장되어 있는데, 

keep-alive threshold, ssl setting, session timeout 등을 설정하기 위해 별도의 ConfigMap을 만든다.

그래서 configmap에 대한 정의 또한 args에 포함한다.

 

그리고, pod와 pod의 namespace 또한 env로 포함해줘야하고,

ingress controller에 의해 사용되는 ports 또한 추가한다.

 

그리고, ingress controller를 외부 세상에 노출하기 위해 service가 필요하다.

그래서 NodePort 타입의 service를 생성하고, label-selector를 이용해서 deployment와 링크시킨다.

 

그리고, 아까 언급했듯 ingress는 k8s 클러스터를 모니터링하는 추가적인 기능들을 갖고 있다.

그래서 어떤 설정이 변경되었을 때, 그것들을 nginx 서버에 설정할 수 있는데, 이를 위해 service account가 필요하다.

이 service account에는 맞는 퍼미션이 필요한데, 그를 위해 roles과 roles binding이 필요하다.

 

즉, 정리하자면

ingress를 위해서는 최소한으로 Deployment file, service file, configmap, Auth(ServiceAccount)가 필요하다.

 

ingress resource는 ingress controller에 적용되는 rules과 configurations들의 세트인데, 

첫 번째 그림과 같이 모든 incomming traffic에 대해 single application으로 route할 수도 있고, 

두 번째 그림과 같이 URL을 기반으로 다른 app들로 라우팅을 분배할 수도 있다. 

 

그럼 이것들을 어떻게 설정하는지 알아보자.

 

ingress resource는 위의 오른쪽과 같이 파일을 정의해주는데, pod에게 direct로 가는 게 아니라, service로 보내준다.

 

그리고, 다른 조건에 따라 traffic을 분리하고 싶을 때 rules을 사용할 수도 있는데,

위와 같이 www.my-online-store.com // www.wear.my-online-store.com/ 등으로 분리할 수 있다.

아래에서 하나씩 설정을 확인해보자.

 

 

위와 같이, 각 호스트의 top level로부터 rule을 생성할 수도 있고,

URL을 기반으로 라우팅 패스를 다르게 설정할 수도 있다. 

 

어떻게 설정할까?

처음엔 Ingress-wear.yaml를 사용했지만,

지금은 두 개의 app으로 나뉘므로, ingress-wear-watch.yaml 파일에서 각각의 path와 service를 정의해줘야 한다. 

 

이후 yaml파일을 apply로 생성하면, 위와 같이 ingress를 조회해볼 수 있다.

2가지 path가 생긴 것을 확인할 수 있는데, 위의 Default backend는 무엇일까?

 

 

유저가 접근을 시도하는 URL이 없을 때(어떤 Rule도 match되지 않을 때) 보여주는 page를 정의하는 것이다.

위의 oops 404 페이지처럼 말이다.

 

 

자, 그럼 3번째 설정 타입으로는 domain name 또는 host name을 이용하는 것을 알아보자.

이전 설정에선 host를 정의하지 않았는데, host를 정의하지 않으면

hostname matching 없이 특정 rule에 따라 incoming traffic이 허용된다.

 

이전에 만든 것과 비교해보면(왼쪽), rule에 hostname이 추가되었을 뿐이다. (오른쪽)

 

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형
반응형

K8s에서 client는 인증서를 사용하기 위해 curl 명령어를 이용하여 쿼리를 한다.

그런데, 명령어가 너무 길어지다보면 실수를 할 수도 있고 매일 이렇게 다 쳐주는 건 귀찮은 일이다.

 

 

그래서 kubeConfig File 개념이 나온다.

여기에 작성을 해 두고, 조회나 curl시 kubeConfig 를 이용하여 인증서를 조회할 수 있다.

그리고 kubeConfig 포맷은 크게 3가지 섹션으로 나뉘는데, 아래에서 알아보자.

 

 

크게 Clusters, Contexts, Users로 나뉜다.

Cluster는 말 그대로 시료 환경에 대한 것이고, clients 들은 k8s 환경에 접속하는 user들인데

각각 권한이 다르다.

Context는 어떤 Users가 어떤 Clusters에 접근하는지를 묶어주는 부분이다.

 

실제 KubeConfig file은 $HOME/.kube/config 디렉토리에 있으며,

clusters, contexts, users 섹션으로 나뉜다.

contexts의 cluster에 clusters name을 입력해주고, contexts의 user 부분에 users의 name을 입력해준다.

 

kubeConfig 파일은 위와 같이 조회할 수 있으며, current-context 수정은 오른쪽과 같이 가능하다.

# kubectl config view

# kubectl config use-context [변경할 내용]

 

그럼 다른 내용들을 수정/삭제하고 싶다면?

#kubectl config -h 를 통해 알아보면 된다.

 

 

Cluster내엔 다양한 namespace도 있을 텐데, kubeconfig에도 해당 namespace를 명시해줄 수 있다.

 

그리고 certificate-authority도 crt파일의 전체 path를 입력해줘야 하지만, 아예 

'certificate-authority-data'를 여기 파일에 직접 입력하는 방법도 있다. (물론 base64로)

 

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형
반응형

K8s에서는 Security가 매우 중요하다. 

kube-apiserver를 중심으로 security가 이뤄지는데, 중요한 것은

1. 누가 access할 수 있고

2. 그들이 뭘 할 수 있느냐다.

 

1. 누가 access할 수 있냐!? User 계정, 토큰, 인증서, ldap, service account 등이 있다.

 

2. 접근에 대해 권한을 받은 그들이 뭘 할 수 있냐면,

RBAC, ABAC, Node Authorization, Webhook Mode를 한다고 한다.

이게 뭘까? 하나씩 알아보자.

 

먼저, 각 컴포넌트들은 Kube ApiServer를 중심으로 TLS를 사용하여 보안을 유지하고 있고,

pod간은 network policy를 통해 보안을 유지하고 있다.

 

그럼, 먼저 내부 클러스터간 어떻게 인증을 해서 통신을 하고 관리되는지 알아보자.

 

 

먼저, cluster에 접근하는 user는 크게 Admin, Developers, Robots(k8s로 접근하는 외부 프로세스 들)으로 나눈다.

크게 보면 사람 / 로봇이다.

 

그런데, k8s는 자체적으로 user 관리를 하지 않고 Service Account에 한해 관리를 한다.

* Service account는 나중에 다루고, 이번 강의에선 user에 집중한다.

 

먼저 유저들은 API SERVER를 통해 K8S에 접근하는데, kube-apiserver가 해당 req에 대한 과정이 진행되기 전,

유저 인증(Authentication user)를 진행한다.

어떻게 인증을 할까?

StaticPassword File(직접 정보 입력), Static Token file, Certificates, Identity Service (3rd party authentication program. ex. LDAP)등의 방법이 있다.

 

 

 

1. StaticPassword File

user의 id/pw를 별도의 csv로 저장한 후, 그걸 apiservice.service에 '--basic-auth-file=user-details.csv'로 가져온다.

 

 

pod가 생성되면, curl 명령을 통해 kube-api server로 user의 id/pw를 이용하여 인증한다.

 

그리고, static password file에는 optional로 group 필드가 하나 더 있으며,

2. Static Token File은 Static password file 대비, password 대신 token을 사용한다.

key값 또한 '--basic-auth-file=user-details.csv'가 아닌, '--token-auth-file=user-details.csv'를 사용한다.

 

위에서 다룬 내용들은 이해를 위해 쉬운 방법들을 다룬 것이지, 권고하는 방법은 아니다.

다음 강의에서 하나씩 더 알아보자.

 

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

 

반응형
반응형

우린 이때까지 클러스터에 deployment, service definition file들을 이용하여 많은 app을 설치했다.

그 중에, etcd는 모든 클러스터와 관계있는 정보들이 저장되었는데,
만약 app이 persistent storage에 configured 된다면, 백업을 위한 다른 방법이 있다.

 

 

 

우리가 클러스터 내에 resource를 생성한다면, 명령어/YAML등을 통해 이를 정의했다.
그리고 후자의 방법(YAML을 통한 정의)이 더 선호되는 방식이다.

왜냐하면, object들은 하나의 폴더 내 object definition 형태를 요구하기 때문이다.

그래야 다음에 재 사용도 가능하고, 정보가 날라갔을 때도 얼른 붙여와서 사용할 수 있다.
그래서 이런 것들은 source code repository에 저장하는 것이 좋다. (GitHub등)
그리고 이런 repository는 적절한 backup solution이 설정되어야 하는데,
GitHub과 같은 repository는 이에 대해 걱정할 필요는 없다.


 

또 하나의 resource 설정 backup 방법은, kube-apiserver에 쿼리해서 모든 정보를 저장하는 것이다. 
# kubectl get all --all-namespaces -o yaml > all-deploy-services.yaml


그런데, 사실 이렇게 하는 것도 적은 resource에 대해서만 유용하지,

app이나 저장할 양이 커지면 관리하기도 어렵다.

그래서, k8s API를 사용하는 대용량 저장을 위한 VELERO라는 솔루션도 있다.


그럼 다시 ETCD Cluster로 돌아가본다.
etcd는 클러스터 자체, 그리고 내부 상태에 대한 정보를 저장한다. 

따라서, 이전과 같이 리소스를 백업하는 대신, 백업할 서버를 선택할 수 있다.  
etcd는 master node에 호스팅 되는데, etcd 내 모든 정보가 저장되는 location이 별도로 설정된다. (--data-dir=/var/lib/etcd/ )

 

그리고, etcd에는 snapshot 이라는 내장 기능도 있다.

ETCDCTL_API=3 etcdctl \
   snapshot save snapshot.db

 

 

그럼 복구 기능은?
kubeapi server를 stop시킨다. 그런 다음 etcdctl를 통해 snapshot restore + path cmd를 사용한다.
그러면, etcd는 backup파일로부터 복구를 시작하고, etcd 멤버가 새 멤버인 것처럼 새 클러스터에 설정된다(?).

이 방법은 존재하는 클러스터로부터 뉴 멤버를 막기 위함이다.(??? 이해 못함)

이렇게 하면, 새 데이터 디렉토리가 생성되고, 생성된 새 directory를 etcd config파일에 설정한다.
이후에 service 데몬을 reload하고 restart etcd를 한다.
k8s api server가 시작되면, 클러스터는 오리지널 상태가 된다.


정리하자면, 백업을 위한 2가지 옵션이 있다.
1. backup using etcd
2. backup using by querying the kube-APIverver
만약 cloud등의 환경에서 k8s를 사용한다면, outside cluster를 향한 접근이 없으니 2번을 쓰는 게 편할 것이다. 



# ETCDCTL_API=3 etcdctl version
# ETCDCTL_API=3 etcdctl --cacert="" --cert="" --key="" snapshot save /opt/snapshot-pre-boot.db 
 // 위의 ""에 kubectl describe po를 통해 조회한 값을 넣는다.


status도 조회 가능하다.

# ETCDCTL_API=3 etcdctl snapshot status /opt/snapshot-pre-boot.db 


복구

# ETCDCTL_API=3 etcdctl snapshot restart <filename> --data-dir= 
  ex. ETCDCTL_API=3 etcdctl snapshot restart /opt/snapshot-pre-book.db --data-dir=/var/lib/etcd-backup
  // 이렇게 하면 etcd-backup 디렉토리가 생성되고, restore도 진행됨.
  data-dir은 etcd yaml 파일에 있기 때문에, hostPath도 backup으로 인해 생성된 backup directory로 바꿔주기.

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형
반응형

K8s에는 각 컴포넌트마다 다른 버전을 가지고 있다.

그런데, kube-apiserver가 가장 상위 버전이고, 다른 것들은 kube-apiserver보다 높은 버전을 가질 수 없다. (동일은 가능)

단, kubectl의 경우 상위버전, 동일버전, 하위버전 모두 가질 수 있다.

 

그리고, k8s는 하위 3개의 minor버전까지만 support하기 때문에, v1.13이 배포되었다는 기준으로 

v.11까지만 upgrade할 수 있다.

그리고, upgrade를 할 땐 v1.10 -> v1.13으로 바로 가지말고, minor버전을 하나씩 올리라고 권고하고 있다.

ex. v1.10 -> v1.11 -> v1.12 -> v1.13

 

그럼, upgrade는 어떻게 진행할까?

GCP등 ServiceProvider에 올린 경우 버튼 몇번으로 진행할 수 있고,

이 외는 kubeadm을 통해 진행할 수 있다.

 

upgrade 절차는 Master Node를 먼저 진행하고, 그 이후엔 3가지 전략이 있다.

1) 전체Node 삭제 후 전체 Node 생성: service impacted

2) 하나의 Node씩 Upgrade: Impact 없음

 

3) 최신 버전인 new Node를 하나 생성한 후, 기존 node를 하나씩 upgrade하고, 기존 node중 하나 삭제

 (3은 cloud 환경에 있다면 가장 쉽고 편한 방법)

 

 

실제 upgrade command는

1. kubeadm upgrade plan을 통해 available한 pkg version을 조회한다.

# kubeadm upgrade plan

 

1 apt-get을 통해 pkg를 땡겨오고 (available한 건 v1.13.4였지만, 버전이 v1.11.3이었으므로 하나씩 올린다)

2. kubeadm upgrade apply v1.12.0을 통해 pkg를 upgrade한다.

3. version을 조회하면 아직 v1.11.3이다.

4. 이유는, 해당 버전은 kubelet을 기준으로 보이는데, kubelet이 upgrade되지 않았기 때문이다.

   그래서 kubelet을 마지막으로 upgrade한다.

# apt get upgrade -y kubeadm=1.12.0-00
# kubeadm upgrade apply v1.12.0
# kubectl get nodes
# apt-get upgrade -y kubelet=1.12.0-00
# systemctl restart kubelet

 

 

각 Node들을 upgrade할 땐, 이전 포스팅에서 다루었던 drain, uncordon 명령을 통해

https://countrymouse.tistory.com/entry/cka-6-1

node에 있는 pod가 미리 다른 pod로 옮겨갈 수 있게 설정해준다.

 

 

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형
반응형

pod를 upgrade할 때, pod들은 자동으로 down 되었다가 up이 된다.

그런데 이때, default 타이머가 5분으로, k8s는 5분동안 pod가 살아나지 않으면 죽었다고 판단 후 다른 node에 pod를 생성한다.

그럼, Node가 down될 경우는 어떨까?

 

(지금은 아무것도 없는) 2번째 Node에 파랑, 초록 pod들이 있었다.

그런데, Node 2가 down되면, replica에 속한 파란 노드의 경우 다른 node에 생성될 수 있다.

그런데, 초록이는 혼자 있던 pod(=daemon set)이고 replicaset에 속하지 않았기 때문에 다른 node로 생성될 수 없다.

 

그런데, 그림 상에는 왜 초록색pod가 4번째 pod에 있냐면,

# kubectl drain node-2

위 drain command를 통해, Node-2에 속한 pod들을 다른 Node로 이동시킨 것이다.

* drain: 해당Node에서 실행 중인 pod들을 다른 곳으로 이동시키는 명령어

 

직접 수행해보자.

$ kubectl get nodes
NAME                 STATUS    ROLES     AGE       VERSION
docker-for-desktop   Ready     master    4d        v1.10.3


$ kubectl drain docker-for-desktopnode
"docker-for-desktop" cordonederror: unable to drain node "docker-for-desktop", aborting command...There are pending nodes to be drained:docker-for-desktoperror: DaemonSet-managed pods (use --ignore-daemonsets to ignore): kube-proxy-4s52d
우선 kubectl drain을 해보면 다음처럼 에러가 납니다. 데몬셋으로 떠 있는 포드가 존재하기 때문입니다.
// DaemonSet의 경우 drain을 사용할 경우 반드시 아래 옵션을 줘야한다.


** --ignore-daemonsets=true 옵션을 주고 다시 실행하면 정상적으로 실행되는걸 확인할 수 있습니다.
$ kubectl drain docker-for-desktop --ignore-daemonsets=true
node "docker-for-desktop" already cordonedWARNING: Ignoring DaemonSet-managed pods: kube-proxy-4s52dpod "compose-api-6fbc44c575-k6fz8" evictedpod "compose-7447646cf5-w4mzb" evictedpod "kubernetes-simple-app-57585656fc-nvkxm" evictedpod "kube-dns-86f4d74b45-dt5rb" evictednode "docker-for-desktop" drained

출처: 
https://arisu1000.tistory.com/27845 [아리수]

출처:  https://arisu1000.tistory.com/27845  [아리수]

 

그럼 cordon 명령어는 뭘까?

* cordon: 해당 노드에 더이상 pod들이 scheduling되지 않게 하는 것(존재하던 pod는 유지)

$ kubectl get nodes
NAME                 STATUS    ROLES     AGE       VERSION
docker-for-desktop   Ready     master    4d        v1.10.3

 

$ kubectl cordon docker-for-desktop

node "docker-for-desktop" cordoned

 

$ kubectl get nodes

NAME                 STATUS                     ROLES     AGE       VERSION

docker-for-desktop   Ready,SchedulingDisabled   master    4d        v1.10.3

$  kubectl uncordon docker-for-desktop// scheduling되게 다시 변경

그럼 새로운 pod가 생성될 때, 해당 node에는 scheduling이 되지 않는다.

그리고, cordon 속성을 제거하거나 / drain 속성을 풀려면 'uncordon'을 수행하면 된다.

 kubectl uncordon docker-for-desktop// scheduling되게 다시 변경



출처: https://arisu1000.tistory.com/27845 [아리수]
출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형
반응형

위와 같이 pod에 특정 환경변수를 설정하려면 어떻게 하는게 편할까?

pod definition YAML에 설정할 수 있다.

 

 

하지만, pod definition file이 많다면 query files 내에 저장된 environment data 관리에 어려움이 있다.
그래서, 이 configuration들을 묶어 pod-definition 파일 밖에서 ConfigMap과 Secrets 파일을 만든다.



1. ConfigMap: 일반적인 plain text를 별도의 파일에 저장. 
  pod가 생성될 때, ConfigMap이 pod 내부로 추가되고, 해당 파일에 있는 환경 변수들을 사용할 수 있다.

 1) ConfigMap의 두 가지 phase

   (1) Create ConfigMaps
      -  imperative way (command로 생성. file 미작성)

         . kubectl create configmap 명령어

# kubectl create configmap <config-name> --from-literal=<key>=<value>
ex. app-config --from-literal=APP_COLOR=blu
                   --from-literal=APP_MOD=prod  (추가로 원하는 속성이 있다면)

 

 

    - Declarative way (file 작성)

      . kubectl create -f  [file Name]
       ex. config-map.yaml 생성

 

 

 

   (2) Inject them into the POD (다른 object들 처럼)
    - (ENV의 경우) "envFrom:" key 추가 
    envFrom:
      - configMapRef:
            name: app-config // 여기에 configmap의 name 넣기

 

 

 - (Single Env의 경우) valueFrom:
 - (Volume의 경우) configMap:

 

 

  * ConfigMap 조회

 

 

2. Kubernetes Secrets

위에서 ConfigMap을 알아봤는데, ConfigMap은 모든 data를 plain 형태로 저장했다.

그런데, id/pw와 같이 민감한 값을 저장해야 한다면 configMap이 적합할까?

 

 

당연히 아니다.

그래서, 이런 민감한 정보들은 Screts 파일에 암호화하여 저장한다.

Secrets 역시 2가지 Phase로 나눠진다.

1) CREATE Secret
2) Inject them into the POD 

 

하나씩 알아보자.

 

먼저 이 역시 명령형(imperative)와 선언형(Declarative)로 나뉜다.

 

 

먼저 명령형 부터.

# kubectl create secret generic <secret-name> --from-literal=<key>=<value>
ex. kubectl create secret generic \
       app-secret --from-literal=DB_Host=mysql app-secret
                      --from-literal=DB_User=root ...

설정이 많아지면, file로 가져오는 명령어도 있다.
# kubectl create secret generic <secret-name> --from-file=<path-to-file>
ex. kubectl create secret generic \ app-secret --from-file=app_secret.properties

 

다음은 역시, 선언형이다.

kubectl create -f secret-data.yaml
 * 단, secret은 민감한 정보를 다루기 때문에, plain text말고 encoded된 형식으로 "직접" 작성해야함.

 

 

어떻게 encoded된 형식으로 변환?   'echo -n' 명령어 사용!

# echo -n 'mysql' | base64 
# echo -n 'root' | base64 

그럼 decode 방법은!?
#'echo -n 'bXlzcWw=' | base64 --decode 

 

 

2) Inject them into the POD 
 ConfigMap과 동일하게 아래와 같은 key를 추가한다

- (ENV의 경우) "envFrom:" key 추가 
    envFrom:
      - secretRef:
            name: app-config // 여기에 configmap 이름 넣기

 


 - (Single Env의 경우) valueFrom: secretKeyRef:
 - (Volume의 경우) secretName:





생성된 secrets을 조회해보면, describe에서도 data는 숨겨지는 것을 볼 수 있다.

 

위는 정말 secret파일이 container에 포함되는지 확인하는 명령.

 

 

* Note)
# explain kubectl explain [--recursive=false] [flags]
파드, 노드, 서비스 등의 다양한 리소스에 대한 문서를 출력한다.
출처: https://kubernetes.io/ko/docs/reference/kubectl/overview/

controller-0:~$ kubectl explain pods --recursive | grep Volume -A3

 

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형
반응형

 

컨테이너는 OS를 점유하지 않고 특정한 task나 process를(ex.webserver, app server, db) 실행하기 때문에,
task가 완료되면 컨테이너는 exit 된다. 


즉, 컨테이너는 프로세스가 동작중일 때만 살아있는다.
예를 들어, 컨테이너 내부의 web server가 중지되거나 crash되면, 컨테이너도 종료된다. 
(위 그림을 보면, ubuntu를 run했으나 곧내 Exit 된걸 볼 수 있다)

 

 

 

그럼, 컨테이너 내에서 어떤 프로세스가 구동될지는 누가 정의할까?

docker file을 보면(여기서는 nginx), 'CMD'(=command)라는 instruction을 볼 수 있다.
즉, 해당 프로그램이 컨테이너가 시작되면, 컨테이너 내에서 구동될 것이라는 것을 의미한다. 
mysql에는 mysqld가 있다.

 

 

Ubuntu 파일의 docker file도 보면, 'bash' 라는 default cmd가 있다.
그런데, bash는 webserver와 db와 같은 프로세스가 아니라 쉘이다.
* shell: 터미널로부터 input을 listen. 없으면 종료.

우리가 우분투 컨테이너를 생성할 때,

docker는 우분투 img로부터 container를 생성하고, bash program을 구동한다.
그런데, 기본적으로 docker는 터미널이 포함되어 있지 않기 때문에,

bash program은 터미널을 찾을 수 없고, 이내 프로세스는 시작되자마자 종료될 것이다. 

 

1. 'docker run' command 

: 컨테이너가 생성되자마자 종료되지 않기 위해서는 어떻게 해야할까?

sleep 5초를 줘보자.
# docker run ubuntu sleep 5 // ubuntu 컨테이너를 시작할 때, sleep program을 함께 구동, 5초간 기다렸다가 exit

 

 

* 그런데 이것은 일시적인데... 어떻게 영구적으로 적용할까?
새 커멘드를 만들면 된다.

docker build -t ubuntu-sleeper
docker run ubuntu-sleeper

단, CMD에는 항상 키와 값을 따로따로 써줘야 한다.

ex. ["sleep", "5"]  // ["sleep 5"]하면 안됨

 

 

그럼 value(값)를 바꾸고 싶다면?
ENTRYPOINT로 명령어를 수행하고, CMD를 통해 매개변수 값을 입력한다.


런타임에 ENTRYPOINT를 sleep2.0으로 수정하고 싶다면? 
entry point option을 사용해서 override할 수 있음.
 # docker run --entrypoint sleep2.0 ubuntu-sleeper 10

그럼 위의 설정은 YAML에 어떻게 입력 할까?
args:가 CMD에 있는 매개변수 값으로, args에 value를 입력해준다.
그리고 ENTRYPOINT가 command: 이다. (Entrypoint를 수정하고 싶다면, YAML에 위와 같이 "sleep2.0"으로 바꿔도 된다)

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형
반응형

1. Monitoring: K8s에서는 어떻게 Node간 Resource를 체크할까?

위 Prometheus, Elastic Stack 등 Monitoring에 대한 OpenSource를 사용한다.

 

 

 

세부 동작 과정은, Node의 Kubelet 안에  cAdvisor라는 subcomponent가 있다.

cAdvisor는 pod로부터 성능 metrics들을 조회하고, kubelet API를 통해 이것을 metric server로 노출시킨다.

 

 

메트릭 서버는 위와 같은 명령어로 설치하며, 설치 후에는 kubectl top node, top pod 명령어를 통해

각 node, pod의 사용량을 알 수 있다.

 

 

 

 

그럼, Logging에 대해서도 알아보자.

2. Logging:

Docker의 경우 이미 app에 의해 standard output으로 event를 생성하고 있다. 

docker container를 background 모드로 사용하고 싶다면, -d 옵션을 사용하면 된다.

이러면 log를 볼 수 없다.

 

만약 로그를 보고 싶다면, container ID를 이용한 logs -f 옵션을 사용하면 된다.

docker logs -f [Container ID]

 

 

그럼 K8s를 알아보자.

일단 위와 동일한 image를 사용하여 pod를 하나 만든다. 

pod가 생성된 후에는, kubectl logs -f event-simulator-pod 옵션을 통해 log를 볼 수 있다.

(-f 옵션은 docker cmd처럼 라이브로 로그를 보겠다는 의미.)

 

 

그런데, 이 로그는 pod 내 container마다 다르다.

pods는 여러 개의 docker container를 가질 수 있으므로, 'image-processor'라는 추가적인 컨테이너를 만들어 본다.

 

그러면, logs를 조회할 때도 2개의 container를 한 번에 조회할 수 있다.

# kubectl logs -f event-simulator-pod event-simulator

kubectl logs -f [Container ID 1] [Container ID 2] ...

 

 

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형
반응형

K8s에는 Scheduler도 1개 이상을 생성할 수 있다.

왜 1개 이상의 생성이 필요할까?

 

이전에 Taint&Toleration, Affinity, Selector를 이용하여 Scheduler가 특정 pod에 특정 Node를 생성하게 했다.

그런데, 복합적인 절차들이 맞물려서, 여러 개의 Schedule 조건도 필요할 수 있다.

예를 들어, 이 pod는 특정 작업이 끝난 후 생성되게 해달라. 등의 작업 말이다.

 

그래서 k8s에는 Multiple Scheduler를 생성한다. 

Deploy는 위와 같은 방법으로 진행한다.

YAML파일을 하나 더 만들어서, spec: containers: command 아래에 2개의 값을 별도로 추가해준다.

-- leader-elect=false
-- scheduler-name=my-custom-scheduler 

 

 

그리고 kubectl create -f YAML파일을 통해 각 Scheduler를 생성한다.

이제부터는 pod에도 어떤 scheduler를 쓸 건지 'schedulerName'을 명시해줘야 한다. 

(명시해주지 않으면, 이전에 설정했던 -- leader-elect=true 값을 가진 scheduler가 default로 설정될 것이다.)

 

 

이후 pod를 생성해서 k8s의 events를 조회해보면,

my-custom-scheduler를 통해 생성된 pod의 event를 확인할 수 있다.

 

 

 

출처: Udemy 사이트의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의

반응형

+ Recent posts