티아카데미 컨테이너 오케스트레이션 쿠버네티스 살펴보기 TIL - 쿠버네티스 주요기능 실습

2020-12-11

.

Data_Engineering_TIL(20201211)

study_program : 티아카데미 컨테이너 오케스트레이션 쿠버네티스 살펴보기

(URL : https://tacademy.skplanet.com/frontMain.action)

실습 시 참고한 URL : https://github.com/subicura/workshop-k8s-basic

  • 아래와 같이 쿠버네티스 이해를 위한 주요 개념에 대해 실습해본다.

1) kubectl

2) pod

3) replicaset

4) deployment

5) service

6) ingress

  • 실습환경 셋팅

ec2를 생성하고 ssh 접속해서 아래와 같이 명령어를 실행한다.

[ec2-user@ip-10-0-1-231 ~]$ sudo yum update -y

[ec2-user@ip-10-0-1-231 ~]$ sudo yum install jq -y

[ec2-user@ip-10-0-1-231 ~]$ sudo amazon-linux-extras install docker

[ec2-user@ip-10-0-1-231 ~]$ sudo service docker start

[ec2-user@ip-10-0-1-231 ~]$ sudo usermod -a -G docker ec2-user

[ec2-user@ip-10-0-1-231 ~]$ exit

# ssh 재접속

[ec2-user@ip-10-0-1-231 ~]$ docker info
Client:
 Debug Mode: false

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 19.03.13-ce
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 runc version: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 init version: de40ad0 (expected: fec3683)
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 4.14.193-149.317.amzn2.x86_64
 Operating System: Amazon Linux 2
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.909GiB
 Name: ip-10-0-1-231.ap-northeast-2.compute.internal
 ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

[ec2-user@ip-10-0-1-231 ~]$ curl -sfL https://get.k3s.io | sh -
[INFO]  Finding release for channel stable
[INFO]  Using v1.19.4+k3s1 as release
[INFO]  Downloading hash https://github.com/rancher/k3s/releases/download/v1.19.4+k3s1/sha256sum-amd64.txt
[INFO]  Downloading binary https://github.com/rancher/k3s/releases/download/v1.19.4+k3s1/k3s
[INFO]  Verifying binary download
[INFO]  Installing k3s to /usr/local/bin/k3s
[INFO]  Creating /usr/local/bin/kubectl symlink to k3s
[INFO]  Creating /usr/local/bin/crictl symlink to k3s
[INFO]  Skipping /usr/local/bin/ctr symlink to k3s, command exists in PATH at /usr/bin/ctr
[INFO]  Creating killall script /usr/local/bin/k3s-killall.sh
[INFO]  Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO]  env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO]  systemd: Creating service file /etc/systemd/system/k3s.service
[INFO]  systemd: Enabling k3s unit
Created symlink from /etc/systemd/system/multi-user.target.wants/k3s.service to /etc/systemd/system/k3s.service.
[INFO]  systemd: Starting k3s
    
[ec2-user@ip-10-0-1-231 ~]$ sudo chown ec2-user:ec2-user /etc/rancher/k3s/k3s.yaml
  • 기본명령어 실습

get을 이용해서 각종정보를 조회해본다.

get은 object들을 list로 조회한다.

# 쿠버네티스 클러스터 현황확인
# ec2 한대밖에없어서 하나만 보인다.
# 실제 프로덕션 환경에서는 여러대를 클러스터링해서 사용한다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get nodes
NAME                                            STATUS   ROLES    AGE   VERSION
ip-10-0-1-231.ap-northeast-2.compute.internal   Ready    master   36s   v1.19.4+k3s1

# -o wide 옵션을 주어 상세내용을 볼 수도 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get nodes -o wide
NAME                                            STATUS   ROLES    AGE   VERSION        INTERNAL-IP   EXTERNAL-IP   OS-IMAGE         KERNEL-VERSION                  CONTAINER-RUNTIME
ip-10-0-1-231.ap-northeast-2.compute.internal   Ready    master   23m   v1.19.4+k3s1   10.0.1.231    <none>        Amazon Linux 2   4.14.193-149.317.amzn2.x86_64   containerd://1.4.1-k3s1

# -o yaml 옵션을 주면 완전 자세한 내용을 확인할 수 있다.
# 쿠버네티스는 어떤형태의 상태를 관리하는 것이 목적인데 이런 상태를 체크하기에 적합한 옵션이다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get nodes -o yaml
    
# pod 현황확인
# 아직 만든게 없어서 노 리소스로 나온다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get pod
No resources found in default namespace.

[ec2-user@ip-10-0-1-231 ~]$ kubectl get replicaset
No resources found in default namespace.

[ec2-user@ip-10-0-1-231 ~]$ kubectl get deployment
No resources found in default namespace.

# 쿠버네티스에서 사용하는 서비스가 하나 보인다.
# 이거는 kubectl이 api 통신을 하기위해서 필요해서 떠있는 것이다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   9m46s

[ec2-user@ip-10-0-1-231 ~]$ kubectl get ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
No resources found in default namespace.

# 전체 오브젝트는 kubectl api-resources 명령어로 조회가 가능하다.
# 아래와 같은 리소스들이 복잡하게 얽혀서 쿠버네티스 클러스터가 동작하는 것이다.
# 하지만 실제로 사용자가 사용하는건 위에서 확인한 몇가지 것들 위주다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl api-resources
NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bindings                                                                      true         Binding
componentstatuses                 cs                                          false        ComponentStatus
configmaps                        cm                                          true         ConfigMap
endpoints                         ep                                          true         Endpoints
events                            ev                                          true         Event
limitranges                       limits                                      true         LimitRange
namespaces                        ns                                          false        Namespace
nodes                             no                                          false        Node
persistentvolumeclaims            pvc                                         true         PersistentVolumeClaim
persistentvolumes                 pv                                          false        PersistentVolume
pods                              po                                          true         Pod
podtemplates                                                                  true         PodTemplate
replicationcontrollers            rc                                          true         ReplicationController
resourcequotas                    quota                                       true         ResourceQuota
secrets                                                                       true         Secret
serviceaccounts                   sa                                          true         ServiceAccount
services                          svc                                         true         Service
mutatingwebhookconfigurations                  admissionregistration.k8s.io   false        MutatingWebhookConfiguration
validatingwebhookconfigurations                admissionregistration.k8s.io   false        ValidatingWebhookConfiguration
customresourcedefinitions         crd,crds     apiextensions.k8s.io           false        CustomResourceDefinition
apiservices                                    apiregistration.k8s.io         false        APIService
controllerrevisions                            apps                           true         ControllerRevision
daemonsets                        ds           apps                           true         DaemonSet
deployments                       deploy       apps                           true         Deployment
replicasets                       rs           apps                           true         ReplicaSet
statefulsets                      sts          apps                           true         StatefulSet
tokenreviews                                   authentication.k8s.io          false        TokenReview
localsubjectaccessreviews                      authorization.k8s.io           true         LocalSubjectAccessReview
selfsubjectaccessreviews                       authorization.k8s.io           false        SelfSubjectAccessReview
selfsubjectrulesreviews                        authorization.k8s.io           false        SelfSubjectRulesReview
subjectaccessreviews                           authorization.k8s.io           false        SubjectAccessReview
horizontalpodautoscalers          hpa          autoscaling                    true         HorizontalPodAutoscaler
cronjobs                          cj           batch                          true         CronJob
jobs                                           batch                          true         Job
certificatesigningrequests        csr          certificates.k8s.io            false        CertificateSigningRequest
leases                                         coordination.k8s.io            true         Lease
endpointslices                                 discovery.k8s.io               true         EndpointSlice
events                            ev           events.k8s.io                  true         Event
ingresses                         ing          extensions                     true         Ingress
helmchartconfigs                               helm.cattle.io                 true         HelmChartConfig
helmcharts                                     helm.cattle.io                 true         HelmChart
addons                                         k3s.cattle.io                  true         Addon
nodes                                          metrics.k8s.io                 false        NodeMetrics
pods                                           metrics.k8s.io                 true         PodMetrics
ingressclasses                                 networking.k8s.io              false        IngressClass
ingresses                         ing          networking.k8s.io              true         Ingress
networkpolicies                   netpol       networking.k8s.io              true         NetworkPolicy
runtimeclasses                                 node.k8s.io                    false        RuntimeClass
poddisruptionbudgets              pdb          policy                         true         PodDisruptionBudget
podsecuritypolicies               psp          policy                         false        PodSecurityPolicy
clusterrolebindings                            rbac.authorization.k8s.io      false        ClusterRoleBinding
clusterroles                                   rbac.authorization.k8s.io      false        ClusterRole
rolebindings                                   rbac.authorization.k8s.io      true         RoleBinding
roles                                          rbac.authorization.k8s.io      true         Role
priorityclasses                   pc           scheduling.k8s.io              false        PriorityClass
csidrivers                                     storage.k8s.io                 false        CSIDriver
csinodes                                       storage.k8s.io                 false        CSINode
storageclasses                    sc           storage.k8s.io                 false        StorageClass
volumeattachments                              storage.k8s.io                 false        VolumeAttachment

# pod, replicaset, deployment, service 한꺼번에 조회
[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   20m

# json으로 나온 결과를 파이프로 받아서 jq라는 얘가 다시 그거를 처리하는 명령어이다.
# 현재 이노드의 네임과 cpu 메모리 정보 등을 확인할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get nodes -o json | jq ".items[] | {name:.metadata.name} + .status.capacity"
{
  "name": "ip-10-0-1-231.ap-northeast-2.compute.internal",
  "cpu": "2",
  "ephemeral-storage": "31444972Ki",
  "hugepages-1Gi": "0",
  "hugepages-2Mi": "0",
  "memory": "2002012Ki",
  "pods": "110"
}
  • describe 명령어 실습

상세정보를 조회할때 사용한다.

[ec2-user@ip-10-0-1-231 ~]$ kubectl get nodes
NAME                                            STATUS   ROLES    AGE   VERSION
ip-10-0-1-231.ap-northeast-2.compute.internal   Ready    master   39m   v1.19.4+k3s1

[ec2-user@ip-10-0-1-231 ~]$ kubectl describe node ip-10-0-1-231.ap-northeast-2.compute.internal
Name:               ip-10-0-1-231.ap-northeast-2.compute.internal
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=k3s
                    beta.kubernetes.io/os=linux
                    k3s.io/hostname=ip-10-0-1-231.ap-northeast-2.compute.internal
                    k3s.io/internal-ip=10.0.1.231
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=ip-10-0-1-231.ap-northeast-2.compute.internal
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=true
                    node.kubernetes.io/instance-type=k3s
Annotations:        flannel.alpha.coreos.com/backend-data: {"VtepMAC":"xxxxxxxxxxxxxxxxxxxx"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 10.0.1.231
                    k3s.io/node-args: ["server"]
                    k3s.io/node-config-hash: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx====
                    k3s.io/node-env: {"K3S_DATA_DIR":"/var/lib/rancher/k3s/data/xxxxxxxxxxxxxxxxxxxxxxxxxx"}
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Fri, 11 Dec 2020 08:09:46 +0000
Taints:             <none>
Unschedulable:      false
Lease:
  HolderIdentity:  ip-10-0-1-231.ap-northeast-2.compute.internal
  AcquireTime:     <unset>
  RenewTime:       Fri, 11 Dec 2020 08:49:26 +0000
Conditions:
  Type                 Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----                 ------  -----------------                 ------------------                ------                       -------
  NetworkUnavailable   False   Fri, 11 Dec 2020 08:10:02 +0000   Fri, 11 Dec 2020 08:10:02 +0000   FlannelIsUp                  Flannel is running on this node
  MemoryPressure       False   Fri, 11 Dec 2020 08:45:54 +0000   Fri, 11 Dec 2020 08:09:45 +0000   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure         False   Fri, 11 Dec 2020 08:45:54 +0000   Fri, 11 Dec 2020 08:09:45 +0000   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure          False   Fri, 11 Dec 2020 08:45:54 +0000   Fri, 11 Dec 2020 08:09:45 +0000   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready                True    Fri, 11 Dec 2020 08:45:54 +0000   Fri, 11 Dec 2020 08:09:56 +0000   KubeletReady                 kubelet is posting ready status
Addresses:
  InternalIP:  10.0.1.231
  Hostname:    ip-10-0-1-231.ap-northeast-2.compute.internal
Capacity:
  cpu:                2
  ephemeral-storage:  31444972Ki
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             2002012Ki
  pods:               110
Allocatable:
  cpu:                2
  ephemeral-storage:  30589668738
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             2002012Ki
  pods:               110
System Info:
  Machine ID:                 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  System UUID:                xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  Boot ID:                    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  Kernel Version:             4.14.193-149.317.amzn2.x86_64
  OS Image:                   Amazon Linux 2
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.4.1-k3s1
  Kubelet Version:            v1.19.4+k3s1
  Kube-Proxy Version:         v1.19.4+k3s1
PodCIDR:                      10.42.0.0/24
PodCIDRs:                     10.42.0.0/24
ProviderID:                   k3s://ip-10-0-1-231.ap-northeast-2.compute.internal
Non-terminated Pods:          (5 in total)
  Namespace                   Name                                      CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                   ----                                      ------------  ----------  ---------------  -------------  ---
  kube-system                 local-path-provisioner-7ff9579c6-vkqxc    0 (0%)        0 (0%)      0 (0%)           0 (0%)         39m
  kube-system                 metrics-server-7b4f8b595-zpqnm            0 (0%)        0 (0%)      0 (0%)           0 (0%)         39m
  kube-system                 coredns-66c464876b-hllht                  100m (5%)     0 (0%)      70Mi (3%)        170Mi (8%)     39m
  kube-system                 svclb-traefik-7czk5                       0 (0%)        0 (0%)      0 (0%)           0 (0%)         39m
  kube-system                 traefik-5dd496474-brj2s                   0 (0%)        0 (0%)      0 (0%)           0 (0%)         39m
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests   Limits
  --------           --------   ------
  cpu                100m (5%)  0 (0%)
  memory             70Mi (3%)  170Mi (8%)
  ephemeral-storage  0 (0%)     0 (0%)
  hugepages-1Gi      0 (0%)     0 (0%)
  hugepages-2Mi      0 (0%)     0 (0%)
Events:
  Type     Reason                   Age                From        Message
  ----     ------                   ----               ----        -------
  Normal   Starting                 39m                kubelet     Starting kubelet.
  Warning  InvalidDiskCapacity      39m                kubelet     invalid capacity 0 on image filesystem
  Normal   NodeHasSufficientPID     39m (x2 over 39m)  kubelet     Node ip-10-0-1-231.ap-northeast-2.compute.internal status is now: NodeHasSufficientPID
  Normal   NodeHasSufficientMemory  39m (x2 over 39m)  kubelet     Node ip-10-0-1-231.ap-northeast-2.compute.internal status is now: NodeHasSufficientMemory
  Normal   NodeHasNoDiskPressure    39m (x2 over 39m)  kubelet     Node ip-10-0-1-231.ap-northeast-2.compute.internal status is now: NodeHasNoDiskPressure
  Normal   NodeAllocatableEnforced  39m                kubelet     Updated Node Allocatable limit across pods
  Normal   Starting                 39m                kube-proxy  Starting kube-proxy.
  Normal   NodeReady                39m                kubelet     Node ip-10-0-1-231.ap-northeast-2.compute.internal status is now: NodeReady
    

[ec2-user@ip-10-0-1-231 ~]$ kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   50m

[ec2-user@ip-10-0-1-231 ~]$ kubectl describe service kubernetes
Name:              kubernetes
Namespace:         default
Labels:            component=apiserver
                   provider=kubernetes
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP:                10.43.0.1
Port:              https  443/TCP
TargetPort:        6443/TCP
Endpoints:         10.0.1.231:6443
Session Affinity:  None
Events:            <none>
  • 가장 자주 사용하는 명령어는 아래와 같다.

kubectl exec -it

–> exec 명령어를 이용해서 특정 컨테이너에 접속할때

kubectl logs -f <POD_NAME TYPE/NAME>

–> 로그를 확인하거나

kubectl apply -f

–> 사용자가 정의한 상태를 apply

kubectl delete -f

–> 사용자가 정의한 상태를 delete

  • 쿠버네티스의 배포단위인 pod을 만들어보자

프로덕션 환경에서는 yaml파일로 다 정의해놓고 pod을 만드는게 일반적이다.

# whoami 라는 이미지 속성을 넣어서 만들어보자.
# 네트워크가 연결되어 있지 않은 웹서비스 형태의 컨테이너를 실행시킨다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl run whoami --image subicura/whoami:1
pod/whoami created

[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
whoami   1/1     Running   0          39s

[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP          NODE                                            NOMINATED NODE   READINESS GATES
whoami   1/1     Running   0          66s   10.42.0.8   ip-10-0-1-231.ap-northeast-2.compute.internal   <none>           <none>

[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods -o yaml
apiVersion: v1
items:
- apiVersion: v1
  kind: Pod
  metadata:
    creationTimestamp: "2020-12-11T09:11:26Z"
    labels:
      run: whoami
    managedFields:
    - apiVersion: v1
      fieldsType: FieldsV1
      fieldsV1:
        f:metadata:
          f:labels:
            .: {}
            f:run: {}
        f:spec:
          f:containers:
            k:{"name":"whoami"}:
              .: {}
              f:image: {}
              f:imagePullPolicy: {}
              f:name: {}
              f:resources: {}
              f:terminationMessagePath: {}
              f:terminationMessagePolicy: {}
          f:dnsPolicy: {}
          f:enableServiceLinks: {}
          f:restartPolicy: {}
          f:schedulerName: {}
          f:securityContext: {}
          f:terminationGracePeriodSeconds: {}
      manager: kubectl-run
      operation: Update
      time: "2020-12-11T09:11:26Z"
    - apiVersion: v1
      fieldsType: FieldsV1
      fieldsV1:
        f:status:
          f:conditions:
            k:{"type":"ContainersReady"}:
              .: {}
              f:lastProbeTime: {}
              f:lastTransitionTime: {}
              f:status: {}
              f:type: {}
            k:{"type":"Initialized"}:
              .: {}
              f:lastProbeTime: {}
              f:lastTransitionTime: {}
              f:status: {}
              f:type: {}
            k:{"type":"Ready"}:
              .: {}
              f:lastProbeTime: {}
              f:lastTransitionTime: {}
              f:status: {}
              f:type: {}
          f:containerStatuses: {}
          f:hostIP: {}
          f:phase: {}
          f:podIP: {}
          f:podIPs:
            .: {}
            k:{"ip":"xxxxxxxxxxxxxxx"}:
              .: {}
              f:ip: {}
          f:startTime: {}
      manager: k3s
      operation: Update
      time: "2020-12-11T09:11:36Z"
    name: whoami
    namespace: default
    resourceVersion: "3162"
    selfLink: /api/v1/namespaces/default/pods/whoami
    uid: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  spec:
    containers:
    - image: subicura/whoami:1
      imagePullPolicy: IfNotPresent
      name: whoami
      resources: {}
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
      volumeMounts:
      - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
        name: default-token-bklrx
        readOnly: true
    dnsPolicy: ClusterFirst
    enableServiceLinks: true
    nodeName: ip-10-0-1-231.ap-northeast-2.compute.internal
    preemptionPolicy: PreemptLowerPriority
    priority: 0
    restartPolicy: Always
    schedulerName: default-scheduler
    securityContext: {}
    serviceAccount: default
    serviceAccountName: default
    terminationGracePeriodSeconds: 30
    tolerations:
    - effect: NoExecute
      key: node.kubernetes.io/not-ready
      operator: Exists
      tolerationSeconds: 300
    - effect: NoExecute
      key: node.kubernetes.io/unreachable
      operator: Exists
      tolerationSeconds: 300
    volumes:
    - name: default-token-bklrx
      secret:
        defaultMode: 420
        secretName: default-token-bklrx
  status:
    conditions:
    - lastProbeTime: null
      lastTransitionTime: "2020-12-11T09:11:26Z"
      status: "True"
      type: Initialized
    - lastProbeTime: null
      lastTransitionTime: "2020-12-11T09:11:36Z"
      status: "True"
      type: Ready
    - lastProbeTime: null
      lastTransitionTime: "2020-12-11T09:11:36Z"
      status: "True"
      type: ContainersReady
    - lastProbeTime: null
      lastTransitionTime: "2020-12-11T09:11:26Z"
      status: "True"
      type: PodScheduled
    containerStatuses:
    - containerID: containerd://1c9288f23c00f9dd1eb867afb0e6d4febf05328939370d9dbc2b512de44598ee
      image: docker.io/subicura/whoami:1
      imageID: docker.io/subicura/whoami@sha256:b560f146bf9cf80ee34bd495ce04dc9661292086781364d36125ef6fc9292fc9
      lastState: {}
      name: whoami
      ready: true
      restartCount: 0
      started: true
      state:
        running:
          startedAt: "2020-12-11T09:11:36Z"
    hostIP: 10.0.1.231
    phase: Running
    podIP: 10.42.0.8
    podIPs:
    - ip: 10.42.0.8
    qosClass: BestEffort
    startTime: "2020-12-11T09:11:26Z"
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""
    
[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods -o json
{
    "apiVersion": "v1",
    "items": [
        {
            "apiVersion": "v1",
            "kind": "Pod",
            "metadata": {
                "creationTimestamp": "2020-12-11T09:11:26Z",
                "labels": {
                    "run": "whoami"
                },
                "managedFields": [
                    {
                        "apiVersion": "v1",
                        "fieldsType": "FieldsV1",
                        "fieldsV1": {
                            "f:metadata": {
                                "f:labels": {
                                    ".": {},
                                    "f:run": {}
                                }
                            },
                            "f:spec": {
                                "f:containers": {
                                    "k:{\"name\":\"whoami\"}": {
                                        ".": {},
                                        "f:image": {},
                                        "f:imagePullPolicy": {},
                                        "f:name": {},
                                        "f:resources": {},
                                        "f:terminationMessagePath": {},
                                        "f:terminationMessagePolicy": {}
                                    }
                                },
                                "f:dnsPolicy": {},
                                "f:enableServiceLinks": {},
                                "f:restartPolicy": {},
                                "f:schedulerName": {},
                                "f:securityContext": {},
                                "f:terminationGracePeriodSeconds": {}
                            }
                        },
                        "manager": "kubectl-run",
                        "operation": "Update",
                        "time": "2020-12-11T09:11:26Z"
                    },
                    {
                        "apiVersion": "v1",
                        "fieldsType": "FieldsV1",
                        "fieldsV1": {
                            "f:status": {
                                "f:conditions": {
                                    "k:{\"type\":\"ContainersReady\"}": {
                                        ".": {},
                                        "f:lastProbeTime": {},
                                        "f:lastTransitionTime": {},
                                        "f:status": {},
                                        "f:type": {}
                                    },
                                    "k:{\"type\":\"Initialized\"}": {
                                        ".": {},
                                        "f:lastProbeTime": {},
                                        "f:lastTransitionTime": {},
                                        "f:status": {},
                                        "f:type": {}
                                    },
                                    "k:{\"type\":\"Ready\"}": {
                                        ".": {},
                                        "f:lastProbeTime": {},
                                        "f:lastTransitionTime": {},
                                        "f:status": {},
                                        "f:type": {}
                                    }
                                },
                                "f:containerStatuses": {},
                                "f:hostIP": {},
                                "f:phase": {},
                                "f:podIP": {},
                                "f:podIPs": {
                                    ".": {},
                                    "k:{\"ip\":\"10.42.0.8\"}": {
                                        ".": {},
                                        "f:ip": {}
                                    }
                                },
                                "f:startTime": {}
                            }
                        },
                        "manager": "k3s",
                        "operation": "Update",
                        "time": "2020-12-11T09:11:36Z"
                    }
                ],
                "name": "whoami",
                "namespace": "default",
                "resourceVersion": "3162",
                "selfLink": "/api/v1/namespaces/default/pods/whoami",
                "uid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            },
            "spec": {
                "containers": [
                    {
                        "image": "subicura/whoami:1",
                        "imagePullPolicy": "IfNotPresent",
                        "name": "whoami",
                        "resources": {},
                        "terminationMessagePath": "/dev/termination-log",
                        "terminationMessagePolicy": "File",
                        "volumeMounts": [
                            {
                                "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
                                "name": "default-token-bklrx",
                                "readOnly": true
                            }
                        ]
                    }
                ],
                "dnsPolicy": "ClusterFirst",
                "enableServiceLinks": true,
                "nodeName": "ip-10-0-1-231.ap-northeast-2.compute.internal",
                "preemptionPolicy": "PreemptLowerPriority",
                "priority": 0,
                "restartPolicy": "Always",
                "schedulerName": "default-scheduler",
                "securityContext": {},
                "serviceAccount": "default",
                "serviceAccountName": "default",
                "terminationGracePeriodSeconds": 30,
                "tolerations": [
                    {
                        "effect": "NoExecute",
                        "key": "node.kubernetes.io/not-ready",
                        "operator": "Exists",
                        "tolerationSeconds": 300
                    },
                    {
                        "effect": "NoExecute",
                        "key": "node.kubernetes.io/unreachable",
                        "operator": "Exists",
                        "tolerationSeconds": 300
                    }
                ],
                "volumes": [
                    {
                        "name": "default-token-bklrx",
                        "secret": {
                            "defaultMode": 420,
                            "secretName": "default-token-bklrx"
                        }
                    }
                ]
            },
            "status": {
                "conditions": [
                    {
                        "lastProbeTime": null,
                        "lastTransitionTime": "2020-12-11T09:11:26Z",
                        "status": "True",
                        "type": "Initialized"
                    },
                    {
                        "lastProbeTime": null,
                        "lastTransitionTime": "2020-12-11T09:11:36Z",
                        "status": "True",
                        "type": "Ready"
                    },
                    {
                        "lastProbeTime": null,
                        "lastTransitionTime": "2020-12-11T09:11:36Z",
                        "status": "True",
                        "type": "ContainersReady"
                    },
                    {
                        "lastProbeTime": null,
                        "lastTransitionTime": "2020-12-11T09:11:26Z",
                        "status": "True",
                        "type": "PodScheduled"
                    }
                ],
                "containerStatuses": [
                    {
                        "containerID": "containerd://1c9288f23c00f9dd1eb867afb0e6d4febf05328939370d9dbc2b512de44598ee",
                        "image": "docker.io/subicura/whoami:1",
                        "imageID": "docker.io/subicura/whoami@sha256:b560f146bf9cf80ee34bd495ce04dc9661292086781364d36125ef6fc9292fc9",
                        "lastState": {},
                        "name": "whoami",
                        "ready": true,
                        "restartCount": 0,
                        "started": true,
                        "state": {
                            "running": {
                                "startedAt": "2020-12-11T09:11:36Z"
                            }
                        }
                    }
                ],
                "hostIP": "10.0.1.231",
                "phase": "Running",
                "podIP": "10.42.0.8",
                "podIPs": [
                    {
                        "ip": "10.42.0.8"
                    }
                ],
                "qosClass": "BestEffort",
                "startTime": "2020-12-11T09:11:26Z"
            }
        }
    ],
    "kind": "List",
    "metadata": {
        "resourceVersion": "",
        "selfLink": ""
    }
}

# 아래와 같은 명령어로 생성한 pod에 대해 log를 확인해보자.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
whoami   1/1     Running   0          6m20s

# pod에서 실행된 컨테이너의 로그를 확인할 수 있다.
# 현재서버에서 돌던 다른서버에서 돌던 알아서 api서버가 모아서 보여주기 때문에 한곳에서 모든 로그를 확인할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl logs -f whoami
[2020-12-11 09:11:37] INFO  WEBrick 1.3.1
[2020-12-11 09:11:37] INFO  ruby 2.3.3 (2016-11-21) [x86_64-linux]
== Sinatra (v1.4.7) has taken the stage on 4567 for development with backup from WEBrick
[2020-12-11 09:11:37] INFO  WEBrick::HTTPServer#start: pid=7 port=4567
^C

# 직접 접속해서 들어갈 수도 있다.
# 이거 역시 이게 어떤 노드에 존재하는지 몰라도 이 명령어를 실행하면 api가 알아서 프록시 연결로 연결을 해준다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl exec -it whoami sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/usr/src/app #
/usr/src/app # ls -al
total 16
drwxr-xr-x    1 root     root            73 Feb 10  2017 .
drwxr-xr-x    1 root     root            17 Feb 10  2017 ..
-rw-r--r--    1 root     root           193 Feb 11  2017 Dockerfile
-rw-r--r--    1 root     root            44 Feb 11  2017 Gemfile
-rw-r--r--    1 root     root           280 Feb 11  2017 Gemfile.lock
-rw-r--r--    1 root     root            73 Feb 11  2017 app.rb
/usr/src/app # cat app.rb
require 'sinatra'
require 'socket'

get '/' do
  Socket.gethostname
end

/usr/src/app #
/usr/src/app # exit

# 또한 describe 명령으로 pod의 상세정보를 확인할 수 있다.
# 여기서 중요한 내용은 Events이다.
# 이벤트 부분을 보면 스케쥴러가 assign 해줬고, 내부적으로 도커이미지가 없으니까 pulling했고,
# 컨테이너를 생성하고, 러닝까지 했다는 것을 알 수 있다.
# 쿠버네티스를 쓰다보면 뭔가 실행을 했는데 pod이 안뜨는 경우가 있다. 이따 describe pod 명령을 이용하면 좋다.
# 이벤트에 어떤 Error가 났는지 다 확인할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl describe pod whoami
Name:         whoami
Namespace:    default
Priority:     0
Node:         ip-10-0-1-231.ap-northeast-2.compute.internal/10.0.1.231
Start Time:   Fri, 11 Dec 2020 09:11:26 +0000
Labels:       run=whoami
Annotations:  <none>
Status:       Running
IP:           10.42.0.8
IPs:
  IP:  10.42.0.8
Containers:
  whoami:
    Container ID:   containerd://1c9288f23c00f9dd1eb867afb0e6d4febf05328939370d9dbc2b512de44598ee
    Image:          subicura/whoami:1
    Image ID:       docker.io/subicura/whoami@sha256:b560f146bf9cf80ee34bd495ce04dc9661292086781364d36125ef6fc9292fc9
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 11 Dec 2020 09:11:36 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bklrx (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-bklrx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-bklrx
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  29m   default-scheduler  Successfully assigned default/whoami to ip-10-0-1-231.ap-northeast-2.compute.internal
  Normal  Pulling    29m   kubelet            Pulling image "subicura/whoami:1"
  Normal  Pulled     28m   kubelet            Successfully pulled image "subicura/whoami:1" in 9.413830827s
  Normal  Created    28m   kubelet            Created container whoami
  Normal  Started    28m   kubelet            Started container whoami


# 생성한 pod을 삭제해보자.
# 참고로 deployment라는 것은 pod을 원하는 갯수를 생성을해준다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl delete pod whoami
pod "whoami" deleted

[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods
No resources found in default namespace.

[ec2-user@ip-10-0-1-231 ~]$ kubectl get deployment
No resources found in default namespace.
  • YAML 파일 예제

그러면 위에 명령어 위주로 pod을 실행했는데

yaml 형태로 정의해서 실습을 해보자.

[ec2-user@ip-10-0-1-231 ~]$ mkdir guide-03

[ec2-user@ip-10-0-1-231 ~]$ mkdir guide-03/task-02

[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-02/whoami-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: whoami
  labels:
    type: app
spec:
  containers:
  - name: app
    image: subicura/whoami:1
            
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-02/whoami-pod.yml
pod/whoami created

[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
whoami   1/1     Running   0          46s

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME         READY   STATUS    RESTARTS   AGE
pod/whoami   1/1     Running   0          2m54s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   110m

pod이 생성되는 과정을 보면 컨테이너를 생성하라고 지시하고, 해당 이미지를 다운로드를 받을 것이다. 그 다음에 컨테이너가 러닝이 되는데 러닝이 된다는 것은 process가 실행이 된다는 것이고, 근데 해당 process는 실행이 되자마자 바로 application을 요청을 받을수는 없을 것이다. 예를 들어서 예를 들어서 웹서비스를 띄운다고 하면 웹이 구동되는 시간이 있기 때문이다. 따라서 컨테이너가 running하는 시간과 최종적으로 application이 running되는 시간 사이에는 약간의 겝이 있다. 아직 app이 running되지 않았는데 네트워크를 연결하게 되면 error가 날 것이다. 따라서 그 웹이 구동되는 겝동안에 상태를 체크할 수 있는 값을 줄 수 있다. app이 실행되고나서도 주기적으로 체크를 하면서 컨테이너가 정상인지 아닌지를 판단을 하고, 정상이 아니면 자체적으로 재시작을 해서 정상여부를 확인을 한다.

이를 확인하는게 하나는 app이 실행되고나서 컨테이너가 정상인지 체크하는 livenessProbe라는게 있고, app이 준비가 잘 되었는지 체크하는 readinessProbe 라는게 있다.

아래에 작성하는 두 yaml에는 네트워크가 안되도록 작성이 된 내용이다. 따라서 해당 yaml을 실행하면 네트워크가 연결이 안되어서 error가 나는 것을 확인해보고자 한다.

  • livenessProbe 예제
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-02/whoami-pod-lp.yml
apiVersion: v1
kind: Pod
metadata:
  name: whoami-lp
  labels:
    type: app
spec:
  containers:
  - name: app
    image: subicura/whoami:1
    livenessProbe:
      httpGet:
        path: /not/exist
        port: 8080
      initialDelaySeconds: 5
      timeoutSeconds: 2 # Default 1
      periodSeconds: 5 # Defaults 10
      failureThreshold: 1 # Defaults 3
        
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-02/whoami-pod-lp.yml
pod/whoami-lp created

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME            READY   STATUS    RESTARTS   AGE
pod/whoami      1/1     Running   0          17m
pod/whoami-lp   1/1     Running   0          27s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   125m

# Liveness probe 상태가 지속적으로 fail난다는 것을 확인해서 계속 재시도하다가 killing을 시킨것을 알 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl describe pod/whoami-lp
Name:         whoami-lp
Namespace:    default
Priority:     0
Node:         ip-10-0-1-231.ap-northeast-2.compute.internal/10.0.1.231
Start Time:   Fri, 11 Dec 2020 10:14:50 +0000
Labels:       type=app
Annotations:  <none>
Status:       Running
IP:           10.42.0.10
IPs:
  IP:  10.42.0.10
Containers:
  app:
    Container ID:   containerd://2fbcea98f85dbd9c513ab0ea994ea07cf12427ca85157ba1a4451797cfbc3ba7
    Image:          subicura/whoami:1
    Image ID:       docker.io/subicura/whoami@sha256:b560f146bf9cf80ee34bd495ce04dc9661292086781364d36125ef6fc9292fc9
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 11 Dec 2020 10:16:01 +0000
    Last State:     Terminated
      Reason:       Error
      Exit Code:    137
      Started:      Fri, 11 Dec 2020 10:15:26 +0000
      Finished:     Fri, 11 Dec 2020 10:16:01 +0000
    Ready:          True
    Restart Count:  2
    Liveness:       http-get http://:8080/not/exist delay=5s timeout=2s period=5s #success=1 #failure=1
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bklrx (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-bklrx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-bklrx
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  77s               default-scheduler  Successfully assigned default/whoami-lp to ip-10-0-1-231.ap-northeast-2.compute.internal
  Normal   Pulled     6s (x3 over 77s)  kubelet            Container image "subicura/whoami:1" already present on machine
  Normal   Created    6s (x3 over 77s)  kubelet            Created container app
  Normal   Started    6s (x3 over 76s)  kubelet            Started container app
  Warning  Unhealthy  1s (x3 over 71s)  kubelet            Liveness probe failed: Get "http://10.42.0.10:8080/not/exist": dial tcp 10.42.0.10:8080: connect: connection refused
  Normal   Killing    1s (x3 over 71s)  kubelet            Container app failed liveness probe, will be restarted
  • readinessProbe 예제
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-02/whoami-pod-rp.yml
apiVersion: v1
kind: Pod
metadata:
  name: whoami-rp
  labels:
    type: app
spec:
  containers:
  - name: app
    image: subicura/whoami:1
    readinessProbe:
      httpGet:
        path: /not/exist
        port: 8080
      initialDelaySeconds: 5
      timeoutSeconds: 2 # Default 1
      periodSeconds: 5 # Defaults 10
      failureThreshold: 1 # Defaults 3

[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-02/whoami-pod-rp.yml
pod/whoami-rp created

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME            READY   STATUS             RESTARTS   AGE
pod/whoami      1/1     Running            0          45m
pod/whoami-lp   0/1     CrashLoopBackOff   13         28m
pod/whoami-rp   0/1     Running            0          8s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   153m

# pod/whoami-rp   0/1 를 봤을때 아예 뜨지 못하고 있는 모습을 확인할 수 있다.
# 상태를 아래와 같이 체크를 해보니 접속을 계속 시도하고 있는데 네트워크 접속이 안되고 있는 것을 알 수 있다.
# restart를 지정된 횟수가 넘어가 버리면 killing 된다.

[ec2-user@ip-10-0-1-231 ~]$ kubectl describe pod/whoami-rp
Name:         whoami-rp
Namespace:    default
Priority:     0
Node:         ip-10-0-1-231.ap-northeast-2.compute.internal/10.0.1.231
Start Time:   Fri, 11 Dec 2020 10:42:56 +0000
Labels:       type=app
Annotations:  <none>
Status:       Running
IP:           10.42.0.11
IPs:
  IP:  10.42.0.11
Containers:
  app:
    Container ID:   containerd://bb4127257fb82eb13625166274cc4ba0eb31c21e917efe32f4b62a070ca0eb61
    Image:          subicura/whoami:1
    Image ID:       docker.io/subicura/whoami@sha256:b560f146bf9cf80ee34bd495ce04dc9661292086781364d36125ef6fc9292fc9
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 11 Dec 2020 10:42:57 +0000
    Ready:          False
    Restart Count:  0
    Readiness:      http-get http://:8080/not/exist delay=5s timeout=2s period=5s #success=1 #failure=1
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bklrx (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
Volumes:
  default-token-bklrx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-bklrx
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age                   From               Message
  ----     ------     ----                  ----               -------
  Normal   Scheduled  2m55s                 default-scheduler  Successfully assigned default/whoami-rp to ip-10-0-1-231.ap-northeast-2.compute.internal
  Normal   Pulled     2m55s                 kubelet            Container image "subicura/whoami:1" already present on machine
  Normal   Created    2m55s                 kubelet            Created container app
  Normal   Started    2m55s                 kubelet            Started container app
  Warning  Unhealthy  61s (x22 over 2m46s)  kubelet            Readiness probe failed: Get "http://10.42.0.11:8080/not/exist": dial tcp 10.42.0.11:8080: connect: connection refused
  • health check 예제

livenessProbe와 readinessProbe를 전반적으로 체크하는 예제이다.

위에 있던 예제들은 일부러 네트워크가 안되도록 yaml을 작성해준 것이고, 아래의 yaml에서 4567 포트는 통신이 가능한 포트로 아래와 같이 yaml을 작성해서 실행하면 정상적으로 실행이 되는 것을 확인할 수 있다.

[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-02/whoami-pod-health.yml
apiVersion: v1
kind: Pod
metadata:
  name: whoami-health
  labels:
    type: app
spec:
  containers:
  - name: app
    image: subicura/whoami:1
    livenessProbe:
      httpGet:
        path: /
        port: 4567
    readinessProbe:
      httpGet:
        path: /
        port: 4567

[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-02/whoami-pod-health.yml
pod/whoami-health created

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                READY   STATUS             RESTARTS   AGE
pod/whoami          1/1     Running            0          51m
pod/whoami-rp       0/1     Running            0          6m52s
pod/whoami-lp       0/1     CrashLoopBackOff   15         34m
pod/whoami-health   0/1     Running            0          5s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   160m

[ec2-user@ip-10-0-1-231 ~]$ kubectl describe pod/whoami-health
Name:         whoami-health
Namespace:    default
Priority:     0
Node:         ip-10-0-1-231.ap-northeast-2.compute.internal/10.0.1.231
Start Time:   Fri, 11 Dec 2020 10:49:43 +0000
Labels:       type=app
Annotations:  <none>
Status:       Running
IP:           10.42.0.12
IPs:
  IP:  10.42.0.12
Containers:
  app:
    Container ID:   containerd://3f6612c361698a62850363c6a20a51f075ff916d6b1f67639ad72a8ae170e3f8
    Image:          subicura/whoami:1
    Image ID:       docker.io/subicura/whoami@sha256:b560f146bf9cf80ee34bd495ce04dc9661292086781364d36125ef6fc9292fc9
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 11 Dec 2020 10:49:44 +0000
    Ready:          True
    Restart Count:  0
    Liveness:       http-get http://:4567/ delay=0s timeout=1s period=10s #success=1 #failure=3
    Readiness:      http-get http://:4567/ delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bklrx (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-bklrx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-bklrx
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  21s   default-scheduler  Successfully assigned default/whoami-health to ip-10-0-1-231.ap-northeast-2.compute.internal
  Normal  Pulled     20s   kubelet            Container image "subicura/whoami:1" already present on machine
  Normal  Created    20s   kubelet            Created container app
  Normal  Started    20s   kubelet            Started container app

지금까지는 pod 안에 컨테이너가 하나 있는거만 했는데 pod 하나에 두개 이상을 넣을 수도 있다.

  • multi-container 예제

pod 안에 정의된 컨테이너는 동일한 ip를 사용한다. docker-compose 같은 경우에는 같은 네트워크 대역을 쓸뿐이지 같은 아이피주소를 쓰지는 않았지만 이 pod 안에서 뜨는 여러개의 컨테이너는 동일한 ip를 쓰고 서로다른 포트를 이용을 해서 통신을 한다.

[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-02/whoami-pod-redis.yml
apiVersion: v1
kind: Pod
metadata:
  name: whoami-redis
  labels:
    type: stack
spec:
  containers:
  - name: app
    image: subicura/whoami-redis:1
    env:
    - name: REDIS_HOST
      value: "localhost"
  - name: db
    image: redis

[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-02/whoami-pod-redis.yml
pod/whoami-redis created

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                READY   STATUS              RESTARTS   AGE
pod/whoami          1/1     Running             0          66m
pod/whoami-rp       0/1     Running             0          21m
pod/whoami-health   1/1     Running             0          14m
pod/whoami-lp       0/1     CrashLoopBackOff    19         49m
pod/whoami-redis    0/2     ContainerCreating   0          4s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   174m
[ec2-user@ip-10-0-1-231 ~]$ kubectl describe pod/whoami-redis
Name:         whoami-redis
Namespace:    default
Priority:     0
Node:         ip-10-0-1-231.ap-northeast-2.compute.internal/10.0.1.231
Start Time:   Fri, 11 Dec 2020 11:04:20 +0000
Labels:       type=stack
Annotations:  <none>
Status:       Pending
IP:
IPs:          <none>
Containers:
  app:
    Container ID:
    Image:          subicura/whoami-redis:1
    Image ID:
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Environment:
      REDIS_HOST:  localhost
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bklrx (ro)
  db:
    Container ID:
    Image:          redis
    Image ID:
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bklrx (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             False
  ContainersReady   False
  PodScheduled      True
Volumes:
  default-token-bklrx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-bklrx
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  12s   default-scheduler  Successfully assigned default/whoami-redis to ip-10-0-1-231.ap-northeast-2.compute.internal
  Normal  Pulling    12s   kubelet            Pulling image "subicura/whoami-redis:1"
    
[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                READY   STATUS             RESTARTS   AGE
pod/whoami          1/1     Running            0          67m
pod/whoami-rp       0/1     Running            0          22m
pod/whoami-health   1/1     Running            0          15m
pod/whoami-lp       0/1     CrashLoopBackOff   19         50m
pod/whoami-redis    2/2     Running            0          63s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   175m

# 이 pod 안에는 컨테이너가 두개 띄어져 있으니까 어떤 service에 대한 log를 보고 싶은지 몰라서 Error가 난다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl logs pod/whoami-redis
error: a container name must be specified for pod whoami-redis, choose one of: [app db]
        
[ec2-user@ip-10-0-1-231 ~]$ kubectl logs pod/whoami-redis app
[2020-12-11 11:04:36] INFO  WEBrick 1.3.1
[2020-12-11 11:04:36] INFO  ruby 2.3.8 (2018-10-18) [x86_64-linux-musl]
== Sinatra (v2.0.4) has taken the stage on 4567 for development with backup from WEBrick
[2020-12-11 11:04:36] INFO  WEBrick::HTTPServer#start: pid=1 port=4567
        
[ec2-user@ip-10-0-1-231 ~]$ kubectl logs pod/whoami-redis db
1:C 11 Dec 2020 11:04:44.031 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 11 Dec 2020 11:04:44.031 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 11 Dec 2020 11:04:44.031 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 11 Dec 2020 11:04:44.033 * Running mode=standalone, port=6379.
1:M 11 Dec 2020 11:04:44.033 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 11 Dec 2020 11:04:44.033 # Server initialized
1:M 11 Dec 2020 11:04:44.033 * Ready to accept connections

# 아래 명령어와 같이 컨테이너에 직접 들어갈수도 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl exec -it whoami-redis -c db sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# ls -al
total 0
drwxr-xr-x 2 redis redis  6 Nov 18 08:28 .
drwxr-xr-x 1 root  root  28 Dec 11 11:04 ..
# exit

# app이라는 컨테이너에 접속했는데 여기서 redis에 접속이 가능한지 테스트를 해보자.
# redis는 별도의 컨테이너이기 때문에 접속이 가능한지, 같은 아이피를 사용중인지 체크해본다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl exec -it whoami-redis -c app sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/usr/src/app # apk add curl busybox-extras
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
(1/5) Installing busybox-extras (1.28.4-r3)
Executing busybox-extras-1.28.4-r3.post-install
(2/5) Installing nghttp2-libs (1.39.2-r0)
(3/5) Installing libssh2 (1.9.0-r1)
(4/5) Installing libcurl (7.61.1-r3)
(5/5) Installing curl (7.61.1-r3)
Executing busybox-1.28.4-r1.trigger
OK: 16 MiB in 35 packages
/usr/src/app # curl localhost:4567
1
/usr/src/app # curl localhost:4567
2
/usr/src/app # curl localhost:4567
3
/usr/src/app # curl localhost:4567
4
/usr/src/app # telnet localhost 6379
dbsize
:1
keys *
*1
$5
count
GET count
$1
4
quit
+OK
Connection closed by foreign host
/usr/src/app # exit
command terminated with exit code 1

[ec2-user@ip-10-0-1-231 ~]$ kubectl describe pod/whoami-redis
Name:         whoami-redis
Namespace:    default
Priority:     0
Node:         ip-10-0-1-231.ap-northeast-2.compute.internal/10.0.1.231
Start Time:   Fri, 11 Dec 2020 11:04:20 +0000
Labels:       type=stack
Annotations:  <none>
Status:       Running
IP:           10.42.0.13
IPs:
  IP:  10.42.0.13
Containers:
  app:
    Container ID:   containerd://64b0072264f511098ed05a0232b10fa1b3144bb06e1109caafc43c71c3fdfa6a
    Image:          subicura/whoami-redis:1
    Image ID:       docker.io/subicura/whoami-redis@sha256:4ebb7fcc2adc99f72aaf33f5a7a49c4f516aa413e87177542554573cb93c9454
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 11 Dec 2020 11:04:35 +0000
    Ready:          True
    Restart Count:  0
    Environment:
      REDIS_HOST:  localhost
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bklrx (ro)
  db:
    Container ID:   containerd://139ed68e3d9ece9956402d818b7e243d52d6d1fdc393316b2d3966822994e17d
    Image:          redis
    Image ID:       docker.io/library/redis@sha256:e2ae53ef2864fca0a117f9b80f287e2890dd1036271dd363c20b9dfc54a8664c
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 11 Dec 2020 11:04:44 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bklrx (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-bklrx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-bklrx
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  15m   default-scheduler  Successfully assigned default/whoami-redis to ip-10-0-1-231.ap-northeast-2.compute.internal
  Normal  Pulling    15m   kubelet            Pulling image "subicura/whoami-redis:1"
  Normal  Pulled     15m   kubelet            Successfully pulled image "subicura/whoami-redis:1" in 13.5701249s
  Normal  Created    15m   kubelet            Created container app
  Normal  Started    15m   kubelet            Started container app
  Normal  Pulling    15m   kubelet            Pulling image "redis"
  Normal  Pulled     15m   kubelet            Successfully pulled image "redis" in 8.099270678s
  Normal  Created    15m   kubelet            Created container db
  Normal  Started    15m   kubelet            Started container db
  • 지금까지 실습했던 yaml을 싹 정리해주자.
[ec2-user@ip-10-0-1-231 ~]$ kubectl delete -f ./guide-03/task-02/
pod "whoami-health" deleted
pod "whoami-lp" deleted
pod "whoami-redis" deleted
pod "whoami-rp" deleted
pod "whoami" deleted
  • Replicaset 실습

앞에서 만든 pod을 replicaset으로 만들어보자.

아래에서 replicaset은 1개로 할거고, selector는 리플리카셋 입장에서는 해당하는 라벨에 pod이 있는지 없는지를 판단한다. 타입이 app이고 service가 whoami라는 이름의 pod이 1개가 있는지를 체크한다. template는 만약에 타입이 app이고 service가 whoami라는 이름의 pod이 1개가 있는지를 체크를 해봤는데 해당하는 pod이 없으면 template 이해의 명세대로 pod을 만들라는 의미다. pod에 metadata를 보면 타입이 app이고 service가 whoami라는 라벨을 가진 pod을 만들거고 그 pod의 컨테이너는 subicura/whoami:1라는 이름의 pod을 만들겠다는 의미다.

실제 현업에서는 Replicas를 거의 쓰지는 않는데 우리가 알아야 하는 이유가 있다. deployment를 현업에서 많이 쓰는데 deployment가 내부적으로 replicas를 사용하고 있기 때문이다.

[ec2-user@ip-10-0-1-231 ~]$ ls
guide-03

[ec2-user@ip-10-0-1-231 ~]$ mkdir guide-03/task-03

[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-03/whoami-rs.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: whoami-rs
spec:
  replicas: 1
  selector:
    matchLabels:
      type: app
      service: whoami
  template:
    metadata:
      labels:
        type: app
        service: whoami
    spec:
      containers:
      - name: whoami
        image: subicura/whoami:1
        livenessProbe:
          httpGet:
            path: /
            port: 4567

[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-03/whoami-rs.yml
replicaset.apps/whoami-rs created

# 아까와 유사한데 replicaset.apps/whoami-rs라는 리플리카셋이 하나 생겼다.
# 그리고 리플리카셋이 생기면서 앞에서 정의했듯이 타입이 app이고 service가 whoami라는 라벨을 가진 pod을
# 찾았는데 없어서 templates 이하내용에 명시된 pod을 생성한 것이다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                  READY   STATUS    RESTARTS   AGE
pod/whoami-rs-tjbrr   1/1     Running   0          115s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   21h

NAME                        DESIRED   CURRENT   READY   AGE
replicaset.apps/whoami-rs   1         1         1       115s

# 아래와 같이 --show-labels 옵션을 주면 서비스는 whoami에 type는 app이라는 라벨정보를 확인할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods --show-labels
NAME              READY   STATUS    RESTARTS   AGE     LABELS
whoami-rs-tjbrr   1/1     Running   0          4m41s   service=whoami,type=app

# 위에 이 라벨링 정보는 사용자가 임의로 삭제&변경이 가능하다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl label pod/whoami-rs-tjbrr type-
pod/whoami-rs-tjbrr labeled

# 아래와 같이 pod/whoami-rs-tjbrr 에 대해서 type을 제거하니까
# whoami-rs-7d6xg가 강제로 새로 생긴것을 확인할 수 있다.
# 리플리카셋은 주기적으로 yaml에 명시되어 있는 pod을 찾기만 한다.
# 이게 최초에는 없어서 yaml이 실행되면서 pod이 1개 생성되어 replicaset 1 명시된대로 그대로 유지가 되었는데
# 지금 강제로 라벨을 제거하니까 리플리카셋 입장에서는 해당 relicaset이 없어진 것이라고 판단한 것이다.
# 그래서 yaml에 명시된 조건에 맞는 pod을 template를 이용해서 또 다른 pod을 생성을 한 것이다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods --show-labels
NAME              READY   STATUS    RESTARTS   AGE     LABELS
whoami-rs-tjbrr   1/1     Running   0          9m33s   service=whoami
whoami-rs-7d6xg   1/1     Running   0          11s     service=whoami,type=app


# 아래와 같이 pod을 제거를 했을때 pod/whoami-rs-7d6xg을 삭제할 경우
# 역시 리플리카셋 입장에서 해당 pod이 없어진 것이기 때문에 template로 새로 하나를
# 만드는 것을 확인할 수 있다. 상태를 체크하고 있는 것이다.
# 이런 이유로 쿠버네티스가 상태를 관리한다고 할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl delete pod/whoami-rs-tjbrr
pod "whoami-rs-tjbrr" deleted

[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
whoami-rs-7d6xg   1/1     Running   0          7m15s

[ec2-user@ip-10-0-1-231 ~]$ kubectl delete pod/whoami-rs-7d6xg
pod "whoami-rs-7d6xg" deleted

[ec2-user@ip-10-0-1-231 ~]$ kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
whoami-rs-zbdpk   1/1     Running   0          41s

# 그러면 replicaset 을 3으로 해서 다시 pod을 띄워보자
# 아까 yaml에서 replicas 만 1에서 3으로 바꿔준 것이다.
# 나머지 내용은 전부 동일하다.
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-03/whoami-rs.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: whoami-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      type: app
      service: whoami
  template:
    metadata:
      labels:
        type: app
        service: whoami
    spec:
      containers:
      - name: whoami
        image: subicura/whoami:1
        livenessProbe:
          httpGet:
            path: /
            port: 4567
                
# 그런다음에 다시 띄우면 큐브컨트롤이 기존것과의 차이점을 인지해서 새로 명령을 내리게 된다. 
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-03/whoami-rs.yml
replicaset.apps/whoami-rs configured

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                  READY   STATUS    RESTARTS   AGE
pod/whoami-rs-zbdpk   1/1     Running   0          15m
pod/whoami-rs-rhxv2   1/1     Running   0          76s
pod/whoami-rs-b7khr   1/1     Running   0          76s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   21h

NAME                        DESIRED   CURRENT   READY   AGE
replicaset.apps/whoami-rs   3         3         3       32m


# 위에 실습이 끝나면 아래와 같이 삭제를 해준다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl delete -f guide-03/task-03/
replicaset.apps "whoami-rs" deleted
  • Deployment 실습

guide-03/task-04/whoami-deploy.yml는 위에서 replicas와 전혀 차이가 없다. kind와 metadata 이름만 다를 뿐이다.

Deployment는 버전을 관리하고 rollback 같은 기능이 있을뿐이고 replicaset과 거의 차이가 없다. 예를들어서 이미지의 tag 같은 것들이 바뀌면 Deployment는 이력을 모두 기록한다.

[ec2-user@ip-10-0-1-231 ~]$ ls
guide-03

[ec2-user@ip-10-0-1-231 ~]$ mkdir guide-03/task-04

[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-04/whoami-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      type: app
      service: whoami
  template:
    metadata:
      labels:
        type: app
        service: whoami
    spec:
      containers:
      - name: whoami
        image: subicura/whoami:1
        livenessProbe:
          httpGet:
            path: /
            port: 4567
                
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-04/whoami-deploy.yml
deployment.apps/whoami-deploy created

# replicas와는 다르게 NAME 세번째에 deployment.apps/whoami-deploy 부분이 새로 생겼다.
# 이 deployment.apps/whoami-deploy가 replicaset을 만들었고, replicaset.apps/whoami-deploy-698f4ffd64가 만든 pod 세개가
# 추가된 것을 알 수 있다. 
[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                                 READY   STATUS    RESTARTS   AGE
pod/whoami-deploy-698f4ffd64-2ccjr   1/1     Running   0          5s
pod/whoami-deploy-698f4ffd64-ldd9t   1/1     Running   0          5s
pod/whoami-deploy-698f4ffd64-tpjrd   1/1     Running   0          5s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   22h

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/whoami-deploy   3/3     3            3           5s

NAME                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/whoami-deploy-698f4ffd64   3         3         3       5s

# 그러면 왜 deployment가 replicaset을 쓸까
# 아래와 같이 yaml에서 subicura/whoami:1을 subicura/whoami:2로 바꿔서 다시 실행해보자.
# 그러면 원래 pod은 그대로 있고 subicura/whoami:2가 실행이 된다.
# 그러다가 subicura/whoami:2가 실행이 다 완료되면 원래 있던 3개의 pod은 종료가 된다.
# 그리고 replicaset이 원래는 1개 였는데 2개가 된것을 알 수 있다.
# deployment는 버전을 업그레이드할때 replicaset을 이용을 한다. 
# 위에서 순서대로 첫번째 replicaset은 버전 1을 관리한 replicaset이고
# 아래 replicaset은 버전 2을 관리하는 replicaset이다. 버전 2를 deployment를 이용해서 띄우면
# deployment가 처음에는 버전 1을 갖고있는 replicaset 한테 pod 3개를 띄우라고 했다가
# pod을 2개를 띄우라고 명령을 한다. 그리고 버전 2을 관리하는 replicaset에게 pod을 1개 띄우라고 한다.
# 이게 성공적으로 되면 버전 1을 갖고있는 replicaset에게 pod 두개띄우는걸 한개로 띄우라고하고,
# 그런 다음에 버전 2를 갖고 있는 얘한테 pod 1개 갖고 있는걸 2개를 띄우라고 한다. 이런식으로
# 기존의 버전과 새로운 버전을 바꿔치기 한다.
# deployment가 replicaset을 이용을 하는 것이다.
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-04/whoami-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      type: app
      service: whoami
  template:
    metadata:
      labels:
        type: app
        service: whoami
    spec:
      containers:
      - name: whoami
        image: subicura/whoami:2
        livenessProbe:
          httpGet:
            path: /
            port: 4567
                
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-04/whoami-deploy.yml
deployment.apps/whoami-deploy configured

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                                 READY   STATUS              RESTARTS   AGE
pod/whoami-deploy-698f4ffd64-2ccjr   1/1     Running             0          4m19s
pod/whoami-deploy-698f4ffd64-ldd9t   1/1     Running             0          4m19s
pod/whoami-deploy-698f4ffd64-tpjrd   1/1     Running             0          4m19s
pod/whoami-deploy-8686bdc7cc-f5ks5   0/1     ContainerCreating   0          7s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   22h

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/whoami-deploy   3/3     1            3           4m19s

NAME                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/whoami-deploy-698f4ffd64   3         3         3       4m19s
replicaset.apps/whoami-deploy-8686bdc7cc   1         1         0       7s

# 한 3초 있다가 다시 아래와 같이 조회해본다.

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                                 READY   STATUS    RESTARTS   AGE
pod/whoami-deploy-8686bdc7cc-f5ks5   1/1     Running   0          71s
pod/whoami-deploy-8686bdc7cc-vnzbf   1/1     Running   0          64s
pod/whoami-deploy-8686bdc7cc-dtmx5   1/1     Running   0          63s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   22h

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/whoami-deploy   3/3     3            3           5m23s

NAME                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/whoami-deploy-8686bdc7cc   3         3         3       71s
replicaset.apps/whoami-deploy-698f4ffd64   0         0         0       5m23s


# 그러면 위에서 언급한 내용이 실시간으로 어떻게 변화는지 아래와 같이 명령어를 실행해서 확인해보자.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get rs -w
NAME                       DESIRED   CURRENT   READY   AGE
whoami-deploy-8686bdc7cc   3         3         3       17m
whoami-deploy-698f4ffd64   0         0         0       21m


## 프로세스가 계속 물고 있기 때문에 새로 터미널을 띄운다.

# subicura/whoami:2에서 다시 1로 바꿔서 실행해보자.
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-04/whoami-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      type: app
      service: whoami
  template:
    metadata:
      labels:
        type: app
        service: whoami
    spec:
      containers:
      - name: whoami
        image: subicura/whoami:1
        livenessProbe:
          httpGet:
            path: /
            port: 4567
                
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-04/whoami-deploy.yml
deployment.apps/whoami-deploy configured
                
## 아까 kubectl get rs -w 띄워놓은 터미널로 돌아가면

# pod 뜨고 죽는 현황을 확인할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get rs -w
NAME                       DESIRED   CURRENT   READY   AGE
whoami-deploy-8686bdc7cc   3         3         3       17m
whoami-deploy-698f4ffd64   0         0         0       21m
whoami-deploy-698f4ffd64   0         0         0       27m
whoami-deploy-698f4ffd64   1         0         0       27m
whoami-deploy-698f4ffd64   1         0         0       27m
whoami-deploy-698f4ffd64   1         1         0       27m
whoami-deploy-698f4ffd64   1         1         1       27m
whoami-deploy-8686bdc7cc   2         3         3       22m
whoami-deploy-698f4ffd64   2         1         1       27m
whoami-deploy-8686bdc7cc   2         3         3       22m
whoami-deploy-698f4ffd64   2         1         1       27m
whoami-deploy-8686bdc7cc   2         2         2       22m
whoami-deploy-698f4ffd64   2         2         1       27m
whoami-deploy-698f4ffd64   2         2         2       27m
whoami-deploy-8686bdc7cc   1         2         2       22m
whoami-deploy-698f4ffd64   3         2         2       27m
whoami-deploy-8686bdc7cc   1         2         2       22m
whoami-deploy-698f4ffd64   3         2         2       27m
whoami-deploy-8686bdc7cc   1         1         1       22m
whoami-deploy-698f4ffd64   3         3         2       27m
whoami-deploy-698f4ffd64   3         3         3       27m
whoami-deploy-8686bdc7cc   0         1         1       22m
whoami-deploy-8686bdc7cc   0         1         1       22m
whoami-deploy-8686bdc7cc   0         0         0       22m
^C

# deployment는 pod의 갯수 같은 것을 신경쓰는게 아니라 replicaset의 상태만 관리하고, replicaset에게 위임을 한다.
# 그러면 deployment가 버전관리가 가능한데 이걸 실습을 해보자.

[ec2-user@ip-10-0-1-231 ~]$ kubectl get deployment
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
whoami-deploy   3/3     3            3           37m

# deployment가 replicaset에 명령했던 이력들을 event로 확인할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl describe deployment/whoami-deploy
Name:                   whoami-deploy
Namespace:              default
CreationTimestamp:      Sat, 12 Dec 2020 06:27:12 +0000
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 3
Selector:               service=whoami,type=app
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  service=whoami
           type=app
  Containers:
   whoami:
    Image:        subicura/whoami:1
    Port:         <none>
    Host Port:    <none>
    Liveness:     http-get http://:4567/ delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   whoami-deploy-698f4ffd64 (3/3 replicas created)
Events:
  Type    Reason             Age                From                   Message
  ----    ------             ----               ----                   -------
  Normal  ScalingReplicaSet  34m                deployment-controller  Scaled up replica set whoami-deploy-8686bdc7cc to 1
  Normal  ScalingReplicaSet  33m                deployment-controller  Scaled down replica set whoami-deploy-698f4ffd64 to 2
  Normal  ScalingReplicaSet  33m                deployment-controller  Scaled up replica set whoami-deploy-8686bdc7cc to 2
  Normal  ScalingReplicaSet  33m                deployment-controller  Scaled down replica set whoami-deploy-698f4ffd64 to 1
  Normal  ScalingReplicaSet  33m                deployment-controller  Scaled up replica set whoami-deploy-8686bdc7cc to 3
  Normal  ScalingReplicaSet  33m                deployment-controller  Scaled down replica set whoami-deploy-698f4ffd64 to 0
  Normal  ScalingReplicaSet  11m                deployment-controller  Scaled up replica set whoami-deploy-698f4ffd64 to 1
  Normal  ScalingReplicaSet  11m                deployment-controller  Scaled down replica set whoami-deploy-8686bdc7cc to 2
  Normal  ScalingReplicaSet  11m                deployment-controller  Scaled up replica set whoami-deploy-698f4ffd64 to 2
  Normal  ScalingReplicaSet  11m                deployment-controller  Scaled down replica set whoami-deploy-8686bdc7cc to 1
  Normal  ScalingReplicaSet  11m (x2 over 38m)  deployment-controller  Scaled up replica set whoami-deploy-698f4ffd64 to 3
  Normal  ScalingReplicaSet  11m                deployment-controller  Scaled down replica set whoami-deploy-8686bdc7cc to 0
  

# deployment의 history도 다음과 같은 명령어를 실행해서 확인할 수 있다.
# subicura/whoami:1 --> subicura/whoami:2 --> subicura/whoami:1 이렇게 세번 바뀌었기 떄문에
# revision이 세개가 있는것이고, 이미지 버전이 똑같은 경우에는 이전 기록을 지우기 때문에
# 총 버전이 세개지만 마지막 버전 2개만 보이는 것이다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl rollout history deployment/whoami-deploy
deployment.apps/whoami-deploy
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

# 특정 revision의 상세내역도 확인할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl rollout history deployment/whoami-deploy --revision=2
deployment.apps/whoami-deploy with revision #2
Pod Template:
  Labels:       pod-template-hash=8686bdc7cc
        service=whoami
        type=app
  Containers:
   whoami:
    Image:      subicura/whoami:2
    Port:       <none>
    Host Port:  <none>
    Liveness:   http-get http://:4567/ delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>
    
[ec2-user@ip-10-0-1-231 ~]$ kubectl rollout history deployment/whoami-deploy --revision=3
deployment.apps/whoami-deploy with revision #3
Pod Template:
  Labels:       pod-template-hash=698f4ffd64
        service=whoami
        type=app
  Containers:
   whoami:
    Image:      subicura/whoami:1
    Port:       <none>
    Host Port:  <none>
    Liveness:   http-get http://:4567/ delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>
    
# 이런식으로 내가 버전을 하나 올렸는데 그 버전에 문제가 있다면 다시 rollback해야 한다.
# 이런 시나리오도 대처가 가능하다. 
[ec2-user@ip-10-0-1-231 ~]$ kubectl rollout undo deployment/whoami-deploy
deployment.apps/whoami-deploy rolled back

# 롤백을 하는데 revision을 롤백하는게 아니라 리비전 4번으로 하고, 이전의 상태를 롤백하는 개념이다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl rollout history deployment/whoami-deploy
deployment.apps/whoami-deploy
REVISION  CHANGE-CAUSE
3         <none>
4         <none>

[ec2-user@ip-10-0-1-231 ~]$ kubectl rollout history deployment/whoami-deploy --revision=4
deployment.apps/whoami-deploy with revision #4
Pod Template:
  Labels:       pod-template-hash=8686bdc7cc
        service=whoami
        type=app
  Containers:
   whoami:
    Image:      subicura/whoami:2
    Port:       <none>
    Host Port:  <none>
    Liveness:   http-get http://:4567/ delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>
    

# deployment는 strategy라는 항목이 있다.
# 아까는 3개의 pod이 띄워져 있는 상태에서 버전이 변화하면 pod이 하나가 뜨면 하나가 죽고, 다시 하나가 뜨면 하나가 죽는
# 이런 방식인데 이게 만약에 pod이 100개라고 치면 pod이 한방에 50개뜨고 다 뜨면 50개 죽이고 이런식으로 하고 싶을 것이다.
# 이런걸 적용할 수 있는 옵션이다.
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-04/whoami-deploy-strategy.yml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: whoami-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      type: app
      service: whoami
  minReadySeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        type: app
        service: whoami
    spec:
      containers:
      - name: whoami
        image: subicura/whoami:1
        livenessProbe:
          httpGet:
            path: /
            port: 4567
                

# 위에 실습이 끝나면 아래와 같이 삭제를 해준다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl delete -f guide-03/task-04/
deployment.apps "whoami-deploy" deleted
  • Service 실습

지금까지는 컨테이너를 띄우기만 했지 실제 접속을 해보지는 않았다.

service라는 개념이해를 위해 아래의 URL을 참고한다.

https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0

docker-compose 같은 경우에는 host에 port를 연결하는 컨테이너가 있었고, host에 연결을 하지 않은 컨테이너가 있었는데 그거를 쿠버네티스에서는 명시적으로 구분을 한다.

그래서 clusterIP라는 용어가 있는데 이거는 도커에서 실습한 backend나 mongodb의 포트라고 생각하면 된다. clusterIP는 외부로 노출하는 IP가 아니라 내부적으로 통신할때 쓰는 IP를 말한다. docker-compose로 컨테이너를 띄울때는 아무설정을 하지 않아도 몽고디비 안에 있던 27017을 노출을 시킬 수 있었다. 하지만 쿠버네티스에서는 만약에 몽고디비의 27017을 개방하고 싶다 그러면 clusterIP로 지정을 해줘야 한다. 결론은 어떤 pod에 연결하기 위해서는 해당 pod에 반드시 clusterIP가 부여되어 있어야 한다.

그러면 외부에서 접속을 하려면 어떻게 해야하냐. 쿠버네티스에서는 nodeport라는 것을 제공한다. 도커 같은 경우에는 포트를 오픈하면 그 호스트에서만 포트가 열리는데 nodeport같은 경우에는 갖고 있는 모든 노드의 포트가 같이 열리게 된다. 예를 들어서 100개의 노드다 그러면 100개의 노드에 포트가 전부 열리게 된다. 그 100개중에 아무거나 하나접속하면 알아서 내부에 있는 pod을 찾아서 접속하게 설계가 되어 있다.

loadbalancer라는 것도 있다. AWS의 로드밸런서라고 보면 된다. nodeport를 열어주면 모든 노드의 해당 포트가 전부 열린다고 했다. loadbalancer를 쓰게 되면 실제로는 loadbalancer만 포트가 열리게 되고, 이게 서비스에 붙게 된다.

ingress라는 개념도 있다. 이거는 어떤 도메인과 path를 이용해서 원하는 서비스를 연결해주는 기능이다. ingress 안에 nginx가 있는경우가 많다. 이게 무슨의미냐면 ingress는 쿠버네티스에서 얘기하는 개념이고, 실제 구현체로 nginx도 있고, HAproxy도 있고, AWS ELB 또는 ALB도 ingress로 사용할 수 있다. 사용자가 어떻게 구현하느냐에 따라 다른 형태가 되는 것이다.

1) clusterIP 기능을 이용해서

내부서비스 간에 통신하는 것을 실습해보자.

# deployment로 redis를 띄울거고 deployment는 type은 db면서 service는 redis인 pod을 찾는다. 
# 그래서 type은 db면서 service는 redis를 만족하는 pod이 없으면
# tempates를 이용해서 pod을 생성한다. 
# ---밑에부분이 clusterIP에 관한 설정이다. ClusrterIP는 라벨이 type은 db면서 service는 redis인 pod을 바라본다.
# clusterIP의 selector가 그 역할을 한다.
# 아래와 같이 --- 구분을 통해 분리하는 것이 양식이다.
[ec2-user@ip-10-0-1-231 ~]$ mkdir guide-03/task-05/

[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-05/redis-app.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      type: db
      service: redis
  template:
    metadata:
      labels:
        type: db
        service: redis
    spec:
      containers:
      - name: redis
        image: redis
        ports:
        - containerPort: 6379
          protocol: TCP
---

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
  - port: 6379
    protocol: TCP
  selector:
    type: db
    service: redis

# deployment와 service가 생성된 것을 알 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-05/redis-app.yml
deployment.apps/redis created
service/redis created

# deployment가 하나 생성되었고, 이 deployment가 replicaset을 생성했고,
# 이 replicaset이 pod을 생성했다. 그리고 여기에 redis라는 서비스가 추가가 된것이다.
# redis는 10.43.3.112를 부여받았는데 10.43.3.112로 접근하면 pod/redis-b6fd45ccc-lcg7j에 접근하는 것이다.
# 지금은 pod이 하나라서 무조건 pod/redis-b6fd45ccc-lcg7j로 접속하겠지만 만약에 pod이 여러개가 있으면
# 10.43.3.112로 접근했을때 내부적으로 로드밸런스처럼 여러개의 pod에 번갈아가면서 접속한다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                        READY   STATUS    RESTARTS   AGE
pod/redis-b6fd45ccc-lcg7j   1/1     Running   0          27s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   10.43.0.1     <none>        443/TCP    24h
service/redis        ClusterIP   10.43.3.112   <none>        6379/TCP   27s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/redis   1/1     1            1           27s

NAME                              DESIRED   CURRENT   READY   AGE
replicaset.apps/redis-b6fd45ccc   1         1         1       27s

# 10.42.0.36:6379는 pod/redis-b6fd45ccc-lcg7j의 endpoin이다.
# 10.43.3.112로 접근하면 10.42.0.36:6379를 통해 pod/redis-b6fd45ccc-lcg7j에 접근할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl describe service/redis
Name:              redis
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          service=redis,type=db
Type:              ClusterIP
IP:                10.43.3.112
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         10.42.0.36:6379
Session Affinity:  None
Events:            <none>
    
# pod을 세개로 늘려보자.
# 기존내용에서 replicas: 3만 추가한 것이다.
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-05/redis-app.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 3
  selector:
    matchLabels:
      type: db
      service: redis
  template:
    metadata:
      labels:
        type: db
        service: redis
    spec:
      containers:
      - name: redis
        image: redis
        ports:
        - containerPort: 6379
          protocol: TCP
---

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
  - port: 6379
    protocol: TCP
  selector:
    type: db
    service: redis

[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-05/redis-app.yml
deployment.apps/redis configured
service/redis unchanged

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                        READY   STATUS    RESTARTS   AGE
pod/redis-b6fd45ccc-lcg7j   1/1     Running   0          14m
pod/redis-b6fd45ccc-nlpn4   1/1     Running   0          7s
pod/redis-b6fd45ccc-vtnff   1/1     Running   0          7s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   10.43.0.1     <none>        443/TCP    24h
service/redis        ClusterIP   10.43.3.112   <none>        6379/TCP   14m

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/redis   3/3     3            3           14m

NAME                              DESIRED   CURRENT   READY   AGE
replicaset.apps/redis-b6fd45ccc   3         3         3       14m

# 10.43.3.112로 접근했을때 바라보는게 아까는 엔드포인트가 하나였는데
# 지금은 세개가 되었다. 로드밸런서 처럼 동작할 것이다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl describe service/redis
Name:              redis
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          service=redis,type=db
Type:              ClusterIP
IP:                10.43.3.112
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         10.42.0.36:6379,10.42.0.37:6379,10.42.0.38:6379
Session Affinity:  None
Events:            <none>
    
# 리플리카셋을 다시 1로해서 적용해주자.
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-05/redis-app.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      type: db
      service: redis
  template:
    metadata:
      labels:
        type: db
        service: redis
    spec:
      containers:
      - name: redis
        image: redis
        ports:
        - containerPort: 6379
          protocol: TCP
---

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
  - port: 6379
    protocol: TCP
  selector:
    type: db
    service: redis
        
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-05/redis-app.yml
deployment.apps/redis configured
service/redis unchanged

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                        READY   STATUS    RESTARTS   AGE
pod/redis-b6fd45ccc-lcg7j   1/1     Running   0          17m

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   10.43.0.1     <none>        443/TCP    24h
service/redis        ClusterIP   10.43.3.112   <none>        6379/TCP   17m

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/redis   1/1     1            1           17m

NAME                              DESIRED   CURRENT   READY   AGE
replicaset.apps/redis-b6fd45ccc   1         1         1       17m


# redis를 만들었으니까 그거를 바라보는 app을 만들어보자.
# 호스트를 redis로 사용을 했다. docker-compose에서 container의 이름이 곧 domain인 것처럼
# 동일하게 동작을 한다. 위에서 서비스의 이름을 redis로 지정해줬기 때문에
# whoami 입장에서는 redis로 접근을 하면 redis service로 접근을 한다. 서비스 이름이 곧 도메인 이름처럼 쓰인다.
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-05/whoami-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
spec:
  selector:
    matchLabels:
      type: app
      service: whoami
  template:
    metadata:
      labels:
        type: app
        service: whoami
    spec:
      containers:
      - name: whoami
        image: subicura/whoami-redis:1
        env:
        - name: REDIS_HOST
          value: "redis"
        - name: REDIS_PORT
          value: "6379"
            
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-05/whoami-deploy.yml
deployment.apps/whoami created

[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                          READY   STATUS    RESTARTS   AGE
pod/redis-b6fd45ccc-lcg7j     1/1     Running   0          24m
pod/whoami-676d78bbf8-8m29n   1/1     Running   0          7s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   10.43.0.1     <none>        443/TCP    25h
service/redis        ClusterIP   10.43.3.112   <none>        6379/TCP   24m

NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/redis    1/1     1            1           24m
deployment.apps/whoami   1/1     1            1           7s

NAME                                DESIRED   CURRENT   READY   AGE
replicaset.apps/redis-b6fd45ccc     1         1         1       24m
replicaset.apps/whoami-676d78bbf8   1         1         1       7s

# whoami가 잘떴고 실제 접속이 잘 되는지 테스트를 해보자.
# 아래와 같이 redis에 잘 접근하는 것을 확인할 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl exec -it whoami-676d78bbf8-8m29n sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/usr/src/app # apk add curl busybox-extras
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
(1/5) Installing busybox-extras (1.28.4-r3)
Executing busybox-extras-1.28.4-r3.post-install
(2/5) Installing nghttp2-libs (1.39.2-r0)
(3/5) Installing libssh2 (1.9.0-r1)
(4/5) Installing libcurl (7.61.1-r3)
(5/5) Installing curl (7.61.1-r3)
Executing busybox-1.28.4-r1.trigger
OK: 16 MiB in 35 packages
/usr/src/app # telnet redis 6379
keys *
*0
^C
Console escape. Commands are:

 l      go to line mode
 c      go to character mode
 z      suspend telnet
 e      exit telnet
/usr/src/app # curl localhost:4567
1
/usr/src/app # curl localhost:4567
2
/usr/src/app # curl localhost:4567
3
/usr/src/app # curl localhost:4567
4
/usr/src/app # telnet redis 6379
keys *
*1
$5
count
GET count
$1
4
^C
Console escape. Commands are:

 l      go to line mode
 c      go to character mode
 z      suspend telnet
 e      exit telnet

/usr/src/app # exit
[ec2-user@ip-10-0-1-231 ~]$
  • nodeport 실습

nodeport 기능을 이용해서 외부와의 통신을해보자

app을 바라보는 nodeport를 적용해보자.

[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-05/np.yml
apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  type: NodePort
  ports:
  - port: 4567
    protocol: TCP
  selector:
    type: app
    service: whoami
        
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-05/np.yml
service/whoami created

# whoami라는 노드포트가 연결이 되었고, 포트를 보니까 내부에 4567이 30135에 물게된다.
# 따로지정 안하면 30000이상의 포트중에 랜덤하게 지정을 해준다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                          READY   STATUS    RESTARTS   AGE
pod/redis-b6fd45ccc-lcg7j     1/1     Running   0          59m
pod/whoami-676d78bbf8-8m29n   1/1     Running   0          35m

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/kubernetes   ClusterIP   10.43.0.1      <none>        443/TCP          25h
service/redis        ClusterIP   10.43.3.112    <none>        6379/TCP         59m
service/whoami       NodePort    10.43.85.165   <none>        4567:30135/TCP   23s

NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/redis    1/1     1            1           59m
deployment.apps/whoami   1/1     1            1           35m

NAME                                DESIRED   CURRENT   READY   AGE
replicaset.apps/redis-b6fd45ccc     1         1         1       59m
replicaset.apps/whoami-676d78bbf8   1         1         1       35m

## 웹브라우저를 열고 [ec2-public-ip]:30135 로 접속하면 숫자 5가 전시되는 것을 알 수 있다.
## 웹브라우저를 새로고침 할때마다 숫자가 올라가는 것을 확인할 수 있다.
  • ingress 실습

ingress는 어떤 도메인을 지정하여 해당 도메인에 접근시 특정 서비스에 접근하도록 하는 기능임.

whoami-v1라는 이름으로 ingress를 만들것이다. whoami-v1은 도메인 루트로 접근을 할 것이다.

ssl이 아니더라도 redirect를 하지 않겠다는 옵션도 주었다. 그리고 rule을 지정해줘야 하는데 rule은 v1.whoami.3.35.175.198.sslip.io이라는 도메인 주소로 접속을 하면 아래의 백앤드 서비스로 접속을 하겠다는 것이다.

아래에서 3.35.175.198는 EC2의 public ip다.

[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-05/in.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: whoami-v1
  annotations:
    ingress.kubernetes.io/rewrite-target: "/"
    ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - host: v1.whoami.3.35.175.198.sslip.io
    http:
      paths:
      - path: /
        backend:
          serviceName: whoami-v1
          servicePort: 4567

[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-05/in.yml
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/whoami-v1 created

# ingress가 생성된 것을 확인할 수 있고
[ec2-user@ip-10-0-1-231 ~]$ kubectl get ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME        CLASS    HOSTS                             ADDRESS      PORTS   AGE
whoami-v1   <none>   v1.whoami.3.35.175.198.sslip.io   10.0.1.231   80      61s

# 웹브라우저에서 v1.whoami.3.35.175.198.sslip.io 로 접속을 해본다.
# 아마 404 not found가 뜰 것이다. 
# 왜냐하면 이 ingress는 whoami-v1 서비스를 바라보게 했는데 whoami-v1 서비스가 없어서 그렇다.
# 그러면 whoami-v1 서비스를 만들고 다시 시도해보자.
# --- 밑에는 clusterIP 설정하는 부분인데 ingress가 해당하는 ip로 접근하겠다는 설정이다.
[ec2-user@ip-10-0-1-231 ~]$ sudo vim guide-03/task-05/whoami-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      type: app
      service: whoami
      version: v1
  template:
    metadata:
      labels:
        type: app
        service: whoami
        version: v1
    spec:
      containers:
      - name: whoami
        image: subicura/whoami:1
        livenessProbe:
          httpGet:
            path: /
            port: 4567

---

apiVersion: v1
kind: Service
metadata:
  name: whoami-v1
spec:
  ports:
  - port: 4567
    protocol: TCP
  selector:
    type: app
    service: whoami
    version: v1
        
[ec2-user@ip-10-0-1-231 ~]$ kubectl apply -f guide-03/task-05/whoami-v1.yml
deployment.apps/whoami-v1 created
service/whoami-v1 created

# whoami-v1가 만들어진 것을 볼 수 있다.
[ec2-user@ip-10-0-1-231 ~]$ kubectl get all
NAME                           READY   STATUS    RESTARTS   AGE
pod/redis-b6fd45ccc-lcg7j      1/1     Running   0          92m
pod/whoami-676d78bbf8-8m29n    1/1     Running   0          68m
pod/whoami-v1-54588fd7-fm7hb   1/1     Running   0          27s
pod/whoami-v1-54588fd7-wt6lq   1/1     Running   0          27s
pod/whoami-v1-54588fd7-n6vk6   1/1     Running   0          27s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/kubernetes   ClusterIP   10.43.0.1       <none>        443/TCP          26h
service/redis        ClusterIP   10.43.3.112     <none>        6379/TCP         92m
service/whoami       NodePort    10.43.85.165    <none>        4567:30135/TCP   33m
service/whoami-v1    ClusterIP   10.43.220.236   <none>        4567/TCP         27s

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/redis       1/1     1            1           92m
deployment.apps/whoami      1/1     1            1           68m
deployment.apps/whoami-v1   3/3     3            3           27s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/redis-b6fd45ccc      1         1         1       92m
replicaset.apps/whoami-676d78bbf8    1         1         1       68m
replicaset.apps/whoami-v1-54588fd7   3         3         3       27s

# 그러면 아까 만든 ingress가 whoami-v1을 바라볼테니까 웹브라우저에서 
# 다시한번 v1.whoami.3.35.175.198.sslip.io 로 접속해본다.
# 그러면 whoami-v1-54588fd7-n6vk6 와 같은 메세지가 나오는 것을 확인할 수 있다.
# 새로 고침을 할때마다 whoami-v1-54588fd7-wt6lq whoami-v1-54588fd7-fm7hb 이런식으로 세개가 번갈아가면서
# 나올 것이다. 왜냐하면 pod을 세개 띄웠기 때문에 ingress는 세개의 pod을 바라보는 서비스로 접속을 한거고
# 그래서 새로고침을 할때마다 세개의 팟이 내부적으로 번갈아가면서 접속이 되는 것을 확인할 수 있다.