Kubernetes 101
Kubernetes란?
무엇인가: 여러개의 장비 위에 여러개의 컨테이너를 돌리고 있는 시스템을 위해 사용 왜 사용하는가: 다른 이미지를 가지고 있는 여러개의 컨테이너를 돌려야할 때 사용
과정
Minikube로 설치
kubectl: 노드에 있는 컨테이너 관리 (k8s master와 커뮤니케이션) minikube: VM 자체를 관리 (해당 VM에 싱글 노드 실행)
- kubectl 설치: https://kubernetes.io/docs/tasks/tools/install-kubectl/
- Virtualbox 설치: https://www.virtualbox.org/wiki/Downloads
- minikube 설치: https://github.com/kubernetes/minikube/releases
- Minikube가 제공하는 Kubernetes 기능들 DNS / NodePorts / ConfigMaps & Secrets / Dashboards / Container Runtime(Docker) / Container Network Interface 활성화 / Ingress
설치
MacOS 기준
- kubectl:
brew install kubectl
- Virtualbox 설치
- minikube:
brew cask install minikube
- minikube 시작:
minikube start
- k8s master 상태 확인:
kubectl cluster-info
목표
Get the multi-client image running on our local kubernetes cluster running as a container
실행
$ minikube start
Starting local Kubernetes cluster...
Running pre-create checks...
Creating machine...
Starting local Kubernetes cluster...
$ kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.10 --port=8080
deployment.apps/hello-minikube created
$ kubectl expose deployment hello-minikube --type=NodePort
service/hello-minikube exposed
# We have now launched an echoserver pod but we have to wait until the pod is up before curling/accessing it
# via the exposed service.
# To check whether the pod is up and running we can use the following:
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-minikube-3383150820-vctvh 0/1 ContainerCreating 0 3s
# We can see that the pod is still being created from the ContainerCreating status
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-minikube-3383150820-vctvh 1/1 Running 0 13s
# We can see that the pod is now Running and we will now be able to curl it:
$ curl $(minikube service hello-minikube --url)
Hostname: hello-minikube-7c77b68cff-8wdzq
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=172.17.0.1
method=GET
real path=/
query=
request_version=1.1
request_scheme=http
request_uri=http://192.168.99.100:8080/
Request Headers:
accept=*/*
host=192.168.99.100:30674
user-agent=curl/7.47.0
Request Body:
-no body in request-
$ kubectl delete services hello-minikube
service "hello-minikube" deleted
$ kubectl delete deployment hello-minikube
deployment.extensions "hello-minikube" deleted
$ minikube stop
Stopping local Kubernetes cluster...
Stopping "minikube"...
Docker Compose와의 비교
- Docker Compose
- 각각의 엔트리는 docker-compose로 하여금 이미지를 빌드하도록 할 수 있다.
- service 안에 있던 nginx / worker / client와 같이 각각의 엔트리는 생성하고자 하는 컨테이너를 나타낸다.
- 각각의 엔트리들은 네트워크 필요요소를 정의한다. (port mapping etc…)
- Kubernetes
- 모든 이미지가 다 빌드 되어 있는 상태
- 여러개의 config 파일이 있으며, 각각의 config 파일은 Object 하나당. (Object가 꼭 container는 아니다)
- Networking은 모두 세팅을 별도로 해줘야 한다.
Kubernetes로 시작하기
mkdir simplek8s
- Pod란: Container들의 그룹핑 (k8s에는 container만 만든다는 것이 없다. 최소 단위가 Pod)
-
Pod에 담아야 하는 항목들: 굉장히 결합도가 높은 container들 끼리의 묶음. 정말 묶지 않으면 안될 정도
-
Service란: k8s cluster의 네트워킹 설정
- ClusterIP / NodePort / LoadBalancer / Ingress
- NodePort란: Container를 외부에 노출 (개발용도로만 적합, 프로덕션에서는 되도록 사용하지 않음)
client-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: client-pod
labels:
component: web
spec:
containers:
- name: client
image: stephengrider/multi-client
ports:
- containerPort: 3000
client-node-port.yaml
apiVersion: v1
kind: Service
metadata:
name: client-node-port
spec:
type: NodePort
ports:
- port: 3050
targetPort: 3000
nodePort: 31515
selector:
component: web
- label matching이 되어야 하기 때문에,
labels
항목과selector
항목의 key value가 맞어야 한다.
NodePort Service의 구성
- port:
multi-client
pod를 필요로 하는 다른 pod - targetPort:
multi-client
pod - nodePort: 30000-32767 사이의 랜덤포트 (외부 머신에서 접속). 포트를 별도로 지정하지 않으면 랜덤으로 들어간다.
kubectl을 이용하여 Pod 올리기
kubectl apply -f (filename)
- apply: cluster의 현재 설정을 변경
- -f (filename): 설정이 변경될 파일 명칭 지정
kubectl get pods
: pod list
kubectl get services
: service list
kubectl get pods
의 결과물을 가지고 localhost:(nodeport)로 접속하고자 하면, 안된다.
kube-proxy
를 통해서 해당 VM에 접근해야하기 때문이다.
minikube가 그 정보를 가지고 있기 때문에 minikube ip
를 입력하여 ip주소를 가져온 뒤 사용하면 된다.
ex) 192.168.99.100:31515
minikube ssh
: minikube 환경에 접속
Deployment file이 적용되면 master로 전송된다. (kube-apiserver). master(kube-apiserver)는 deployment file을 읽은 뒤 작업을 수행한다.
용어 정리
- Kubernetes: 컨테이너화된 앱을 배포
- Nodes: Container들을 실행시키는 개별 머신 (혹은 VM)
- Masters: Node를 managegㅏ기 위한 프로그램을 갖추고 있는 개별 머신 (혹은 VM)
- Kubernetes는 이미지를 빌드하지 않음. 다른 곳에서 가져 옴
- Deploy를 하기 위해서는, master에 deploy 설정 파일을 전달한다.
- Master는 예상되는 상태에 부응하기 위해 끊임없이 동작한다.
declarative vs imperative deployment
설정 변경의 기준
kubernetes 설정 파일의 경우, name
과 type
항목을 기준으로 설정 파일을 업데이트 한다.
두 값들이 같을 경우, 다른 항목의 변경은 덮어쓰기 형식으로 적용된다. (image, toleration, activeDeadlineSeconds와 같은 지표들만 변경이 가능하다)
객체에 대한 상세 정보 가져오기
kubectl describe (type: eg. pods) (name: client-pod)
변경할 수 없는 Pod 설정을 변경하는 방법
-
Deployment: 동일한 Pods들을 관리한다. 모두 동일한 설정값을 가지고 있으며, 정확한 숫자가 존재하도록 관리한다.
- Pod 대신에 사용할 수 있다. Pods는 일반적으로 프로덕션 환경에서 잘 사용되지 않는다.
- Pod들의 상태를 모니터링하고, 필요시 업데이트도 진행한다.
Pod Template을 기준으로 Pod를 생성한다.
기존 설정 파일 삭제
kubectl delete -f (config file)
상당히 명령적인 방식인데 (선언적인 방식과 반대인), 일단 삭제할 때는 이 방법 밖엔 없다.
Deployment 가져오기
kubectl get deployments
- DESIRED: deployment 설정에서 설정한 replica 숫자
- CURRENT: 현재 돌아가는 Pod 수
- UP-TO-DATE: 설정 파일을 변경하면 일시적으로 기존의 Pod들이 out-of-date 상태가 된다. 그러면 숫자가 떨어졌다가, 설정이 반영되면 다시 올라온다.
- AVAILABLE: 잘 돌아가고 있는 Pod의 수
Deployment에 대해
내용이 변경되면 기존의 Pod를 삭제하고 새로운걸 띄운다.
Service는 왜 사용할까?
모든 Pod들은 다 개별적인 내부 IP를 가져간다. 내부 IP는 어떤 방식으로던 간에 변경될 수 있다. Pod는 유기적이기 때문에 언제 사라질 수도, 교체될 수도 있다. 이렇게 되면 IP는 변경된다.
- 결론: EIP쓰는 이유와 같다. Service는 Pod를 Selector를 기준으로 모니터링하고, 포트를 매핑한다.
Deploy시 image 버전 업데이트
단순히 latest는 자동으로 업데이트 되지 않는다. (kubernetes issue #33664 번 참조) 그렇기 때문에, kubectl 명령어를 통해 deployment가 새로운 이미지 버전을 사용하도록 강제한다.
- docker build를 먼저 진행하자
docker build -t immigration9/multi-client:v2 ./
docker push immigration9/multi-client:v2
- kubectl에 최신 이미지를 사용하도록 명령하자
kubectl set image deployment/client-deployment client=immigration9/multi-client:v2
kubectl set (변경하고자 하는 속성. eg. image) (객체 타입. eg. deployment) / (객체 이름) (컨테이너명)=(풀 이미지명)
이제 kubectl get pods
를 하면 이미지가 업데이트 되며 Pod들이 재생성 된 것을 확인할 수 있다.