본문 바로가기
Development(Web, Server, Cloud)/Cloud : 정리

kubernetes(k8s) 정리 part1

by tonyhan18 2022. 4. 14.
728x90

개념

노란색이 마스터이다. 파란색이 worker node이다.

master node는 api-server/controller/scheduler/key-value store(etcd) 가 존재한다.

worker node는 kubelete/runtime(docker[ containerd] cri-o, podman)/network proxy가 존재한다.

 

그림을 보면 kubelet이 마스터로부터 명령을 받는다.

kubelet이 명령을 받으면 Container Runtime으로 명령을 전달하고 Docker 가 Pod를 만들라는 명령을 전달해준다.

 

만들어진 Pod가 외부 사용자와 접속이 가능하도록 외부와의 연결이 가능하도록 만들어주어야 한다. 이건 Network-Proxy(kube proxy)가 담당하게 된다.

 

weave-net는 내부에서 소통하기 위한 overlay 네트워크이다.

coredns는 우리가 제작시에 각 포드별로 이름을 달아주면 DNS가 알아서 그 컨테이너(포드)로 연결을 시도해준다.

* coredns는 CNI 가 존재하기 전에 작동을 멈추고 있을 수도 있다. 암튼 엄청 중요함

 

외부 사용자는 CLI나 UI(Web-UI)를 이용해서 API를 호출한다. API는 명령어로 Pod를 생성한다고 하면 Pod를 만들 수 있는 컨테이너가 내부에 존재한다. 쿠버네티스의 경우는 Pod, Service, 보안, 정책, 환경변수 등의 기능들이 별도의 컨테이너 형태로 만들고 각각의 컨테이너를 API로 연결한다.

 

1. api-server :

control-plane의 프론트엔드, 외부 사용자와 상호통신. api-server가 백 쪽에 있는 각각의 pod에 연결해준다. kubelet에 api를 전달하고 runtime에게 일을 전달해준다. kubelet은 사실상 작업반장이다.

 

2. key-value store(etcd) : 클러스터 상태 정보 저장소

클러스터 데이터베이스를 백업하기 위해 사용하는 데이터베이스. 마스터는 노드, 포드, 컨테이너들의 상태 정보를 파악하기 위해 etcd에게 쿼리 한다. 우리가 현재 노드들의 상태가 어떤지 물어보면 etcd에 저장이 되어 있다.

 

3. controller : 실제로 클러스터를 실행, 하나의 컨트롤러는 스케줄러를 참조하여 정확한 수의 포드를 실행. 포드에 문제가 발생한다면 다른 컨트롤러가 이를 감지하고 대응. 서비스를 포드에 연결하므로 요청이 적절한 엔드포인트로 이동.

 

4. scheduler : 클러스터 상태가 양호한가? 새 컨테이너가 필요하다면 어디에 배치할까? CPU 또는 메모리와 같은 포드의 리소스 요구 사항과 함께 클러스터 상태 고려

 

= pod 생성 시나리오 =

1. 사용자가 Pod를 배치한다고 API Server에 전달하면 API Server는 Pod를 배치하기 위해 Pod를 담당하는 Pod에게 작업을 제시한다. 그럼 Key-value Store에서 어디에 배치할지를 결정해야 한다.

 

2. 모든 노드가 작업이 가능한 상황이라면 Scheduler가 어디에 배치할지 결정하게 된다. 그럼 API Server는 Kubelet으로 연결해서 작업을 전달하고 Kubelet은 Runtime에게 전달하고 Runtime은 Pod를 하나만들고 만들어진 Pod는 외부 사용자에게 서비스를 제공하기 위해서 Kube-proxy에게 연결된다.

 

3. kube-proxy를 통해 외부 사용자가 접속해서 들어오게 되면 서비스를 제공받게 된다. 혹시나 문제가 발생하면 해당 정보는 kubelet을 통해 API Server에게 전달되고 API Server는 그 정보를 key-value store에 저장하게 된다.

 

4. 개발자가 다시 들어와 노드 상태 정상인지 물어보면 API Server는 상태를 확인하기 위한 etcd 컨테이너(pod)에게 query를 던진다. 그리고 정보를 반환하여 정상/비정상을 판가름 해준다.

 

 

주로 사용하게될 명령어

- kubeadm -> 설치(master)

- kubectl -> 관리(master)

- kubelet -> 실행(node)

 

 

환경

 

이 상황에서 master와 모든 노드에 도커 설치하기

sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] \ 
https://download.docker.com/linux/ubuntu focal stable"
sudo apt-cache policy docker-ce
sudo apt install docker-ce –y
sudo systemctl enable docker
sudo systemctl restart docker

master와 모든 노드에 ssh 접근과 방화벽 기능 해제츨 해주자

sudo apt-get install -y ssh
sudo systemctl enable ssh	
sudo systemctl restart ssh
sudo ufw disable

master와 모든 노드에 

sudo swapoff -a

 

master와 모든 노드에  kubeadm을 이용한 kubernets 설치

반드시 root로 수행하자

 

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ cat <<EOF > /etc/apt/sources.list.d/kubernetes.list
$ deb http://apt.kubernetes.io/ kubernetes-xenial main
$ EOF
$ sudo apt-get update
$ sudo apt-get install -y kubelet kubeadm kubectl
$ sudo apt-mark hold kubelet kubeadm kubectl
$ systemctl daemon-reload
$ systemctl restart kubelet
* apt 사용시 문제가 발생할 경우 아래 실행한 뒤 진행
sudo rm /var/lib/apt/lists/lock
sudo rm /var/cache/apt/archives/lock
sudo rm /var/lib/dpkg/lock*
sudo dpkg --configure -a
sudo apt update

 

master와 모든 노드에 vi /etc/docker/daemon.json

{
		"exec-opts":	["native.cgroupdriver=systemd"]
}

이거 문구 넣어놓기

 

master 노드에서만

kubeadm init --apiserver-advertise-address 211.183.3.100
# 하고나서 만약에
# kubectl get node를 했는데 에러가 뜨는경우

$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

하고 나오는 토큰을 모든 node에 복붙해주기

 

[ERROR CRI]: container runtime is not running: output: time="2022-05-11T20:52:53+09:00" level=fatal msg="getting status of runtime: rpc error: code = Unimplemented desc = unknown service runtime.v1alpha2.RuntimeService"

 

Kubeadm unknown service runtime.v1alpha2.RuntimeService · Issue #4581 · containerd/containerd (github.com)

 

Kubeadm unknown service runtime.v1alpha2.RuntimeService · Issue #4581 · containerd/containerd

Problem Following Kubernetes official installation instruction for containerd and kubeadm init will fail with unknown service runtime.v1alpha2.RuntimeService. # Commands from https://kubernetes.io/...

github.com

rm /etc/containerd/config.toml
systemctl restart containerd
kubeadm init

이건 가급적 해주는 것이 좋다.

 

 

weavenet이나 coredns에서 에러가 뜨는경우

[K8S] CNI Weave net dial tcp 127.0.0.1:6784: connect: connection refused, failed to clean up sandbox container (tistory.com)

 

[K8S] CNI Weave net dial tcp 127.0.0.1:6784: connect: connection refused, failed to clean up sandbox container

k8s 클러스터 구성 후. kubectl get pod --all-namespaces를 보면 coredns가 정상적으로 Running 되지 않고 아래와 같이 ContainerCreating 상태로 STUCK 걸리는 현상이 발생했다.. NAMESPACE     NAME   ..

syhwang.tistory.com

 

1. master/node1/node2에서 kubeadm reset 실행 후 systemctl restart kubelet
$ kubeadm reset 
$ systemctl restart kubelet

2. cni 관련 디렉토리 파일 삭제(마스터에서만)
$ rm -rf /etc/cni/net.d
$ rm -rf $HOME/.kube/config

3. 마스터에서 kubeadm init 실행 후 cni 설치
$ kubeadm init --apiserver-advertise-address=192.168.56.200
$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

4. 파드 확인
$ kc get pod --all-namespace

그냥 이거 한번 돌려보는것도 좋음

 

 

The connection to the server localhost:8080 was refused - did you specify the right host or port?

이거 에러가 뜬 경우

The connection to the server localhost:8080 was refused 해결방법 (tistory.com)

 

The connection to the server localhost:8080 was refused 해결방법

kubectl을 통해서 쿠버네티스 클러스터에 접속하려 할 때 다음과 같은 에러 메시지가 발생하는 경우가 종종 있다. The connection to the server localhost:8080 was refused - did you specify the ..

twofootdog.tistory.com

# 하고나서 만약에
# kubectl get node를 했는데 에러가 뜨는경우

$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

해결 가능하다

 

만약 안되면 아래의 과정 반복하기

RedPlug's Tory :: [k8s] Get http://localhost:10248/healthz: dial tcp 127.0.0.1:10248: connect: connection refused. 발생 시. (tistory.com)

 

[k8s] Get http://localhost:10248/healthz: dial tcp 127.0.0.1:10248: connect: connection refused. 발생 시.

redplug입니다. 테스트 환경은 Ubuntu 18.04.2 LTS 버젼 입니다. 쿠버네티스 설치 진행 시 kubeadm init, join 시 'http://localhost:10248/healthz: dial tcp 127.0.0.1:10248: connect: connection refused.' 문..

redplug.tistory.com

 

만약 Unable to connect to the server: x509 에러가 계속 뜨는 경우

export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl get nodes

를 이용해서 등록된 노드들을 확인하기

 

master 노드에서 calico 설치해서 overlay 네트워크 만들기

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
kubectl get pod -n kube-system

제대로 작동하는지 확인하기 위해 이걸로 확인하기

 

만약 calico가 설치안되면

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

다른거 설치해버리기

 

만약 coredns가 계속 ContainerCreating 상태인경우

 

이건 cni가 꼬여서 Cluster 전체가 망가진 상황이라고 한다.

[K8S] CNI Weave net dial tcp 127.0.0.1:6784: connect: connection refused, failed to clean up sandbox container (tistory.com)

 

[K8S] CNI Weave net dial tcp 127.0.0.1:6784: connect: connection refused, failed to clean up sandbox container

k8s 클러스터 구성 후. kubectl get pod --all-namespaces를 보면 coredns가 정상적으로 Running 되지 않고 아래와 같이 ContainerCreating 상태로 STUCK 걸리는 현상이 발생했다.. NAMESPACE     NAME   ..

syhwang.tistory.com

제시된 제안은 아예 새로 시작하기

 

---

 

OBJECT

1. 기본명령

kubectl get pod -n kube-system
# 가장 중요한 pod들이 돌아가고 있는지 확인

kubectl api-resources
# 사용가능한 api-resource들 보기

kubectl run nginx --image=nginx --restart=Always
# 그냥 pod 작동

kubectl describe pod nginx
# pod의 상세정보 보기

kubectl get pod
# 배포된 포드들 보기

kubectl get pod -o wide
# pod 리스트를 가져오되 IP와 배치된 node 위치 알기

kubectl get pod nginx -o yaml
# yaml 형식으로 pod 정보를 보다 자세하게 볼 수 있다.

kubectl get pod -n default
# 모든 pod는 namespace가 없다면 default에 배치된다.

kubectl exec -it nginx -- bash 
# Pod(Container) 직접 접근
# ctrl + p, ctrl + q로 빠져나오기

kubectl delete pod nginx
# pod 삭제

kubectl apply -f nginx-pod.yaml
# yaml 파일로 배포하기
# 이걸 다시 입력하면 오류는 발생하지 않고 rollup update된다.

kubectl delete -f nginx-pod.yaml
# 이걸로 파일기반 삭제가 가능해진다.

kubectl get pod -l app
# app 라벨이 붙은 pod 보기

 

 

 

만약 Pod안에 컨테이너가 2개인 경우라면 port로 구분되어서 접근하게 된다.

 

각각을 나누기 위해 cgroup을 이용하여 cpu, ram resource를 구분하여 사용하게 된다. Pod단위가 되면서 컨테이너들이 묶여다니기 떄문에 자원 불균형이 생길일이 없어진다.

 

사용자는 api버전을 입력하면 해당 api를 통해 오브젝트를 사용할 수 있으며 yaml 파익 작성시에는 api 버전과 Kind를 작성해야 하는데 api-resources에서 확인된 정보를 정확히 기입해야 사용이 가능하다.

 

NAMESPACE에는 true, false가 있고 이는 해당 오브젝트를 동작 시킬 때 특정 네임스페이스에 속하도록 할 수 있는지 여부를 결정해주는 것이다.

 

 

2. Pod

yaml 파일을 이용해서 배포를 하게 된다.

 

apiVersion : 포드를 담당하는 api version

Kind : 무엇을 위해 만든건가

metadata :  원본 데이터를 지칭하는(대표하는) 데이터들이다.

spec : 배포 정보

 

 

 

3. ReplicaSet, Deployment

= ReplicaSet =

= Deployment =

 

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-nginx-pods-label
  template:
    metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx-pods-label
      spec:
        containers:
        - name: nginx
          image: nginx:latest
          ports:
          - continaerPort: 80

Replicaset에서 kind를 Deployment로 바꾸어주기만 하면 된다.

 

k apply -f deploy-nginx.yaml --record 
# 배포기록이 저장된다. warning이 뜨지만 괜찮다.
# 파일을 수정해서 이걸로 다시 배포하면 IP가 바뀐다. 나중에 LB로 이걸 트래킹 해준다.

kubectl delete -f deploy-nginx.yaml
# 배포 삭제시

kubectl set image deploy deploy-nginx nginx tonyhan18/testweb:blue
# 이렇게 하면 IP변경 없이 이미지를 바꿀 수 있다.

kubectl get deploy 
# 디플로이먼트 보기(deploy, deployment)

k get deploy,rs,pod --all
# 정보보기

kubectl rollout history deploy deploy-nginx
# 이전 배포정보들을 볼 수 있다.

kubectl rollout undo deploy deploy-nginx --to-revision=1
# 이전 버전으로 돌아갈 수 있다.

 

4. 서비스 : 포드를 연결하고 외부에 노출 : Metal LB/ClusterIP, NodeExport

서비스 오브젝트는 포드를 연결하고 외부에 노출하는 역활을 한다. 클러스터 외부 + 인터넷 접근이 되도록하기

 

1. ClusterIP : 클러스터 환경 내에서만 접근할 수 있는 주소(외부에서는 접근할 수 없음) -> 외부로 나갈필요 없는 DB와 같은 경우에 사용됨

2. Node Port : 외부 연결 가능 -> 처음 접속시 하나에만 연결을 해준다. -> 일반적으로 로컬 환경에서 제공하는 기능

3. lb(로드밸런서) : 외부 연결 가능 -> 처음 접속시 안쪽에 있는 포드들에 로드밸런싱해준다. -> 일반적으로 public cloud 환경에서 제공하는 기능

 

방법

1. 고유한 도메인 이름을 부여

2. 로드 밸런서 기능을 수행

3. 클라우드 플랫폼의 로드 밸런서, 클러스터 노드의 포트 등을 통해 포트를 외부로 노출(주로 사용)

 

- ClusterIP

: 쿠버네티스 내부에서만 포드들에 접근가능. 3개의 포드를 묶어서 관리하고 싶다면 이걸 clusterIP라고 부르게 된다. 물론 이거 외부로 연결이 안된다.

예를 들어서 현재 배포된 이 서비스도 EXTERNAL-IP가 없어서 배포가 안된다.

 

- NodePort

: 노드에 있는 포드로 연결만을 접속하게 하기 때문에 트래픽 분산도 안되고 IP 3개를 운영해야한다는 단점이 존재한다.

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-nginx-pods-label
  template:
    metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx-pods-label
    spec:
      containers:
      - name: nginx
        image: tonyhan18/testweb:green
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
spec:
  ports:
  - name: nginx-port
    targetPort: 80
    port: 8080
  selector:
    app: my-nginx-pods-label
  type: NodePort

 

```

kubectl apply -f deploy-svc-nginx.yaml

k get pods -o wide

kubectl get pods,rs,svc

```

이중에 NodePort의 IP로 외부접속을 시도해보자

 

그런데 NodePort의 개념대로라면 이게 하나로 바뀐다면 다른 노드로의 접속은 허용되어서는 안되지만 replicas를 1로 바꾸고 해보니 이게 매우 잘된다.

 

이게 되는 이유가 clusterIP로 묶여 있기때문에 자동으로 라우팅이 발생한다. 이러면 효율이 크게 떨어지게 된다. 그래서 이걸 Load Balancing 해줄 필요가 있다.

 

```

kubectl describe svc nginx-nodeport

```

로 또 다시 정보를 볼 수 있는데... External Traffic Policy : Cluster가 보인다.

 

External Traffic Policy

- cluster : 내부로 유입된 트래픽이 목적지 포드를 찾지못하면 라우팅을 통해 다른 노드에 있는 동일 deploy(or replica set)의 포드로 전송시켜준다. 즉, 내부적으로 로드밸런싱이 가능해 진다. 단, 이 경우 안정적인 서비스 제공은 가능하지만 불필요한 라우팅으로 인해 노드의 리소스를 사용하게 된다.

 

- local : 지정된 노드로 유입된 트래픽은 해당 노드에 위치한 포드로만 전송하며 없을 경우 로드밸런싱하지 않는다.

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-nginx-pods-label
  template:
    metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx-pods-label
    spec:
      containers:
      - name: nginx
        image: tonyhan18/testweb:green
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
spec:
  externalTrafficPolicy: Local
  ports:
  - name: nginx-port
    targetPort: 80
    port: 8080
    nodePort: 31008
  selector:
    app: my-nginx-pods-label
  type: NodePort

 

Service 부분에서 externalTrafficPolicy: Local로 추가되면 한쪽 노드로만 접속이 가능해진다.

 

```

kubectl scale --replicas 3 deploy deploy-nginx

```

단순히 명령어로 레플리카의 크기를 키울수도 있다.

 

- Metal LB

1. 네임스페이스 생성하기

```

mkdir lb

vi namespace.yaml

```

apiVersion: v1
kind: Namespace
metadata:
  name: metallb-system
  labels:
    app: metallb

```

kubectl apply -f namespace.yaml

```

 

2. metallb 배포하기

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

 

3. metallb에서 사용할 주소 대역정보를 configmap을 통해 전달해준다.

```

vi metallb-config.yaml

```

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 211.183.3.201-211.183.3.239

 

```

kubectl apply -f metallb-config.yaml

```

 

4. deploy 와 타입 LB 의 서비스를 연결하여 포드 배포하기

아래쪽에 NodePort라고 되어있던것을 LoadBalancer로 바꾸어주고 쓸모없는 것들도 지워주었다.

이걸 가지고 배포해보자

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-nginx-pods-label
  template:
    metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx-pods-label
    spec:
      containers:
      - name: nginx
        image: brian24/testweb:green
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
spec:
  ports:
  - name: nginx-port
    targetPort: 80
    port: 80
  selector:
    - app: my-nginx-pods-label
  type: LoadBalancer

```

kubectl apply -f deploy-svc-nginx.yaml

kubectl get svc

```

 

결과 우리가 배포했던것의 TYPE이 LoadBalancer로 바뀌어 있으면 성공이다.

 

직접 접속해보자

 

했더니 LoadBalancer의 ip로 접속해도 NAVER가 나오는 것을 확인할 수 있다.

 

우린 이걸 가지고 이제 DNS 등록만 해주면 성공하는 것이다.

 

```

kubectl delete -f deploy-svc-nginx.yaml

```

일단 서비스를 없애자

 

그래서 이 상태가 되면 된다.

 

MSA(Ingress Controller, Ingress) 63일차

외부에서 나에게 접속할 수 있는 인그레스 네트워크를 구축해보자

 

실재환경에서는 동영상과 DB, 사진과 DB를 위한 서버와 DB가 모두 분리되어 있다. 그래서 들어오는 주소에 따라서 트래픽을 분산하자는 것이다. 그래서 실재로는 각 도메인별로 서버를 구분해두었다. domain을 바꾸게 되면 서버를 바꾸어주는 것이다. 그러다가 특정 서비스에 대한 수요가 넘쳐나면 그 서비스에 대한 pod만 늘려주는 것이다. 이렇게 봐서

는 port에 대한 번호만 봐서는 안된다. 문자열을 보아야한다. 글자는 그럼 어디에서 볼 수 있을까?

 

그리고 k8s에서는 도메인을 보고 어디로 보낼지를 결정하는 서비스가 ingress라는 서비스이다.

ingress controller는 별도로 제공되는 ad-on을 사용해서 도메인을 보고 ingress로 전달해주어야 한다.
일반적인 환경에서 ingress controller는 아래에 보는 것과 같이 nginx로부터 다운받아와야 한다.

 

인그레스 :
내부에서 외부로 나가는 트래픽은 이그레스(egress), 외부에서 내부로 유입되는 트래픽은 인그레스(ingress)

ingress는 인그레스 컨트롤러를 이용하여 외부에서 유입되는 트래픽들의 도메인 주소등을 확인하고 어떠한 포드로 포워딩할지를 결정해주는 도구이며 포트를 넘어 주소의 컨텐츠를 확인하고 로드밸런싱을 구현해준다.

 

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml

인그레스 컨트롤러 설치하기

 

Installation Guide - NGINX Ingress Controller (kubernetes.github.io)

 

Installation Guide - NGINX Ingress Controller

Installation Guide There are multiple ways to install the NGINX ingress controller: with Helm, using the project repository chart; with kubectl apply, using YAML manifests; with specific addons (e.g. for minikube or MicroK8s). On most Kubernetes clusters,

kubernetes.github.io

최신버전은 여기에서 구할 수 있다.

 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: gildong.test.pri
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: test-svc
            port:
              number: 80

ingress.yaml 파일을 위와같이 작성해주면 기타 도메인도 볼 수 있지만 우선은 루트 도메인의 정보를 볼 수 있게 된다.

 

여기까지는 매우 기본적인 ingress 테스트 용이었고

 

MSA 구축하기

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-testshop
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: www.testshop.co.kr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc-main
            port:
              number: 80
      - path: /blog
        pathType: Prefix
        backend:
          service:
            name: svc-blog
            port:
              number: 80
      - path: /shop
        pathType: Prefix
        backend:
          service:
            name: svc-shop
            port:
              number: 80

shopingress.yaml

 

---
# 메인페이지용 코드
apiVersion: v1
kind: Pod
metadata:
  name: pod-main
  labels:
    page: main
spec:
  containers:
  - name: ctn-main
    image: nginx
    ports:
    - containerPort: 80
---
# 메인페이지용 서비스
apiVersion: v1
kind: Service
metadata:
  name: svc-main
spec:
  ports:
    - name: main-lb-port
      targetPort: 80
      port: 80
  selector:
    page: main
  type: LoadBalancer
---
# blog 용 코드
apiVersion: v1
kind: Pod
metadata:
  name: pod-blog
  labels:
    page: blog
spec:
  containers:
  - name: ctn-blog
    image: tonyhan18/testweb:blue
    ports:
    - containerPort: 80
---
# blog 용 서비스
apiVersion: v1
kind: Service
metadata:
  name: svc-blog
spec:
  ports:
    - name: main-lb-port
      targetPort: 80
      port: 80
  selector:
    page: blog
  type: LoadBalancer
---
# shop 용 코드
apiVersion: v1
kind: Pod
metadata:
  name: pod-shop
  labels:
    page: shop
spec:
  containers:
  - name: ctn-shop
    image: tonyhan18/testweb:green
    ports:
    - containerPort: 80
---
# shop 용 서비스
apiVersion: v1
kind: Service
metadata:
  name: svc-shop
spec:
  ports:
    - name: main-lb-port
      targetPort: 80
      port: 80
  selector:
    page: shop
  type: LoadBalancer

service-pod.yaml

 

Autoscaler

Pod에 지정한 CPU 상태를 넘어서게 되면 추가적(자동으로)으로 늘려가나는 방법. 평균값을 계산해서 유지한다. 일단 생성된거는 최소 3분은 유지시킨다.

 

scale은 크게 두가지가 존재한다.

1. scale up -> 서버 한대를 두고 지정된 양보다 트래픽이 몰리면 스펙을 높이겠다.

2. scale out -> 수평적으로 동일 포드/인스턴스를 늘려가는 방식(일반적인 autoscale의 방식)

 

나중에 나오는 ecs를 이용한 auto scale도 이러한 방식으로 움직이게 된다.

 

AMI(glance) = registry

- AMI(glance) : 인스턴스를 만들기 위한 이미지 저장소. 여기에 computing+storage 자원을 붙이는 것이다(cpu, ram)

- registry : 컨테이너를 만들기 위한 이미지 저장소

 

Block Storage도 local과 remote로 나뉘게 되는데 container에 local storage를 연결하는건 좋은 방법이 아니다.

어떤 방법을 사용하던 external 볼륨을 사용해야 한다. 이러한 볼륨을 persistent volume이라고 부른다. 영구디스크/영구스토리지라고 부른다.

 

이러한 것을 aws에서는 ecs로 관리할 수 있게 된다.

 

- 인증하기

wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

 

먼저 github에서 auto scaler를 구성하기 위한 파일을 다운 받아보자

 

```

vi components.yaml

```

metric 사용하는데, 공인 인증서를 사용하겠다라는 뜻, 하지만 별도로 공인 인증서를 우리는 발급받지 않은 상태에서 사용하고자 한다. 이를 위해서는 공인인증서 없이 포드를 실행할 수 있도록 해 주어야 하는데. 이때 필요한 것이, insecure이다. 참고로 공인인증서는 최고 발급(관리) 기관을 통해 사용자를 인증하고 서명을 하여 발급받을 수 있다.

이거 말고도 우리는 사설 CA를 둘 수 있다.

`- --kubelet-insecure-tls`

 

그래서 위와같이 --secure-port 아래에 추가해주면 된다.

 

```

k apply -f components.yaml

```

 

```

k get pod -n kube-system

```

 

---
# 메인페이지용 코드
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-main
spec:
  replicas: 1
  selector:
    matchLabels:
      page: main
  template:
    metadata:
      name: pod-main
      labels:
        page: main
    spec:
      containers:
      - name: ctn-main
        image: nginx
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: "750m"
          requests:
            cpu: "250m"
---
# 메인페이지용 서비스
apiVersion: v1
kind: Service
metadata:
  name: svc-main
spec:
  selector:
    page: main
  ports:
  - port: 80
---
# blog 용 코드
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-blog
spec:
  replicas: 1
  selector:
    matchLabels:
      page: blog
  template:
    metadata:
      name: pod-blog
      labels:
        page: blog
    spec:
      containers:
      - name: ctn-blog
        image: tonyhan18/testweb:blue
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: "250m"
          requests:
            cpu: "150m"
---
# blog 용 서비스
apiVersion: v1
kind: Service
metadata:
  name: svc-blog
spec:
  selector:
    page: blog
  ports:
  - port: 80
---
# shop 용 코드
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-shop
spec:
  replicas: 1
  selector:
    matchLabels:
      page: shop
  template:
    metadata:
      name: pod-shop
      labels:
        page: shop
    spec:
      containers:
      - name: ctn-shop
        image: tonyhan18/testweb:green
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: "500m"
          requests:
            cpu: "250m"
---
# shop 용 서비스
apiVersion: v1
kind: Service
metadata:
  name: svc-shop
spec:
  selector:
    page: shop
  ports:
  - port: 80

마지막으로 사용량에 autoscaler를 적용하기 위해 위와같이 작성해주자

 

kubectl autoscale deploy deploy-blog --cpu-percent=20 --min=1 --max=10

 

 

```

yum install -y httpd-tools

ab -c 1000 -n 200 -t 60 http://www.testshop.co.kr/blog

```

 

web-ui

먼저 web-ui를 설치해보자. 물론 자주 쓰는건 아니지만 그래도 실험용으로 사용해보자

 

kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml

하면 뭐가 막 나올텐데 그게 끝나고

```

kubectl proxy &

```

 

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login

이 주소로 자신의 가상머신 웹브라우저에서 접속해보자

 

그러면 위와같은게 뜬다.

 

vi dashboard-adminuser.yaml을 작성/배포한다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard

 

이 상황에서 사용자에게 권한 부여를 해주자

```

touch roll.yaml

```

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

 

마지막으로 토큰을 확인해보자

kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')

위 명령을 이용하면 토큰값이 나오는데 그걸 web-ui에 복붙하여 접근해주자

 

하면 위와같이 dashboard를 볼 수 있게 된다.

728x90