쿠버네티스(k8s)에 대하여 - 9.2 (object, service, Selector, ingress)

양승현·2022년 9월 2일
3

kubernetes

목록 보기
5/18

오브젝트란

  • 쿠버네티스를 사용하는 관점에서 파드와 디플로이먼트는 스펙(spec)과 상태(status)등의 값을 가지고 있다.
  • 이런 값을 가지고 있는 파드와 디플로이먼트를 개별 속성을 포함해 부르는 단위를 오브젝트라 한다.
  • k8s는 모든 기능을 오브젝트(객체)로 관리한다.

기본 오브젝트

pod

  • k8s에서 최소 단위이며, 1개 이상으 컨테이너를 가지고 있어 여러 기능을 묶어 하나의 목적으로 사용 가능하다.
  • 웹 서비스를 구현하는데 필요한 가장 최소 단위
  • 독립적인 공간과 사용 가능한 IP를 가지고 있다.

네임스페이스

  • k8s 클러스터에서 사용되는 리소스들을 구분해 관리하는 그룹이다.
  • 3가지의 네임스페이스가 있다.
  • 특별히 지정하지 않으면 default로 지정된다.

볼륨

  • 파드가 생성될 때 파드에서 사용할 수 있는 디렉터리를 제공한다.
  • 내부 저장소는 영속적이지 않지만 외부 저장소는 파드가 사라지더라도 데이터를 저장과 보존이 가능하다

서비스

  • 외부에서 클러스터 내의 pod로 접속할 수 있는 방법
LB, nodeport, cluster ip

디플로이먼트

  • 기존 오브젝트로만 k8s를 구성할 수 있지만, 한계가 있어 이를 효율적으로 작동하도록 기능을 조합,추가하여 구현한 것이다
  • 일반적인 포드는 삭제가 자유로운 포드이며 이름의 경우도 임의의 hash 뒤에 붙이게 된다.
	deployment : test-deploy
    replicaset : test-deploy-12345(2개의 pod를 유지하겟다)
    pod : test-deploy-12345-dawdwd
    	  test-deploy-12345-wdawnl
          - statefulset을 적용한다면 
          	test-deploy-12345-1
          	test-deploy-12345-2

목적에 맞는 오브젝트

  • 데몬셋 - 각 노드에 무조건 일괄적으로 하나씩 배포, 모니터링등에 활용하면 유용하다.
  • 컨피그맵(configMap) - 시스템 환경변수, 일반적인 파일 등을 제공하기 위한 방법이다.(보안성은 없다)
  • Secret - 컨피그맵과 거의 동일하지만 해당 데이터가 외부에 노출되지 않는다는 장점이 있어서, 주로 인증, key, susername/password, ssh 접속등과 같은 보안성을 요구하는 곳에서 활용한다.
  • 가령, 특정 사설 저장소로 접속하기 위한 username, password,address를 secret으로 작성하여 yaml 파일에 적용할 경우 특정 저장소에서 파일을 다운로드할 때 유용하다.

cke 실습해보기

파드 업데이트하기

cat nginx1.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  replicas: 3
  selector:
    matchLabels:
      color: blue
  template:
    metadata:
      labels:
        color: blue
    spec:
      containers:
        - name: test
          image: nginx
  • pod 배포
 kubectl apply -f nginx1.yml  
  • pod 정보 확인
 kubectl get pod -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP          NODE                                           NOMINATED NODE   READINESS GATES
test-69454c947b-ggccm   1/1     Running   0          15s   10.64.0.7   gke-mytestcluster-default-pool-f9572c5c-fvhz   <none>           <none>
test-69454c947b-nmlp2   1/1     Running   0          15s   10.64.1.4   gke-mytestcluster-default-pool-f9572c5c-fvj0   <none>           <none>
test-69454c947b-z6b75   1/1     Running   0          15s   10.64.2.6   gke-mytestcluster-default-pool-f9572c5c-ph7f   <none>           <none>

v1 - apply - kubectl get pod
v2 - apply - kubectl get pod

update

Rolling Update

  • 새로 만든 컨테이너 수 만큼, 기존 컨테이너 삭제한다. 시간이 오래 걸리기 때문에 알맞는 상황에 사용해야한다.
  • 예를 들어, 한 번에 삭제할 컨테이너 수를 지정하여, 해당 수만큼 컨테이너를 생성한다.
  • 삭제 개수와 추가 생성 개수를 지정해서 사용할 수 있다
cat nginx1.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 2
  replicas: 3
  selector:
    matchLabels:
      color: blue
  template:
    metadata:
      labels:
        color: blue
    spec:
      containers:
        - name: test
          image: nginx
  • RollingUpdate 를 적용하게 되면 기존 서비스의 중단이 없이, 새로운 포드의 생성을 미리 산정하고 계획할수 있게된다. 만약 서비스 중에 처리 속도가 늦어진다면 maxsurge, maxunavailable 을 조정하여 안정적으로 서비스를 유지시킬 수 있게된다.

2. Recreate

  • 기존 Pod 를 모두 종료 ( terminate ) 시킨 다음, 새로운 Pod 로 전환
  • type: Recreate -> 종료되는 중간에는 해당 애플리케이션으로의 외부 접속이 불가능해지는 문제가 발생한다.
cat nginx1.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  strategy:
    type: Recreate
  replicas: 3
  selector:
    matchLabels:
      color: blue
  template:
    metadata:
      labels:
        color: blue
    spec:
      containers:
        - name: test
          image: nginx
  • 배포하기
kubectl apply -f nginx1.yml
  • 이미지 변경 후 배포
kubectl get pod ; sed -i 's/image: httpd/image: ngix/' nginx1.yml ; kubectl apply -f nginx1.yml ; kubectl get pod

k8s - service

cluseter ip

  • 두개의 포트가 있는 경우 각 포드 별로 별도의 IP주소를 사용한다.
  • 이들은 서로간에 통신을 할 경우 각 포드가 서로 다른 노드에 있다고 가정한다면 이들을 마치 하나의 네트워크에 연결하기 위한 환경이 필요한데 이러한 클러스터 상에서 서로 다른 노드에 있는 포드들간 통신이 가능하도록 하기 위하여 cluster ip를 두게 된다.

NodePort

  • 외부에서 클러스터 내부에 접속하기에 가장 쉬운 방법이다.
  • 노드 포트 서비스를 설정하면 모든 워커 노드의 특정 포트( 30000 ~ 32768 )를 열고 여기로 오는 모든 요청을 노드포트 서비스로 전달하고 노드 포트 서비스는 해당 업무를 처리할 수 있는 파드에 여청을 전달한다.

Selector

  • 라벨 지정

1. replicaset

  • 어떤 포트의 라벨을 확인하고 지정된 개수를 유지할 것인가에 활용

2. service

  • (노드포트에서) 노드의 포트로 접속된 트래픽에 대하여 누구(포드)에게 전달할 것인가 -> label
    port 80-> nodeport 로 접속된 트래픽을 nodeport 서비스의 특정 포트(80/tcp)로 유입되면(2)
    targetPort 80-> 최종적으로 목적지 포드의 80번포트로 전달하겠다(3)
    nodePort 30000 -> 외부에서 가상머신의 어떤 포트로 접속하면?(1)
    Port 를 3 가지 지정해야 한다
nodePort : 외부에서 Node 에 접속할 Port
port : Node 로 접속된 트래픽이 전달될 node Port 서비스의 특정 포트
targetPort : node Port 서비스의 특정 포트에 트래픽이 전달시 최종적으로 전달될 Pod 의 Port
cat nginx1.yml

metadata:
  name: test
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 2
  replicas: 3
  selector:
    matchLabels:
      color: blue
  template:
    metadata:
      labels:
        color: blue
    spec:
      containers:
        - name: test
          image: nginx

--- # --- 를 사용하면 작업을 구분
apiVersion: v1
kind: Service
metadata:
  name: test
spec:
  selector:
    color: blue
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetport: 80
      nodePort: 30000
  type: NodePort

방화벽 규칙 생성 및 삭제

$ gcloud compute firewall-rules create permitnp --allow=tcp:30000
$ gcloud compute firewall-rules delete permitnp

스케일 조정

  • 포드3 -> 포드1
kubectl scale --replicas 1 deploy test

External Traffic Policy: Cluster (기본값)

  • 해당 노드에 포드가 없다고 하더라도 클러스터를 통해 다른 노드에 있는 포드로 트래픽이 전송된다. 이때 hop 을 바꾸기 때문에 결국 라우팅이 발생한다.
  • Local 로 변경하면 해당 노드에 있는 포드로만 접속하게 되고 만약 포드가 없다면 서비스를 받을 수 없게 된다.
  • 하지만 불필요한 라우팅은 없기 때문에 DC 에 부담을 줄일 수 있게된다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 2
  replicas: 3
  selector:
    matchLabels:
      color: blue
  template:
    metadata:
      labels:
        color: blue
    spec:
      containers:
      - name: test
        image: nginx

---
apiVersion: v1
kind: Service
metadata:
  name: test
spec:
  selector:
    color: blue
  externalTrafficPolicy: Local
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30000
  type: NodePort
  • 배포하기
kubectl apply -f nginx1.yaml 
kubectl get pod,svc

NAME                        READY   STATUS    RESTARTS   AGE
pod/test-69454c947b-258lg   1/1     Running   0          4m44s
pod/test-69454c947b-6tq7q   1/1     Running   0          149m
pod/test-69454c947b-dg2vk   1/1     Running   0          4m44s
kubectl describe svc test

:
:
External Traffic Policy:  Local
  • 스케일 조정
kubectl scale --replicas 1 deploy test 
 kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
test-69454c947b-6tq7q   1/1     Running   0          152m
  • 이후 3 페이지로 접속해 보면 1곳에서만 정상적으로 페이지가 보이고 나머지 2곳은 페이지로 접속이 되지 않는다.

인그레스

rules:
- host: www.test.com        1) www.test.com 2) www.test.com/ip , 3) www.test.com/y...
  http:

  paths
  - path
    backend:
      servicename: hname-svc-default -> 서비스를 제공하는 포트의 어떤 경로로 접속되도록 할 것인가? : / -> 포드의 기본 웹 디렉토리로 전달하겠다
  • 포드에서는 아래와 같이 구성해야 한다.
 /var/www/html/index.html 

  - path: /ip

  - path: /your-directory
  • ingress는 svc와 연결하여 사용해야 한다.
    LB | NodePort ------> ingress-controller
    -ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: 
  name: example
spec:
  rules:
  - host: www.test.pri
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: example
              port:
                number: 80
  • 인그레스 컨트롤러 배포
kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml
  • 서비스 제공을 위한 포드 배포
kubectl run example --image=nginx
  • vm의 랜덤포트(30000~ ) -> nodeport:80 -> pod:80
kubectl expose pod example --port=80 --name example --type=NodePort
  • 포트 확인
kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
example      NodePort    10.12.4.16    <none>        80:30594/TCP   84s

     www.test.pri:30594 ---> nodeport:80 -------> pod/example:80
                                                           /var/www/html
  • 기존 ingress.yaml 에 아래내용 추가
metadata: 
  name: example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx"  
spec:
  • 인그레스 배포
kubectl apply -f ingress.yaml
  • 노트포트접속을 위하여 가상머신의 포트를 오픈하기위한 방화벽 설정
gcloud compute firewall-rules create permitingress --allow=tcp:3XXXX
  • 최종접속
curl -L http:www.test.pri:3XXXX
  • [최종결과]
curl -s http://yang.test.pri:31597 | head -5

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

k8s에서 로브밸런서는 public과 openstack(로드밸런서)와 같은 클라우드 환경에서 사용이 가능하다. 만약 on-premise에서 LB를 사용하고 싶다면 k8s와 연계가 가능한 별도의 object가 필요하다. 이를 metalLB

1개의 댓글

comment-user-thumbnail
2022년 9월 3일

잘보고 갑니다

답글 달기