Commit 2c32e071 authored by JooHan Hong's avatar JooHan Hong

k8s, scale,deployment update

parent 5a247c78
Pipeline #5219 passed with stages
in 44 seconds
......@@ -11,9 +11,10 @@
| 1 | Cluster 운용상 비교 및 검토 | [GO](./CLUSTER/) | |
| 2 | Service Deploy(**Swarm**)에 대한 비교 및 검토| [GO](./SERVICE/SWARM/) | |
| 3 | Service Deploy(**K8s**)에 대한 비교 및 검토| [GO](./SERVICE/K8S/) | |
| 4 | Network 구조에 대한 비교 및 검토| [GO](./NETWORKING/) | |
| 5 | Storage 구조에 대한 비교 및 검토 | [GO](./STORAGE/) | |
| 6 | 이 외 비교 및 검토 | [GO](./MISC/) | |
| 4 | Auto Scaling(**K8s**)에 대한 검토| [GO](./SERVICE/SCALE/) | |
| 5 | Network 구조에 대한 비교 및 검토| [GO](./NETWORKING/) | |
| 6 | Storage 구조에 대한 비교 및 검토 | [GO](./STORAGE/) | |
| 7 | 이 외 비교 및 검토 | [GO](./MISC/) | |
# Overview
......
[![logo](https://www.hongsnet.net/images/logo.gif)](https://www.hongsnet.net)
# K8s Service Deploy에 대한 비교 및 검토
- **Pod Deployment**에 대한 검증을 수행한다.
- **Service Expose Network**에 대한 검증을 수행한다.
# hello-world (nodejs) Service
> Service Deploy를 검증하는 간단한 nodejs 컨테이너
> Container Image : registry.hongsnet.net/joohan.hong/docker/nodejs:latest
# K8s
> URL : https://k8s-demo.freehongs.net
## Dockerfile
```bash
# cat Dockerfile
FROM node
MAINTAINER Hongs <master@hongsnet.net>
RUN mkdir -p /usr/src/app
COPY index.js /usr/src/app
EXPOSE 8080
CMD ["node", "/usr/src/app"]
```
```bash
# cat index.js
var http = require('http');
var os = require('os');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
console.log(req.socket.localAddress)
res.end(`<h1>Docker Container ID -> ${os.hostname()}</h1><br><h1>Server IP -> ${req.socket.localAddress}</h1><h1>Client IP -> ${req.socket.remoteAddress}</h1><br>Container Tag -> Update_20200916`);
}).listen(8080);
```
## Object의 생성
- **Deployment**
```python
# cat hello-world.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: k8s-verify
name: hello-world
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: k8s-verify
template:
metadata:
labels:
app: k8s-verify
spec:
containers:
- image: registry.hongsnet.net/joohan.hong/docker/nodejs:latest
#imagePullPolicy: Always
imagePullPolicy: IfNotPresent
name: hello-world
ports:
- containerPort: 8080
nodeSelector:
key: worker
```
- **Service**
```python
# cat hello-world_service.yaml
apiVersion: v1
kind: Service
metadata:
name: hongsnet
spec:
type: NodePort
selector:
app: k8s-verify
ports:
- port: 8080
targetPort: 8080
nodePort: 32000
```
- **Execute**
```bash
# kubectl apply -f hello-world.yaml
# kubectl apply -f hello-world_service.yaml
```
## K8s Cluster 구성
다음과 같이 4 대로 구성했다.
* master : cube01 (172.24.0.222)
* worker01 : cube02 (172.16.0.223)
* worker02 : cube03 (172.16.0.224)
* worker03 : cube04 (172.16.0.225)
구성된 내역은 다음과 같다.
```bash
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
cube01 Ready control-plane,master 24h v1.20.4
cube02 Ready <none> 24h v1.20.4
cube03 Ready <none> 24h v1.20.4
cube04 Ready <none> 24h v1.20.4
```
k8s의 경우 Swarm과 달리 **Overlay 네트워크**가 기본적으로 제공되지않고, **Network Plugin을 Addon하게 설치**해야한다. 여러가지 Plugin을 제공하며, 여기서는 **Flannel**을 사용한다.
```bash
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.254.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
```
## Pod Check
```bash
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-world-7856df46fd-5ws4b 1/1 Running 0 23m 10.244.254.2 cube03 <none> <none>
hello-world-7856df46fd-cgq88 1/1 Running 0 23m 10.244.254.3 cube02 <none> <none>
hello-world-7856df46fd-jmrfc 1/1 Running 0 23m 10.244.254.3 cube03 <none> <none>
hello-world-7856df46fd-jw4gs 1/1 Running 0 23m 10.244.254.2 cube02 <none> <none>
hello-world-7856df46fd-z25bl 1/1 Running 0 23m 10.244.254.4 cube02 <none> <none>
```
## Service Check
```bash
# kubectl get services hongsnet
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hongsnet NodePort 10.98.254.117 <none> 8080:32000/TCP 25m
```
> 네트워크 구성중 "NodePort"를 사용하는 이유는 바로 아래의 내용을 참조한다.
## `Service` External Network 노출 방식
각 Pod들이 고유의 IP를 갖고 있기는 하지만, 그 IP들은 서비스의 도움없이 클러스터 외부로 노출되어질 수 없다. 따라서 다음 방식을 통해 내부 또는 외부로의 노출을 검토해야 한다.
1. **CluserIP**
ClusterIP는 `기본 값`이며, 클러스터 내에서 내부 IP 에 대해 서비스를 노출해준다. 이 방식은 오직 클러스터 내에서만 서비스가 접근될 수 있도록 해준다.
2. **NodePort** <= Pick
NAT가 이용되는 클러스터 내에서 각각 선택된 노드들의 동일한 포트에 서비스를 노출시켜준다. <NodeIP>:<NodePort>를 이용하여 클러스터 외부로부터 서비스가 접근할 수 있도록 해준다. **ClusterIP의 상위 집합**이다.
3. **LoadBalancer**
지원 가능한 경우 기존 클라우드에서 외부용 로드밸런서를 생성하고 서비스에 고정된 공인 IP를 할당해준다. **NodePort의 상위 집합**이다.
4. **ExternalName**
이름으로 **CNAME 레코드**를 반환함으로써 임의의 이름(스펙에서 externalName으로 명시)을 이용하여 서비스를 노출시켜준다. 프록시는 사용되지 않는다. 이 방식은 **kube-dns 버전 1.7 이상에서 지원 가능**하다.
> 검증에서는 NodePort를 사용하며, 포트는 **32000/tcp**으로 고정한다. 왜냐하면, Pod 재실행 시 이 포트는 `Random`(기본 값: 30000~32768)하게 변경되기 때문이며, 외부 접속은 Apache Proxy를 사용한다. 이는 현재 Swarm 환경과 거의 동일한 구성이다.
```plaintext
Client -> Proxy(Apache) -> Worker01
-> Worker02
-> Worker03
```
# Pod의 확장
위의 5개의 Replica로 구성된 상태에서 다음과 같이 **2 개의 Replica를 추가해서 확장**해 보자.
```bash
# kubectl scale deployment/hello-world --replicas=7
deployment.apps/hello-world scaled
```
그럼 다음과 같이 총 7개의 Pod가 실행되고 있는 것을 볼 수 있다.
```bash
# ./kube-podlist.sh
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-world-7856df46fd-6c286 1/1 Running 0 15s 10.244.254.12 cube02 <none> <none>
hello-world-7856df46fd-8j5r7 1/1 Running 0 15s 10.244.254.13 cube02 <none> <none>
hello-world-7856df46fd-lkswt 1/1 Running 0 25m 10.244.254.10 cube02 <none> <none>
hello-world-7856df46fd-lxsjt 1/1 Running 0 25m 10.244.254.11 cube02 <none> <none>
hello-world-7856df46fd-mbtkp 1/1 Running 0 25m 10.244.254.9 cube03 <none> <none>
hello-world-7856df46fd-mdqqw 1/1 Running 0 25m 10.244.254.11 cube03 <none> <none>
hello-world-7856df46fd-qxvsl 1/1 Running 0 25m 10.244.254.10 cube03 <none> <none>
```
# Pod의 축소
위의 **7개**의 Pod를 초기 **5개**로 축소해보자.
```bash
# kubectl scale deployment/hello-world --replicas=5
deployment.apps/hello-world scaled
```
그럼, 7개의 Pod 중 2개의 상태가 Terminating 되는 것을 볼 수 있으며, 최종적으로는 5개가 된다.
```bash
# ./kube-podlist.sh
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-world-7856df46fd-6c286 1/1 Terminating 0 104s 10.244.254.12 cube02 <none> <none>
hello-world-7856df46fd-8j5r7 1/1 Terminating 0 104s 10.244.254.13 cube02 <none> <none>
hello-world-7856df46fd-lkswt 1/1 Running 0 27m 10.244.254.10 cube02 <none> <none>
hello-world-7856df46fd-lxsjt 1/1 Running 0 27m 10.244.254.11 cube02 <none> <none>
hello-world-7856df46fd-mbtkp 1/1 Running 0 27m 10.244.254.9 cube03 <none> <none>
hello-world-7856df46fd-mdqqw 1/1 Running 0 27m 10.244.254.11 cube03 <none> <none>
hello-world-7856df46fd-qxvsl 1/1 Running 0 27m 10.244.254.10 cube03 <none> <none>
```
[![logo](https://www.hongsnet.net/images/logo.gif)](https://www.hongsnet.net)
# K8s Auto Scaling에 대한 검토
> HPA(scale-up, scale-down)과 VPA(Resource-up, Resource-down)에 대한 검증을 진행한다.
# Auto Scaling
k8s에서는 **Horizontal Pod Autoscaler**(HPA), **Vertical Pod Autoscaler**(VPA)로 지정한 메트릭을 Controller가 체크하여, 부하에 따라 필요한 Pod의 Replica수가 되도록 자동으로 Pod수를 늘리거나 줄일 수 있는 기술을 지원한다.
- `Pre-Requirement`
k8s에서 Resouce에 대한 현황을 확인하려면, **metric-server가 설치**되어 있어야 한다. 최초의 경우 다음과 같이 설치를 진행한다.
```bash
# git clone https://github.com/kubernetes-sigs/metrics-server
# vi ./metrics-server/manifests/base/deployment.yaml
...중략
containers:
- name: metrics-server
image: gcr.io/k8s-staging-metrics-server/metrics-server:master
imagePullPolicy: IfNotPresent
#22 라인 아래추가
command:
- /metrics-server
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP
```
다음과 같이 설치한다.
```bash
# kubectl apply -k ./metrics-server/manifests/base/
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
```
- **Horizontal Pod Autoscaler**(HPA, 수평)
**HPA**는 metric(System Resource metric)을 관찰한 후 임계치가 넘을 경우 `Pod 개수를 Scale Up 또는 Scale Down`한다. 만약 요구하는 metric에 비해 실행되고 있는 파드의 수가 작다면, 파드의 수를 늘리고(**Scale Up**), 반대의 경우 파드의 수를 줄인다(**Scale Down**). 단, `DaemonSet`과 같이 크기를 조정할 수 없는 경우에는 적용되지 않는다.
먼저 Deployment Object에 **Resource를 제한**한다.
```bash
# cat hello-world.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: k8s-verify
name: hello-world
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: k8s-verify
template:
metadata:
labels:
app: k8s-verify
spec:
containers:
- image: registry.hongsnet.net/joohan.hong/docker/nodejs:latest
#imagePullPolicy: Always
imagePullPolicy: IfNotPresent
name: hello-world
resources:
requests:
cpu: "500m"
limits:
cpu: "500m"
nodeSelector:
key: worker
```
이제 **HPA**의 Object를 다음과 같이 작성한다.
```bash
# cat hello-world_scale.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: k8s-verify-hpa
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: hello-world
minReplicas: 5
maxReplicas: 10
targetCPUUtilizationPercentage: 5
```
> cpu 사용률 평균이 5% 이상일 경우에 Scale Up이 발생된다.
다음은 기능에 대한 **동작검증 결과** 이며, **CPU 부하를 발생**하는 명령은 다음과 같다.
```bash
# while true;do curl localhost:32000;done
```
```bash
# kubectl get hpa --watch
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
k8s-verify-hpa Deployment/hello-world <unknown>/5% 5 10 0 8s
k8s-verify-hpa Deployment/hello-world <unknown>/5% 5 10 5 15s
k8s-verify-hpa Deployment/hello-world 0%/5% 5 10 5 46s
k8s-verify-hpa Deployment/hello-world 2%/5% 5 10 5 76s
k8s-verify-hpa Deployment/hello-world 6%/5% 5 10 5 92s
k8s-verify-hpa Deployment/hello-world 5%/5% 5 10 6 107s <- scale up
k8s-verify-hpa Deployment/hello-world 5%/5% 5 10 6 2m2s
k8s-verify-hpa Deployment/hello-world 4%/5% 5 10 6 2m17s
k8s-verify-hpa Deployment/hello-world 4%/5% 5 10 6 2m33s
k8s-verify-hpa Deployment/hello-world 4%/5% 5 10 6 3m18s
k8s-verify-hpa Deployment/hello-world 4%/5% 5 10 6 3m34s
k8s-verify-hpa Deployment/hello-world 4%/5% 5 10 6 3m49s
k8s-verify-hpa Deployment/hello-world 4%/5% 5 10 6 4m4s
k8s-verify-hpa Deployment/hello-world 1%/5% 5 10 6 4m19s
k8s-verify-hpa Deployment/hello-world 0%/5% 5 10 6 4m35s
k8s-verify-hpa Deployment/hello-world 0%/5% 5 10 6 7m7s
k8s-verify-hpa Deployment/hello-world 0%/5% 5 10 5 7m22s <- scale down
k8s-verify-hpa Deployment/hello-world 0%/5% 5 10 5 9m9s
k8s-verify-hpa Deployment/hello-world 0%/5% 5 10 5 9m24s
```
- **Vertical Pod Autoscaler**(VPA, 수직)
HPA가 파드의 수를 늘리거나 줄여서 스케일링 했다면, **VPA**`Pod의 요청 리소스를 늘리거나 줄여서 스케일링 하는 방식`이다. 단, HPA와 다르게 Pod에 할당된 리소스는 실행 중에 다시 할당할 수 없기 때문에 스케일링 시 **Pod를 재시작하게** 된다.
......@@ -2,14 +2,14 @@
# Service Deploy에 대한 비교 및 검토
> `Swarm과 k8s 모두 Host Mode로 동작되도록 구성`했기 때문에 Replica(set)에 대한 **확장/축소**의 검토는 수행하지 않는다. 단, k8s를 기준으로의 Concept는 아래와 같이 검토를 수행한다.
> `Swarm과 k8s 모두 Host Mode로 동작되도록 구성`했기 때문에 Replica(set)에 대한 **확장/축소**의 검토는 수행하지 않는다. 단, 최초 도입을 검증했던 Swarm 구성에 대한 검증내역은 다음과 같다..
# hello-world (nodejs) Service
> Service Deploy를 검증하는 간단한 nodejs 컨테이너
> registry.hongsnet.net/joohan.hong/docker/nodejs:latest
> Container Image : registry.hongsnet.net/joohan.hong/docker/nodejs:latest
# Docker Swarm
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment