Kubernetes 인강 정리

Kubernetes 인강 정리

Pod 생성하기

vagrant@kube-control1:~/tmp$ cat hello.yaml apiVersion: v1 kind: Pod metadata: name: hello-pod labels: app: hello spec: containers: - name: hello-container image: wowjd1375/hello ports: - containerPort: 8000

kubectl 명령어를 이용한 Container 쉘 접속하기(한 개 컨테이너의 경우)

vagrant@kube-control1:~/tmp$ kubectl exec --stdin --tty hello-pod /bin/bash

멀티 컨테이너의 경우

vagrant@kube-control1:~/tmp$ kubectl exec --stdin --tty pod-1 -c container2 /bin/bash

Service를 만들어서 외부에서도 접속이 가능하게 할 수 있다.

Pod의 labels: 부분과 selector: 부분이 매칭되어 Service와 Pod를 연결할 수 있다.

apiVersion: v1 kind: Service metadata: name: hello-svc spec: selector: app: hello ports: - port: 8200 targetPort: 8000 externalIPs: - 192.168.0.30

vagrant@kube-control1:~/tmp$ kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR hello-svc ClusterIP 10.105.101.24 192.168.0.30 8200/TCP 3m3s app=hello

curl 명령어를 통해 서비스를 확인한다.

vagrant@kube-control1:~/tmp$ curl http://192.168.0.30:8100 Hello Kubernetes!

Pod

먼저 아래 yaml 파일을 통해 Pod를 생성한다.

apiVersion: v1 kind: Pod metadata: name: pod-1 spec: containers: - name: container1 image: kubetm/p8000 ports: - containerPort: 8000 - name: container2 image: kubetm/p8080 ports: - containerPort: 8080

생성된 pod로 통신을 시도한다.

vagrant@kube-control1:~/tmp$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-1 2/2 Running 0 115s 192.168.9.65 kube-node1 vagrant@kube-control1:~/tmp$ curl 192.168.9.65:8000 containerPort : 8000 vagrant@kube-control1:~/tmp$ curl 192.168.9.65:8080 containerPort : 8080

containerPort를 중복으로 만든 후 파드를 생성해보자.

아래 명령어는 8000번 포트를 가진 컨테이너 두 개를 생성하는 명령어이다.

vagrant@kube-control1:~/tmp$ cat pod.yaml apiVersion: v1 kind: Pod metadata: name: pod-2 spec: containers: - name: container1 image: kubetm/p8000 ports: - containerPort: 8000 - name: container2 image: kubetm/p8000 ports: - containerPort: 8000

describe 명령어로 생성된 pod-2를 확인해보자

vagrant@kube-control1:~/tmp$ kubectl describe pod pod-2

container1은 생성됐지만 container2는 생성 시 failed 하는 것을 볼 수 있다.

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 57s default-scheduler Successfully assigned default/pod-2 to kube-node1 Normal Pulling 51s kubelet Pulling image "kubetm/p8000" Normal Pulled 46s kubelet Successfully pulled image "kubetm/p8000" in 4.820224576s Normal Created 45s kubelet Created container container1 Normal Started 44s kubelet Started container container1 Normal Pulled 39s kubelet Successfully pulled image "kubetm/p8000" in 4.918907458s Normal Pulled 29s kubelet Successfully pulled image "kubetm/p8000" in 4.652612655s Normal Pulling 11s (x3 over 44s) kubelet Pulling image "kubetm/p8000" Normal Pulled 7s kubelet Successfully pulled image "kubetm/p8000" in 4.013264951s Normal Created 6s (x3 over 39s) kubelet Created container container2 Normal Started 5s (x3 over 37s) kubelet Started container container2 Warning BackOff 4s (x3 over 26s) kubelet Back-off restarting failed container

로그를 확인해보자.

8000번 포트가 이미 사용 중이라는 로그가 찍힌다.

vagrant@kube-control1:~/tmp$ kubectl logs pod-2 container2 events.js:187 throw er; // Unhandled 'error' event ^ Error: listen EADDRINUSE: address already in use :::8000

✅ 한 Pod 내의 컨테이너들은 같은 포트를 사용할 수 없다.

ReplicationController

파드를 생성해주고 파드에 문제가 생기면 재 생성 시켜준다.(IP는 변경된다.)

아래와 같이 controller를 생성해주자.

control.yaml

apiVersion: v1 kind: ReplicationController metadata: name: replication-1 spec: replicas: 1 selector: app: rc template: metadata: name: pod-1 labels: app: rc spec: containers: - name: container image: kubetm/init

vagrant@kube-control1:~/tmp$ kubectl create -f control.yaml replicationcontroller/replication-1 created

현재 192.168.233.194의 ip를 가진 pod가 생성됐다.

이제 이 파드를 삭제해보자.

vagrant@kube-control1:~/tmp$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES replication-1-ktsbs 1/1 Running 0 3m54s 192.168.233.194 kube-node2

pod를 직접 삭제해도 다른 이름을 가진 pod가 재 생성되어 동작 중이다.

vagrant@kube-control1:~/tmp$ kubectl delete pod replication-1-ktsbs pod "replication-1-ktsbs" deleted vagrant@kube-control1:~/tmp$ kubectl get pods NAME READY STATUS RESTARTS AGE replication-1-mrv6z 1/1 Running 0 59s

pod의 ip를 살펴보면 192.168.233.196으로 변경된 것을 확인할 수 있다.

vagrant@kube-control1:~/tmp$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES replication-1-mrv6z 1/1 Running 0 2m6s 192.168.233.196 kube-node2

Label

먼저 아래와 같이 6개의 Pod를 생성해준다.

vagrant@kube-control1:~/tmp$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-1 1/1 Running 0 3m43s 192.168.233.197 kube-node2 pod-2 1/1 Running 0 3m3s 192.168.9.68 kube-node1 pod-3 1/1 Running 0 2m30s 192.168.233.198 kube-node2 pod-4 1/1 Running 0 69s 192.168.9.69 kube-node1 pod-5 1/1 Running 0 46s 192.168.233.199 kube-node2 pod-6 1/1 Running 0 16s 192.168.9.70 kube-node1

이제 서비스를 만들 때 원하는 pod를 선택해보자.

selector는 type: web으로 설정하여 service를 생성한다.

vagrant@kube-control1:~/tmp$ cat label-svc.yaml apiVersion: v1 kind: Service metadata: name: svc-for-web spec: selector: type: web ports: - port: 8080

생성된 서비스의 상세 정보를 확인하면 endpoint에 192.168.233.197(pod-1), 192.168.9.69(pod-4)가

포함된 것을 확인할 수 있다.

이 두 파드는 labels의 type이 web으로 설정된 파드들이다.

vagrant@kube-control1:~/tmp$ kubectl describe svc svc-for-web Name: svc-for-web Namespace: default Labels: Annotations: Selector: type=web Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.100.17.151 IPs: 10.100.17.151 Port: 8080/TCP TargetPort: 8080/TCP Endpoints: 192.168.233.197:8080,192.168.9.69:8080 Session Affinity: None Events:

이번엔 label의 lo가 production인 파드를 연결해보자.

vagrant@kube-control1:~/tmp$ cat label-prod.yaml apiVersion: v1 kind: Service metadata: name: svc-for-prod spec: selector: lo: production ports: - port: 8080

서비스의 상세정보를 확인하면 라벨의 lo가 production인 파드들이 Endpoint에 속한 것을

확인할 수 있다.

vagrant@kube-control1:~/tmp$ kubectl describe svc svc-for-prod Name: svc-for-prod Namespace: default Labels: Annotations: Selector: lo=production Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.106.85.173 IPs: 10.106.85.173 Port: 8080/TCP TargetPort: 8080/TCP Endpoints: 192.168.233.199:8080,192.168.9.69:8080,192.168.9.70:8080 Session Affinity: None Events:

✅ selector를 활용하면 서비스와 파드의 label을 묶어서 사용할 수 있다.

NodeSchedule

Pod를 생성할 때 nodeSelector를 지정하면 정해진 노드에 파드를 생성할 수 있다.

먼저 node들의 label을 확인해보자.

vagrant@kube-control1:~/tmp$ kubectl get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS kube-node1 Ready 171m v1.22.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kube-node1,kubernetes.io/os=linux kube-node2 Ready 170m v1.22.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kube-node2,kubernetes.io/os=linux

node1에 pod를 생성하기 위해 nodeSelector 부분에 kube-node1의 label을 입력한다.

vagrant@kube-control1:~/tmp$ cat nodeselect.yaml apiVersion: v1 kind: Pod metadata: name: pod-3 spec: nodeSelector: kubernetes.io/hostname: kube-node1 containers: - name: container image: kubetm/init

pod-3를 생성하고 NODE 부분을 확인하면 kube-node1에 생성된 것을 확인할 수 있다.

vagrant@kube-control1:~/tmp$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-3 1/1 Running 0 19s 192.168.9.71 kube-node1

또는, node의 현재 자원 상황에 따라 스케쥴러가 자동으로 자원을 할당한다.

kube-node1

Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 250m (12%) 0 (0%) memory 0 (0%) 0 (0%) ephemeral-storage 0 (0%) 0 (0%) hugepages-2Mi 0 (0%) 0 (0%)

kube-node2

Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 250m (12%) 0 (0%) memory 0 (0%) 0 (0%) ephemeral-storage 0 (0%) 0 (0%) hugepages-2Mi 0 (0%) 0 (0%)

먼저 새 pod를 생성해준다.

vagrant@kube-control1:~/tmp$ cat schedule.yaml apiVersion: v1 kind: Pod metadata: name: pod-3 spec: containers: - name: container image: kubetm/init resources: requests: memory: 2Gi limits: memory: 3Gi

현재 node1과 node2 둘 다 메모리에 여유가 있으므로 node1에 파드가 생성된다.

vagrant@kube-control1:~/tmp$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-3 1/1 Running 0 9s 192.168.9.73 kube-node1

이제 동일한 yaml 파일로 다른 파드를 생성해보자.

vagrant@kube-control1:~/tmp$ cat schedule.yaml apiVersion: v1 kind: Pod metadata: name: pod-4 spec: containers: - name: container image: kubetm/init resources: requests: memory: 2Gi limits: memory: 3Gi

아래와 같이 두 번째 pod는 node2에 생성된 것을 확인한다.

vagrant@kube-control1:~/tmp$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-3 1/1 Running 0 108s 192.168.9.73 kube-node1 pod-4 1/1 Running 0 6s 192.168.233.201 kube-node2

Service

1. ClusterIP

2. NodePort

3. Load Balancer

먼저 여러 서비스 중 ClusterIP를 소개한다.

위 그림과 같이 IP가 부여된 Service를 pod에 연결하여 외부에서 접속하여 사용할 수 있다.

pod에도 ip가 있는데 왜 굳이 service를 연결하여 사용할까?

Pod는 시스템 장애 등의 문제가 발생하면 Pod가 재생성되며, 이 때 pod의 ip는 변경된다.

그럼 지속적인 서비스가 불가능해지기 때문에 pod가 아닌 service와 연결하여 서비스를 제공한다.

먼저 pod를 생성한다.

apiVersion: v1 kind: Pod metadata: name: pod-1 labels: app: pod spec: nodeSelector: kubernetes.io/hostname: kube-node1 containers: - name: container image: kubetm/app ports: - containerPort: 8080

그런 다음 Service를 생성해준다.

type을 지정하지 않으면 default로 ClusterIP로 생성되기 때문에 맨 아랫줄은 생략해도 무방하다.

여기서 pod의 label을 통해 pod와 service가 연결된 상태이다.

apiVersion: v1 kind: Service metadata: name: svc-1 spec: selector: app: pod ports: - port: 9000 targetPort: 8080 type: ClusterIP

vagrant@kube-control1:~/tmp$ kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 443/TCP 17d svc-1 ClusterIP 10.105.28.62 9000/TCP 5m4s app=pod vagrant@kube-control1:~/tmp$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-1 1/1 Running 0 3m23s 192.168.9.74 kube-node1

curl 명령어를 통해 Service -> Pod로 통신해보자.

vagrant@kube-control1:~/tmp$ curl 10.105.28.62:9000/hostname Hostname : pod-1

다음으로 NodePort를 살펴보자.

< 출처 : KUBETM BLOG >

NodePort 또한 기본적으로 service에 ip가 할당된다.

특징은 Cluster 내에 연결된 모든 Node에 똑같은 Port가 할당된다.

그럼 외부에서 이 port로 접속을 하면 해당 Service로 연결이 된다.

Service는 외부에서 트래픽이 들어오면 Node1과 Node2 모두에게 트래픽을 전송할 수 있는데,

여기서 "externalTrafficPolicy" 옵션을 설정하면 특정 Node의 ip로 접속한 트래픽은 Servcie가

그 Node에 해당하는 pod에만 트래픽을 전송할 수 있다.

테스트를 위해 먼저 pod를 하나 더 생성한다.

현재 pod-1과 pod-2가 모두 service와 연결된 상태이다.

vagrant@kube-control1:~/tmp$ cat cluster_pod.yaml apiVersion: v1 kind: Pod metadata: name: pod-2 labels: app: pod spec: nodeSelector: kubernetes.io/hostname: kube-node2 containers: - name: container image: kubetm/app ports: - containerPort: 8080 vagrant@kube-control1:~/tmp$ kubectl get pods NAME READY STATUS RESTARTS AGE pod-1 1/1 Running 0 22m pod-2 1/1 Running 0 2m55s

Service를 생성한다.

apiVersion: v1 kind: Service metadata: name: svc-2 spec: selector: app: pod ports: - port: 9000 targetPort: 8080 nodePort: 30000 type: NodePort

생성된 서비스의 ip를 확인한 후 서비스를 통해 pod와 통신한다.

vagrant@kube-control1:~/tmp$ kubectl get svc -o wide | grep svc-2 svc-2 NodePort 10.100.175.188 9000:30000/TCP 79s app=pod

30000번 포트로 통신 시 pod-1과 pod-2 모두 표시되는 것을 확인할 수 있다.

vagrant@kube-control1:~/tmp$ curl 192.168.100.11:30000/hostname Hostname : pod-1 vagrant@kube-control1:~/tmp$ curl 192.168.100.11:30000/hostname Hostname : pod-2

마지막으로 Load Balancer 타입이다.

type이 LoadBalancer로 지정된 새로운 서비스를 생성해보자.

외부 플러그인이 설치돼있지 않다면 type 다음 줄에 externalIPs를 추가한다.

vagrant@kube-control1:~/tmp$ cat lb.yaml apiVersion: v1 kind: Service metadata: name: svc-3 spec: selector: app: pod ports: - port: 9000 targetPort: 8080 type: LoadBalancer externalIPs: - 192.168.0.10

생성된 로드밸런서를 확인한다.

vagrant@kube-control1:~/tmp$ kubectl get svc | grep svc-3 svc-3 LoadBalancer 10.110.22.180 192.168.0.10 9000:30429/TCP 5m29s

로드 밸런서와 통신 시 pod-1과 pod-2가 번갈아가면서 통신이 되는 것을 확인할 수 있다.

vagrant@kube-control1:~/tmp$ curl 192.168.0.10:9000/health pod-1 is Running vagrant@kube-control1:~/tmp$ curl 192.168.0.10:9000/health pod-2 is Running vagrant@kube-control1:~/tmp$ curl 192.168.0.10:9000/health pod-2 is Running vagrant@kube-control1:~/tmp$ curl 192.168.0.10:9000/health pod-2 is Running vagrant@kube-control1:~/tmp$ curl 192.168.0.10:9000/health pod-1 is Running

from http://public-cloud.tistory.com/54 by ccl(A) rewrite - 2021-08-20 18:26:21