Kubernets 클러스터를 구성하려고 한다. Minikube라고 로컬에 Kubernetes를 설치할 수 있는 애플리케이션이 있는 것 같기는 한데, 학습이나 테스트 용도 정도로 사용하는 것 같다. 내가 원하는 건 실제 환경에서 바로 써먹을 수 있는 기술을 익히는 거다. 그래서 VirtualBox 기반으로 클러스터를 구성하기로 했다.
하나의 Kubernetes Master와 3개의 Kubernets Node로 구성하기로 했다. Kubernetes의 구성요소는 Kubernetes overview 문서를 참고하자.
VirtualBox 테스트 환경을 위해서 vboxnet0네트워크를 만들었다. 이 네트워크는 192.168.56.0/24 서브넷을 가지며 게이트웨이는 192.168.56.1 이다. 인터넷으로 나갈 수 있어야 하므로 masquerade 구성을 했다.
kubeadmin init명령을 실행하면, 현재 노드를 kubernetes master로 설정할 수 있다. 그 전에 kubenetes 네트워크를 먼저 선택하기로 했다. Kubenetes는 CNI를 이용해서 다양한 종류의 컨테이너 네트워크를 애드온 형식으로 올릴 수 있다. Calico, Canal, Flannel, Kube-router, Romana, Weave Net 등의 컨테이너 네트워크를 지원하는데, 나는 Kube-router를 설치하기로 했다. 왜냐면 "가장 쉬울 것 같아서"다.
Kube-router를 설치하기 위해서는 /proc/sys/net/bridge/bridge-nf-call-iptables 값을 1로 해야 한다.
# sysctl net.bridge.bridge-nf-call-iptables=1
kubeadmin init를 마스터노드를 설정했다. 이때 kube-router를 설정하기 위해서--pod-network-cidr 플래그도 함께 실행했다.
# kubeadmin init --pod-network-cidr 10.100.0.0/16
[init] using Kubernetes version: v1.11.2
[preflight] running pre-flight checks
I0814 20:14:03.322499 20387 kernel_validator.go:81] Validating kernel version
I0814 20:14:03.322796 20387 kernel_validator.go:96] Validating kernel config
...... // 생략
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join 192.168.56.2:6443 --token p0qlr7.zov9st9zfq7c07va --discovery-token-ca-cert-hash sha256:ced8b2f88b5e4027ef0e2d96565e607eed5f08c6b830be5861c6d32287ce5c6e
성공적으로 실행하고 나면, 클러스터를 이용하기 위한 가이드가 나온다. 먼저 kubernetes를 위한 설정파일을 복사한다.
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
kubemaster Ready master 45m v1.11.2
kubenode-01 Ready <none> 1m v1.11.2
kubenode-02 Ready <none> 18s v1.11.2
kubenode-03 Ready <none> 12s v1.11.2
hello world service 실행
클러스터에 hello world 애플리케이션을 배포해보기로 했다.
kubectl run hello-world --replicas=2 --labels="run=load-balancer-example" --image=gcr.io/google-samples/node-hello:1.0 --port=8080
kubernetes의 최소 배포단위는 Pod다. Pod는 컨테이너의 그룹으로 예를 들어 wordpress Pod라면 Apache+PHP 컨테이너와 Mysql 컨테이너 로 구성이 될 것이다. 이 Pod에 있는 컨테이너들은 하나의 물리서버에 위치한다. kubectl을 이용해서 이런 Pod를 만들 수 있다. Pod가 하나의 물리서버에만 위치하므로 안전하게 구성하기 위해서는 2개 이상의 Pod를 만들어서 배포히야 한다. --replicas 로 복제할 Pod의 갯수를 설정 할 수 있다. 이 예제의 경우 2개의 Pod가 만들어질 것이다. 확인해보자.
# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-86cddf59d5-h5kjd 1/1 Running 0 33m
hello-world-86cddf59d5-hwg64 1/1 Running 0 33m
kubectl descript를 이용해서 pod의 자세한 정보를 확인해보자.
# kubectl describe pod hello-world
Name: hello-world-86cddf59d5-h5kjd
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: kubenode-01/192.168.56.101
Start Time: Tue, 14 Aug 2018 21:07:19 +0900
Labels: pod-template-hash=4278891581
run=load-balancer-example
Annotations: <none>
Status: Running
IP: 10.100.1.3
Controlled By: ReplicaSet/hello-world-86cddf59d5
Containers:
hello-world:
Container ID: docker://99f8da08ca49730a75d613ffb7cbf369232cf85b16a1ea844c6c4cbcdcd531e1
Image: gcr.io/google-samples/node-hello:1.0
Image ID: docker-pullable://gcr.io/google-samples/node-hello@sha256:d238d0ab54efb76ec0f7b1da666cefa9b40be59ef34346a761b8adc2dd45459b
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 14 Aug 2018 21:07:43 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-85zck (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-85zck:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-85zck
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 37m default-scheduler Successfully assigned default/hello-world-86cddf59d5-h5kjd to kubenode-01
Normal Pulling 37m kubelet, kubenode-01 pulling image "gcr.io/google-samples/node-hello:1.0"
Normal Pulled 36m kubelet, kubenode-01 Successfully pulled image "gcr.io/google-samples/node-hello:1.0"
Normal Created 36m kubelet, kubenode-01 Created container
Normal Started 36m kubelet, kubenode-01 Started container
Name: hello-world-86cddf59d5-hwg64
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: kubenode-02/192.168.56.102
Start Time: Tue, 14 Aug 2018 21:07:19 +0900
Labels: pod-template-hash=4278891581
run=load-balancer-example
Annotations: <none>
Status: Running
IP: 10.100.2.2
Controlled By: ReplicaSet/hello-world-86cddf59d5
Containers:
hello-world:
Container ID: docker://59edc50b249f5ae64e38e1550825e0d47a15523a1949ed24f9edf15a53e6841f
Image: gcr.io/google-samples/node-hello:1.0
Image ID: docker-pullable://gcr.io/google-samples/node-hello@sha256:d238d0ab54efb76ec0f7b1da666cefa9b40be59ef34346a761b8adc2dd45459b
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 14 Aug 2018 21:07:44 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-85zck (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-85zck:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-85zck
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 37m default-scheduler Successfully assigned default/hello-world-86cddf59d5-hwg64 to kubenode-02
Normal Pulling 37m kubelet, kubenode-02 pulling image "gcr.io/google-samples/node-hello:1.0"
Normal Pulled 36m kubelet, kubenode-02 Successfully pulled image "gcr.io/google-samples/node-hello:1.0"
Normal Created 36m kubelet, kubenode-02 Created container
Normal Started 36m kubelet, kubenode-02 Started container
Pod의 이름, 실행 중인 노드, IP, Events, Volume 등 중요 정보들을 확인 할 수 있다. 특히 Pod가 제대로 실행되지 않을 때 Events에 있는 내용을 이용해서 Pod를 디버깅 할 수 있다.
Pod는 단일한 서버에 있으므로 실제 배포(deployment)할 때는 하나 이상의 복제를 가지는 ReplicaSet으로 배포한다. 이 Pod와 ReplicaSet으로 이루어진 배포 객체를 Deployments라고 한다. kubectl get deployments 명령을 이용해서, 몇개의 복제를 요청했는지, 몇개의 복제를 사용 할 수 있는지를 확인 할 수 있다.
# kubectl get deployments hello-world
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-world 2 2 2 2 3m
# kubectl describe deployments hello-world
Name: hello-world
Namespace: default
CreationTimestamp: Tue, 14 Aug 2018 21:07:19 +0900
Labels: run=load-balancer-example
Annotations: deployment.kubernetes.io/revision=1
Selector: run=load-balancer-example
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: run=load-balancer-example
Containers:
hello-world:
Image: gcr.io/google-samples/node-hello:1.0
Port: 8080/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: hello-world-86cddf59d5 (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 4m deployment-controller Scaled up replica set hello-world-86cddf59d5 to 2
이렇게 해서 배포 객체까지 만들었다. 이것을 외부에 서비스하기 위해서는 서비스 객체(service object)를 만들어야 한다. MSA(Microservice architecture) 모델을 따르는 애플리케이션들은 하나 이상의 Pod로 구성이 된다. 이들 Pod는 물리적으로 떨어져 있는데, Service로 묶어 줌으로써 하나의 서비스 단위를 만들 수 있다. 예를 들어 프론트엔드와 데이터베이스 백앤드 두 개의 Pod가 있다고 가정해보자. 프론트엔드 Pod는 데이터베이스 Pod를 사용해야 할 것이다. 그러기 위해서는 프론트엔드에서 백엔드 Pod를 찾아서(Service discovery) 연결 할 수 있어야 한다. Service를 이용해서 이런 일들을 할 수 있다.
Contents
Kubernets 클러스터 구성하기
클러스터 구성 환경
docker 설치
kubeadm
hello world service 실행
정리
관련 문서
Recent Posts
Archive Posts
Tags