[K8s] 파드(Pod) 사용-2

Aiden·2021년 6월 27일
0

K8S Study

목록 보기
4/9
post-thumbnail

1. 파드(Pod) 실습

1-1. Pod 배포

변경 상태 실시간 확인

  • 마스터 노드
watch -d 'kubectl get pod'
  • 워커 노드
watch -d 'docker ps --format "table {{.Image}}\t{{.Status}}\t{{.Names}}"'

YAML 템플릿 생성

  • 템플릿 입력
cat <<EOF > myweb.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myweb
spec:
  containers:
  - image: nginx:latest
    name: myweb-container
    ports:
    - containerPort: 80
      protocol: TCP
EOF
  • 생성한 YAML 파일 확인

YAML 파일로 Pod 배포

  • 배포
kubectl apply -f myweb.yaml
  • 확인
kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
myweb   1/1     Running   0          7m19s   172.16.235.137   worker1   <none>           <none>

watch 명령어 혹은 옵션을 통해 아래와 같이 상태 변화를 실시간으로 확인할 수 있다

  • 마스터 노드

  • 워커 노드

Pod 동작 확인

  • ping/curl
[root@master aiden (|kube:default)]# ping 172.16.235.137
PING 172.16.235.137 (172.16.235.137) 56(84) bytes of data.
64 bytes from 172.16.235.137: icmp_seq=1 ttl=63 time=0.175 ms
64 bytes from 172.16.235.137: icmp_seq=2 ttl=63 time=0.174 ms
^C
--- 172.16.235.137 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1022ms
rtt min/avg/max/mdev = 0.174/0.174/0.175/0.000 ms
[root@master aiden (|kube:default)]# curl 172.16.235.137
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
... 생략 ...

Pod 삭제

kubectl delete pod myweb

1-2. 사이드카(sidecar) 패턴

사이드카 패턴은 어플리케이션 컨테이너와 독립적으로 동작하는 별도의 컨테이너를 붙이는 패턴이다. 사이드카는 상위 애플리케이션에 연결되고 애플리케이션에 대한 지원 기능을 제공한다. 사이드카 장애 시 어플리케이션이 영향을 받지 않는다.

실습 구성

myweb2 Pod 안에 2개의 컨테이너가 동작

  • 컨테이너1: myweb2-nginx
  • 컨테이너2: myweb2-netshoot

YAML 템플릿

  • 정의 & 리소스 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: **myweb2**
spec:
  **containers**:
  - name: **myweb2-nginx**
    image: nginx
    ports:
    - containerPort: 80
      protocol: TCP

  - name: **myweb2-netshoot**
    image: nicolaka/netshoot
    command: ["/bin/bash"]
    args: ["-c", "while true; do sleep 5; curl localhost; done"] # Pod가 종료되지 않도록 유지
EOF

생성 확인

  • Pod
[root@master aiden (|kube:default)]# kubectl get pod -o wide
NAME     READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
myweb2   2/2     Running   0          4h52m   172.16.235.138   worker1   <none>           <none>
  • Pod 내부 컨테이너
[root@master aiden (|kube:default)]# kubectl describe pod myweb2
... 생략 ...
myweb2-nginx:
    Container ID:   docker://1c6c7938e5d6b7c62c2cbfffd2c07ffca0fcdf430f2518025189432e34522133
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:47ae43cdfc7064d28800bc42e79a429540c7c80168e8c8952778c0d5af1c09db
... 생략 ...
myweb2-netshoot:
    Container ID:  docker://ad902b7db93c3875600414e3182652aaa565d73136c307f949cb009318e1ff3a
    Image:         nicolaka/netshoot
    Image ID:      docker-pullable://nicolaka/netshoot@sha256:85ce79b823f8bdece01aaacb46ad5d01040f4b8544000d850fe03
... 생략 ...
  • network namespace 확인(워커노드)
root@worker1:~# docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Names}}" | grep myweb2
1c6c7938e5d6   nginx                    k8s_myweb2-nginx_myweb2_default_d0ae07e5-7c0b-4143-8dad-e67d29dcaf8f_0
ad902b7db93c   nicolaka/netshoot        k8s_myweb2-netshoot_myweb2_default_d0ae07e5-7c0b-4143-8dad-e67d29dcaf8f_0
e8d8f8fee19c   k8s.gcr.io/pause:3.4.1   k8s_POD_myweb2_default_d0ae07e5-7c0b-4143-8dad-e67d29dcaf8f_0

⇒ 내부 컨테이너가 pause 컨테이너의 network namespace를 공유

컨테이너 내부 확인(myweb2-netshoot)

  • nginx 컨테이너 웹 접속 로그 출력
[root@master aiden (|kube:default)]# kubectl logs -f myweb2 -c myweb2-nginx
... 생략 ...
127.0.0.1 - - [27/Jun/2021:03:59:34 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.77.0" "-"
127.0.0.1 - - [27/Jun/2021:03:59:39 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.77.0" "-"
127.0.0.1 - - [27/Jun/2021:03:59:44 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.77.0" "-"
... 생략 ...

⇒ myweb2-netshoot으로 부터 요청이 왔으며 IP는 127.0.0.1 이다.

  • myweb2-netshoot 컨테이너 내부로 접속
kubectl exec -it myweb2 -c myweb2-netshoot -- /bin/bash
  • 웹 접속 확인
bash-5.1# curl -s localhost | grep nginx
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
<a href="http://nginx.org/">nginx.org</a>.<br/>
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
  • IP 확인
bash-5.1# ip a
... 생략 ...
4: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP group default 
    link/ether ae:2c:04:99:5e:ae brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.16.235.138/32 brd 172.16.235.138 scope global eth0
       valid_lft forever preferred_lft forever

컨테이너 내부 확인(myweb2-nginx)

  • myweb2-nginx컨테이너 내부로 접속
kubectl exec -it myweb2 -c myweb2-nginx -- /bin/bash
  • 확인을 위한 툴 설치
apt update
apt install -y procps net-tools
  • IP확인
root@myweb2:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1480
        inet 172.16.235.138  netmask 255.255.255.255  broadcast 172.16.235.138
        ether ae:2c:04:99:5e:ae  txqueuelen 0  (Ethernet)
        RX packets 6321  bytes 9712504 (9.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3789  bytes 252598 (246.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
... 생략 ...
  • TCP 포트 확인
root@myweb2:/# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1/nginx: master pro 
tcp6       0      0 :::80                   :::*                    LISTEN      1/nginx: master pro

⇒ TCP 80 Listen 상태

Pod 삭제

  • 모든 Pod 삭제
kubectl delete pod --all

2. 레이블(Label) & 셀렉터(Selector)

  • 쿠버네티스에는 독특한 리소스 질의 체계가 존재
  • 특정 리소스(또는 리소스 그룹)에 명령을 전달하거나 정보를 확인하고 싶을 때 Labeling 시스템을 이용
  • 레이블링 시스템을 이용하여 질의하기 위해서 먼저 리소스key-value 형식의 태그정보(Label)을 붙임
  • 태깅한 리소스를 찾기 위해 셀렉터라는 것을 이용하여 특정 key-value 를 가진 리소스만 추출할 수 있음

2-1. 레이블 설정 후 셀렉터를 통한 확인

YAML 템플릿

  • labels.yaml
cat <<EOF > labels.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myweb1
  labels:
    environment: production
    app: nginx
spec:
  containers:
  - image: nginx
    name: myweb1
    ports:
    - containerPort: 80
      protocol: TCP
---
apiVersion: v1
kind: Pod
metadata:
  name: myweb2
  labels:
    environment: dev
    app: nginx
spec:
  containers:
  - image: nginx
    name: myweb2
    ports:
    - containerPort: 80
EOF

실행 및 확인

  • 파드 생성
kubectl apply -f labels.yaml
  • 생성 확인
[root@master aiden (|kube:default)]# kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
myweb1   1/1     Running   0          31s
myweb2   1/1     Running   0          31s
  • 레이블 정보 확인
[root@master aiden (|kube:default)]# kubectl get pod --show-labels
NAME     READY   STATUS    RESTARTS   AGE   LABELS
myweb1   1/1     Running   0          48s   app=nginx,environment=production
myweb2   1/1     Running   0          48s   app=nginx,environment=dev
  • 셀렉터를 통한 확인
[root@master aiden (|kube:default)]# kubectl get pod -l environment=production
NAME     READY   STATUS    RESTARTS   AGE
myweb1   1/1     Running   0          81s
[root@master aiden (|kube:default)]# kubectl get pod -l app=nginx
NAME     READY   STATUS    RESTARTS   AGE
myweb1   1/1     Running   0          94s
myweb2   1/1     Running   0          94s
  • 셀렉터를 활용하여 특정 파드 삭제 및 확인
[root@master aiden (|kube:default)]# kubectl delete pod -l environment=production
pod "myweb1" deleted
[root@master aiden (|kube:default)]# kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
myweb2   1/1     Running   0          2m26s

레이블 제거

  • 레이블 확인
[root@master aiden (|kube:default)]# kubectl get pod --show-labels
NAME     READY   STATUS    RESTARTS   AGE     LABELS
myweb2   1/1     Running   0          3m41s   app=nginx,environment=dev
  • 레이블 제거
[root@master aiden (|kube:default)]# kubectl label pod myweb2 app-
pod/myweb2 labeled
  • 레이블 확인
[root@master aiden (|kube:default)]# kubectl get pod --show-labels
NAME     READY   STATUS    RESTARTS   AGE     LABELS
myweb2   1/1     Running   0          4m18s   environment=dev

2-2. 노드셀렉터(nodeSelector) 를 이용한 파드 배포 확인

워커노드에 레이블 지정 및 확인

  • 노드 기본 레이블 정보 확인
[root@master aiden (|kube:default)]# kubectl get node --show-labels
NAME      STATUS   ROLES                  AGE   VERSION   LABELS
master    Ready    control-plane,master   11d   v1.21.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
worker1   Ready    <none>                 11d   v1.21.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker1,kubernetes.io/os=linux
worker2   Ready    <none>                 11d   v1.21.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker2,kubernetes.io/os=linux
worker3   Ready    <none>                 11d   v1.21.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker3,kubernetes.io/os=linux
  • 노드1에 레이블 설정
[root@master aiden (|kube:default)]# kubectl label node worker1 gpu=ndivia
node/worker1 labeled
[root@master aiden (|kube:default)]# kubectl get node --show-labels
NAME      STATUS   ROLES                  AGE   VERSION   LABELS
master    Ready    control-plane,master   11d   v1.21.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
worker1   Ready    <none>                 11d   v1.21.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,gpu=ndivia,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker1,kubernetes.io/os=linux
worker2   Ready    <none>                 11d   v1.21.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker2,kubernetes.io/os=linux
worker3   Ready    <none>                 11d   v1.21.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker3,kubernetes.io/os=linux

YAML 템플릿

  • labels-node.yaml

    cat <<EOF > labels-node.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: myweb
    spec:
      containers:
      - image: nginx
        name: myweb
        ports:
        - containerPort: 80
          protocol: TCP
      **nodeSelector:
        gpu: ndivia
    EOF**
    • Pod 배포 / 확인

      [root@master aiden (|kube:default)]# kubectl apply -f labels-node.yaml
      pod/myweb created
      [root@master aiden (|kube:default)]# kubectl get pod -o wide
      NAME    READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
      myweb   1/1     Running   0          45s   172.16.235.140   worker1   <none>           <none>

      Pod 추가 생성

    • 깉은 YAML 템플릿을 이용하여 Pod 3개 더 생성

      cat labels-node.yaml | sed "s/name: myweb/name: myweb2/g" | kubectl apply -f -
      cat labels-node.yaml | sed "s/name: myweb/name: myweb3/g" | kubectl apply -f -
      cat labels-node.yaml | sed "s/name: myweb/name: myweb4/g" | kubectl apply -f -
    • Pod 확인

      [root@master aiden (|kube:default)]# kubectl get pod -o wide
      NAME     READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
      myweb    1/1     Running   0          2m30s   172.16.235.140   worker1   <none>           <none>
      myweb2   1/1     Running   0          33s     172.16.235.141   worker1   <none>           <none>
      myweb3   1/1     Running   0          33s     172.16.235.142   worker1   <none>           <none>
      myweb4   1/1     Running   0          30s     172.16.235.143   worker1   <none>           <none>

      ⇒ nodeSelector를 통해 특정 노드를 선택하여 생성하였으므로, 다른 워커노드에 분산 배치되지 않음

      3. 실행 명령(Command) 및 파라미터(Args)

      파드 생성 시 Command(도커의 Entrypoint)와 Args(도커의 Cmd)를 전달할 수 있다

      3-1. 실행 명령 & 파라미터

      Pod 생성 시 실행 명령 확인

    • nginx Pod 생성 및 확인

      [root@master aiden (|kube:default)]# kubectl run cmd-args --image nginx
      pod/cmd-args created
      [root@master aiden (|kube:default)]# kubectl get pod -owide
      NAME       READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
      cmd-args   1/1     Running   0          10s   172.16.235.144   worker1   <none>           <none>
    • 워커노드에서 컨테이너 상세 정보 확인

      root@worker1:~# docker inspect `docker ps | grep cmd-args | awk '{print $1}'`
      ... 생략 ...
      						"Cmd": [
                      "nginx",
                      "-g",
                      "daemon off;"
                  ],
                  "Healthcheck": {
                      "Test": [
                          "NONE"
                      ]
                  },
                  "Image": "nginx@sha256:47ae43cdfc7064d28800bc42e79a429540c7c80168e8c8952778c0d5af1c09db",
                  "Volumes": null,
                  "WorkingDir": "",
                  "Entrypoint": [
                      "/docker-entrypoint.sh"
                  ],
      ... 생략 ...

      YAML 템플릿

    • cmd-args.yaml

      cat << EOF > cmd-args.yaml
      apiVersion: v1
      kind: Pod
      metadata:
        name: cmd-args
      spec:
        restartPolicy: OnFailure
        containers:
        - image: nginx
          name: cmd-args-nginx
          ports:
          - containerPort: 80
            protocol: TCP
          command: ["/bin/echo"]
          args: ["hello"]
      EOF
    • Pod 생성 및 확인

      [root@master aiden (|kube:default)]# kubectl apply -f cmd-args.yaml
      pod/cmd-args created
      [root@master aiden (|kube:default)]# kubectl get pod -owide
      NAME       READY   STATUS      RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
      cmd-args   0/1     Completed   0          12s   172.16.235.145   worker1   <none>           <none>
    • log 확인

      [root@master aiden (|kube:default)]# kubectl logs cmd-args
      hello
    • 워커노드에서 컨테이너 정보 확인

      root@worker1:~# docker inspect 27f58219cffa
      ... 생략 ...
      						"Cmd": [
                      "hello"
                  ],
                  "Healthcheck": {
                      "Test": [
                          "NONE"
                      ]
                  },
                  "Image": "nginx@sha256:47ae43cdfc7064d28800bc42e79a429540c7c80168e8c8952778c0d5af1c09db",
                  "Volumes": null,
                  "WorkingDir": "",
                  "Entrypoint": [
                      "/bin/echo"
                  ],
      ... 생략 ...

      3-2. 환경변수(env)

      JWT Secret Key / DB 접속정보(IP, Database 명, ID, PW) 등 Pod에 환경변수 전달 시 사용

      YAML 템플릿

    • env.yaml

      cat <<EOF > env.yaml
      apiVersion: v1
      kind: Pod
      metadata:
        name: mynginx
      spec:
        containers:
        - image: nginx:latest
          name: mynginx
          ports:
          - containerPort: 80
          env:
          - name: MYPASSWORD
            value: QWE123
      EOF
    • Pod 생성 및 확인

      [root@master aiden (|kube:default)]# kubectl apply -f env.yaml
      pod/mynginx created
      [root@master aiden (|kube:default)]# kubectl exec mynginx -- env | grep MYPASSWORD
      MYPASSWORD=QWE123
    • 워커 노드에서 확인

      root@worker1:~# docker inspect `docker ps | grep nginx | grep -v pause | awk '{print $1}'` --format '{{.Config.Env}}'
      [MYPASSWORD=QWE123 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 KUBERNETES_SERVICE_HOST=10.96.0.1 KUBERNETES_SERVICE_PORT=443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT=tcp://10.96.0.1:443 KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin NGINX_VERSION=1.21.0 NJS_VERSION=0.5.3 PKG_RELEASE=1~buster]

      ⇒ 중요한 정보일 경우 보안관리가 필요

      4. 볼륨(Volume)

      4-1. 볼륨

    • 파드 내부 스토리지는 파드가 삭제 시 저장된 데이터도 삭제된다

    • 파드 데이터를 지속적으로 저정하기 위해서는 볼륨을 사용해야 한다

    • hostPath : 워커 노드의 로컬 디렉터리를 공유해서 볼륨으로 사용

    • emptyDir : 파드가 실행되는 도중에만 필요한 데이터를 멀티 컨테이너가 함께 사용할 수 있도록 임시 저장 공간을 생성

    • 그외 어느 노드에서도 접근해 사용할 수 있는 퍼시스턴트 볼륨(Persistent Volume) ****있다

      4-2. hostPath

      YAML 템플릿

    • hostpath.yaml

      cat <<EOF > hostpath.yaml
      apiVersion: v1
      kind: Pod
      metadata:
        name: hostpath
      spec:
        containers:
          - name: hostpath
            image: busybox
            args: [ "tail", "-f", "/dev/null" ]
            volumeMounts:
            - name: hostpath-volume
              mountPath: /etc/data
        volumes:
          - name: hostpath-volume
            hostPath:
              path: /cndk
      EOF
    • Pod 생성 및 확인

      [root@master aiden (|kube:default)]# kubectl apply -f hostpath.yaml && watch "kubectl describe pod hostpath | grep Events -A 12"
      pod/hostpath created

      hostPath 확인

    • 워커노드에서 디렉토리 확인

      root@worker1:~# ls /
      bin   cdrom  dev  home  lib32  libx32      media  opt   root  sbin  srv       sys  usr
      boot  cndk   etc  lib   lib64  lost+found  mnt    proc  run   snap  swap.img  tmp  var

      ⇒ cndk 생성 확인

    • Pod에 파일 생성

      [root@master aiden (|kube:default)]# kubectl exec hostpath -- touch /etc/data/test.txt
    • 워커노드에서 확인

      root@worker1:~# ls /cndk
      test.txt
profile
기억이 안되면 기록이라도🐳

0개의 댓글