https://kubernetes.io/ko/docs/tutorials/kubernetes-basics/
Tutorial: 쿠버네티스 기초 학습
Assumming that minikube is successfully installed
Deploying app
Create deployment using kubernetes
- pod는 isolated, private network 되어있기 때문에 proxy를 통해 debug, interact 가능하다.
$ minikube start
$ kube kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
# starting proxy
echo -e "\n\n\n\e[92mStarting Proxy. After starting it will not output a response. Please click the first Terminal Tab\n";
kubectl proxy
curl localhost:8001
# set POD_NAME
export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
echo Name of the Pod: $POD_NAME
Anylize app
kubernetes pod
- Pod is abstract concept
kubernetes node
- Each node can have one or more pods
- Each node is controlled by master node
kubectl get - 자원을 나열한다
kubectl describe - 자원에 대해 상세한 정보를 보여준다.
kubectl logs - 파드 내 컨테이너의 로그들을 출력한다
kubectl exec - 파드 내 컨테이너에 대한 명령을 실행한다.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-69fbc6f4cf-pzqcg 1/1 Running 0 6m26s
$ kubectl describe pods
Name: kubernetes-bootcamp-69fbc6f4cf-pzqcg
Namespace: default
Priority: 0
...
# or just simply "kubectl proxy"
$ echo -e "\n\n\n\e[92mStarting Proxy. After starting it will not output a response. Please click the first Terminal Tab\n"; kubectl proxy
Starting Proxy. After starting it will not output a response. Please click the first Terminal Tab
Starting to serve on 127.0.0.1:8001
# or just get pod name from "kubectl get pods"
$ export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-69fbc6f4cf-pzqcg
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
$ kubectl logs $POD_NAME
Kubernetes Bootcamp App Started At: 2020-05-07T15:28:48.194Z | Running On: kubernetes-bootcamp-69fbc6f4cf-pzqcg
# Executing command on the container
$ kubectl exec $POD_NAME -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-69fbc6f4cf-pzqcg
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
NPM_CONFIG_LOGLEVEL=info
NODE_VERSION=6.3.1
HOME=/root
$ kubectl exec -ti $POD_NAME -- bash
root@kubernetes-bootcamp-69fbc6f4cf-pzqcg:/#
$ cat server.js
$ curl localhost:8080
$ exit
https://kubernetes.io/ko/docs/tutorials/kubernetes-basics/expose/expose-intro/
앱 외부로 노출하기
쿠버네티스에서 서비스는 하나의 논리적인 파드 셋과 그 파드들에 접근할 수 있는 정책을 정의하는 추상적 개념이다.
각 pod들은 ip를 가지지만, 이는 서비스를 통해야만 클러스터 외부로 노출이 가능하다. ServiceSpec
에서 type
을 지정하여 다양한 방식으로 노출 가능.
- ClusterIP (기본값) - 클러스터 내에서 내부 IP 에 대해 서비스를 노출해준다. 이 방식은 오직 클러스터 내에서만 서비스가 접근될 수 있도록 해준다.
- NodePort - NAT가 이용되는 클러스터 내에서 각각 선택된 노드들의 동일한 포트에 서비스를 노출시켜준다.
: 를 이용하여 클러스터 외부로부터 서비스가 접근할 수 있도록 해준다. ClusterIP의 상위 집합이다. - LoadBalancer - (지원 가능한 경우) 기존 클라우드에서 외부용 로드밸런서를 생성하고 서비스에 고정된 공인 IP를 할당해준다. NodePort의 상위 집합이다.
- ExternalName - 이름으로 CNAME 레코드를 반환함으로써 임의의 이름(스펙에서 externalName으로 명시)을 이용하여 서비스를 노출시켜준다. 프록시는 사용되지 않는다. 이 방식은 kube-dns 버전 1.7 이상에서 지원 가능하다.
# 서비스 보는 명령어
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
kubernetes
서비스는minikube
가 뜰 때 자동으로 생성되는 service이다.
새로 서비스를 만드려면 expose
명령어를 사용하면 된다. (minikube
는 아직 loadBalancer 옵션을 제공해주지 않는다.)
$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
kubernetes-bootcamp NodePort 10.105.237.31 <none> 8080:31552/TCP 4s
describe
명령어를 사용하여 더 상세한 service의 상태를 확인 가능하다.
$ kubectl describe services/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: app=kubernetes-bootcamp
Annotations: <none>
Selector: app=kubernetes-bootcamp
Type: NodePort
IP: 10.105.237.31
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31552/TCP
Endpoints: 172.17.0.4:8080
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
현재 배정되어 있는 node port를 $NODE_PORT
환경변수에 지정해보자.
$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
echo NODE_PORT=$NODE_PORT
NODE_PORT=31552
이제 minikube ip와 NODE_PORT를 사용하여 외부에서 접속이 가능하다.
$ curl $(minikube ip):$NODE_PORT
Using labels
$ kubectl describe deployments
$ kubectl get pods -l run=kubernetes-bootcamp
$ kubectl get services -l run=kubernetes-bootcamp
# POD_NAME 설정, 그냥 kubectl get pods에서 보고 해도 상관없다.
$ export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
echo Name of the Pod: $POD_NAME
# 이미 app에 label이 등록되어 있다면 --overwrite 가능
$ kubectl label pod $POD_NAME app=v1
Delete services with label
$ kubectl delete service -l run=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 18d
service가 죽었기 때문에 외부 접속이 안된다.
$ curl $(minikube ip):$NODE_PORT
curl: (7) Failed to connect to 192.168.64.4 port 31552: Connection refused
여전히 클러스터에서는 잘 떠있는 것을 볼 수 있음
$ kubectl exec -ti $POD_NAME -- curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-69fbc6f4cf-pzqcg | v=1
앱 스케일링하기
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
kubernetes-bootcamp-69fbc6f4cf 1 1 1 2d21h
$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
kubernetes-bootcamp-69fbc6f4cf 4 4 4 2d23h
$ kube kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 4/4 4 4 2d23h
$ kubectl get pods -o wide
READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubernetes-bootcamp-69fbc6f4cf-7hp7h 1/1 Running 0 94m 172.17.0.6 m01 <none> <none>
kubernetes-bootcamp-69fbc6f4cf-f4g8n 1/1 Running 0 94m 172.17.0.7 m01 <none> <none>
kubernetes-bootcamp-69fbc6f4cf-mxfvx 1/1 Running 0 94m 172.17.0.5 m01 <none> <none>
kubernetes-bootcamp-69fbc6f4cf-pzqcg 1/1 Running 0 2d23h 172.17.0.4 m01 <none> <none>
$ kubectl describe deployments/kubernetes-bootcamp
$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
echo NODE_PORT=$NODE_PORT
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-69fbc6f4cf-pzqcg | v=1
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-69fbc6f4cf-7hp7h | v=1
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-69fbc6f4cf-f4g8n | v=1
curl
을 해보면 할 때마다 로드밸런싱이 되는 것을 볼 수 있다!!
이제 scale down 해보자.
$ kubectl scale deployments/kubernetes-bootcamp --replicas=2
deployment.apps/kubernetes-bootcamp scaled
$ kubectl get deployments/kubernetes-bootcamp
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 2/2 2 2 2d23h
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubernetes-bootcamp-69fbc6f4cf-mxfvx 1/1 Running 0 102m 172.17.0.5 m01 <none> <none>
kubernetes-bootcamp-69fbc6f4cf-pzqcg 1/1 Running 0 2d23h 172.17.0.4 m01 <none> <none>
앱 업데이트하기
"롤링 업데이트"는 파드 인스턴스를 점진적으로 새로운 것으로 업데이트하여 디플로이먼트 업데이트가 서비스 중단 없이 이루어질 수 있도록 해준다
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 2/2 2 2 2d23h
$ kubectl describe deployments/kubernetes-bootcamp
...
Pod Template:
Labels: app=kubernetes-bootcamp
Containers:
kubernetes-bootcamp:
Image: gcr.io/google-samples/kubernetes-bootcamp:v1
Port: <none>
Host Port: <none>
...
위에서 gcr.io/google-samples/kubernetes-bootcamp:v1
이미지를 롤링 업데이트로 배포시켜보자.
$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment.apps/kubernetes-bootcamp image updated
# 바로 pods를 확인하면 기존 pod가 제거되는 것을 볼 수 있다.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-69fbc6f4cf-mxfvx 1/1 Terminating 0 108m
kubernetes-bootcamp-69fbc6f4cf-pzqcg 1/1 Terminating 0 2d23h
kubernetes-bootcamp-b4d9f565-jw76c 1/1 Running 0 9s
kubernetes-bootcamp-b4d9f565-mbg26 1/1 Running 0 3s
# 조금 시간이 지나면 업데이트 된 pod들만 남아있다.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-b4d9f565-jw76c 1/1 Running 0 49s
kubernetes-bootcamp-b4d9f565-mbg26 1/1 Running 0 43s
# 다시 describe deployments를 확인하여 이미지가 업데이트 된 것을 볼 수 있다.
$ kubectl descirbe deployments/kubernetes-bootcamp
...
Pod Template:
Labels: app=kubernetes-bootcamp
Containers:
kubernetes-bootcamp:
Image: jocatalin/kubernetes-bootcamp:v2
...
이제 업데이트가 정상적으로 되었는지 확인해보자
$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=30486
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-b4d9f565-jw76c | v=2
v=2
를 반환하여 업데이트가 잘 되었음을 볼 수 있다.
# rollout 명령어로도 업데이트를 할 수 있다.
$ kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out
이제 v10
으로 업데이트를 해보자.
$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
deployment.apps/kubernetes-bootcamp image updated
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 2/2 1 2 2d23h
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-6b4c55d8fc-fgtwh 0/1 ErrImagePull 0 70s
kubernetes-bootcamp-b4d9f565-jw76c 1/1 Running 0 8m50s
kubernetes-bootcamp-b4d9f565-mbg26 1/1 Running 0 8m44s
뭔가 잘못된 것을 볼 수 있다. ErrImagePull
status 를 볼 수 있다. 상세한 내용 확인을 위해 describe
를 사용해보자.
$ kubectl describe pods
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/kubernetes-bootcamp-6b4c55d8fc-fgtwh to m01
Normal Pulling 55s (x4 over 2m23s) kubelet, m01 Pulling image "gcr.io/google-samples/kubernetes-bootcamp:v10"
Warning Failed 53s (x4 over 2m21s) kubelet, m01 Failed to pull image "gcr.io/google-samples/kubernetes-bootcamp:v10": rpc error: code = Unknown desc = Error response from daemon: manifest for gcr.io/google-samples/kubernetes-bootcamp:v10 not found: manifest unknown: Failed to fetch "v10" from request "/v2/google-samples/kubernetes-bootcamp/manifests/v10".
Warning Failed 53s (x4 over 2m21s) kubelet, m01 Error: ErrImagePull
Normal BackOff 27s (x6 over 2m21s) kubelet, m01 Back-off pulling image "gcr.io/google-samples/kubernetes-bootcamp:v10"
Warning Failed 12s (x7 over 2m21s) kubelet, m01 Error: ImagePullBackOff
...
레파지토리에 v10
이미지가 없어서 생긴 에러였다. rollout
명령어를 사용해서 이전 버전으로 롤백해보자.
$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment.apps/kubernetes-bootcamp rolled back
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-bootcamp-b4d9f565-jw76c 1/1 Running 0 12m
kubernetes-bootcamp-b4d9f565-mbg26 1/1 Running 0 12m
$ kubectl describe pods
...
Containers:
kubernetes-bootcamp:
Container ID: docker://4f726cfe7a828f0fc3f8e6e4a400bcaf763e26fc522490c09da40113e53f84c5
Image: jocatalin/kubernetes-bootcamp:v2
Image ID: docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
Port: <none>
...
이미지를 확인해보면 다시 v2
인 것을 볼 수 있다.
'backend > kubernetes docs' 카테고리의 다른 글
kubernetes docs - Container (0) | 2020.05.22 |
---|---|
kubernetes docs: 클러스터 아키텍쳐 - 컨트롤러 (controller) (0) | 2020.05.18 |
Kubernetes docs: Cluster Architecture - Node (0) | 2020.05.17 |
Kubernetes object - 쿠버네티스 오브젝트 (0) | 2020.05.16 |
쿠버네티스 기본 개념 (kubernetes conecpt) (0) | 2020.05.14 |