[Nhập môn Kubernetes P4] - Kubernetes resource và kubectl command

Serial blog Nhập môn Kubernetes

Nội dung

  • Giới thiệu
  • Kubernetes và Resource
  • Kubectl và YAML Manifest
  • Cách sử dụng kubectl
  • Tổng kết

Giới thiệu

Trong phần 4 này, mình sẽ giới thiệu đến các bạn cơ bản về các thành phần của Kubernetes và kubectl command.
Trên thực tế, K8s được cấu thành từ Kubernetes Master và Kubernetes Node. Kubernetes Master cung cấp API Endpoint, Đảm nhận vai trò Container Scheduling, Container Scaling vv. Còn Kubernetes Node là host để khởi động những container ứng dụng của chúng ta.
Chúng ta cùng xem lại kiến trúc của K8s một lần nữa nhé.

Trong đó cấu trúc của Kubernetes Master gồm:

Chi tiết các thành phần các bạn có thể xem link tham khảo bên dưới hoặc search ở 1 page khác nhé. Mình chỉ nói cái tổng quát trước, không đi vào chi tiết ngay để mọi người khỏi bị loạn. Đại khái thì khi thao tác với kubernetes cluster thông qua CLI tool kubectl thì chúng ta sẽ call đến API của Kubernetes Master, sau đó các thành phần trong Master sẽ scheduling hay scaling container vào các Kubernetes Node.
Tham khảo:
https://techblog.vn/phan-2-kien-truc-cua-kubernetes


Mối quan hệ giữa Kubernetes Master và Kubernetes Nodes

Khi vận hành Kubernetes Cluster, chúng ta đăng ký resource cho Kubernetes Master bằng cách sử dụng công cụ kubectl và một file .yml (manifest) đã chuẩn bị sẵn được viết bằng YAML. Thực tế thì tool kubectl cũng chỉ call đến Kubernetes Master API thông qua mạng nội bộ, nếu chúng ta không sử dụng kubectl thì cũng có thể sử dụng một thư viện khác hoặc là curl command cũng có thể thao tác được.

Kubernetes và Resource

Nãy giờ mình có nhắc nhiều đến khái niệm resource, thì resource trong kubernetes là gì. Có nhiều loại resource như là: container, load balancer, nodes vv.
Resource của kubernetes có rất nhiều loại nhưng mình tạm phân ra làm 5 nhóm lớn sau:

Phân Loại Resource Nội dung
Workloads Resource liên quan đến thực thi container
Discovery&Load balancer Resource cung cấp Endpoint - cho phép truy cập Container từ bên ngoài Cluster
Config&Storage Resources liên quan đến settings, confidential information, persistent volumes vv
Cluster Resources liên quan đến security và quota
Metadata Resource cho việc quản lý Resource

Bài viết lần này, để cho mọi người có thể nắm tổng quan nhất, mình sẽ trình bày về 5 loại resource mà user sử dụng (Không bao gồm những resource được sử dụng nội bộ). Từ bài viết sau trở đi, mình sẽ trình bày chi tiết cho mỗi loại resource. Trong 5 loại resource này, Application Developer thường sử dụng đó là 3 loại Workload, Discovery&LB và Config&Storage.

Để có cái nhìn tổng quan về 5 loại resource này, mình thể hiện thông quan hình vẽ sau:

kubectl và YAML Manifest

Cách làm thực tế để khởi động 1 container, pod, deployment vv là sử dụng file Manifest. Bây giờ chúng ta hãy thử khởi động container bằng file YAML Maniefst. Mình sẽ tạo 1 pod chứa 1 container là nginx

# nginx-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx-pod
spec:
  containers:
  - name: nginx-pod
    image: nginx:1.12
    imagePullPolicy: "Always"

Khi tạo resource thì chúng ta sử dụng command kubectl create. Trường hợp resource đã tồn tại, sẽ phát sinh lỗi.

# Trường hợp chưa tồn tại resource
$ kubectl create -f nginx-pod.yml
pod "nginx-pod" created
 
# Trường hợp tồn tại resource 
$ kubectl create -f nginx-pod.yml
Error from server (AlreadyExists): error when creating "nginx-pod.yml": pods "nginx-pod" already exists

Muốn xoá resource thì chúng ta dùng lệnh kubectl delete

# Delete pod
$ kubectl delete -f nginx-pod.yml
pod "nginx-pod" deleted

Khi muốn update resource ta sử dụng lệnh kubectl apply. Mình sẽ sử đổi version của docker image. Sửa lại file với nội dung cập nhật như bên dưới.

# Trước update 
image: nginx:1.12

#Sau update
image: nginx:1.13

Sau khi thực hiện update file YAML Manifest xong, ta thực hiện update bằng command kubectl apply. Nếu như file Manifest không có thay đổi gì, không có gì xảy ra ở đây cả. Trường hợp nếu resource chưa tồn tại thì lệnh kubectl apply và lệnh kubectl create là như nhau. Chính về vậy về cơ bản, chung ta không cần sử dụng lệnh kubectl create, chỉ cần lệnh kubectl apply là OK rồi, rất tiện lợi phải không.

# Trường hợp có thay đổi
$ kubectl apply -f nginx-pod.yml
pod "nginx-pod" configured
 
# Trường hợp không có thay đổi
$ kubectl apply -f nginx-pod.yml
pod "nginx-pod" unchanged
 
# Resource không tồn tại
$ kubectl apply -f nginx-pod.yml
pod "nginx-pod" created

Ngoài ra còn có các command như kubectl set, kubectl replace, kubectl edit vv. Sử dụng các command này cũng có thể thực hiện thay đổi Manifest.

Cách sử dụng kubectl

Nãy giờ thì mình cũng đã giới thiệu qua một số các thao tác với resource sử dụng kubectl command, tuy nhiên còn có rất nhiều command để get thông tin nữa. Ví dụ như để thực hiện lấy danh sách resource, chúng ta sử dụng kubectl get. Bằng cách sử dụng option --output (-o) có thể xuất ra với nhiều định dạng khác nhau như: JSON/YAML/custom-columns/Go Template. Trường hợp xuất ra với định dạng JSON hay YAML, chúng ta có thể confirm thông tin một cách chi tiết. Với câu lệnh kubectl get all có thể lấy tất cả thông tin resource.

Một số command thường dùng

# Get list node
$  kubectl get nodes
NAME          STATUS    ROLES               AGE       VERSION
kube-master   Ready     controlplane,etcd   18d       v1.10.3
kube-node1    Ready     worker              18d       v1.10.3
kube-node2    Ready     worker              18d       v1.10.3

$ kubectl get nodes -o wide
NAME          STATUS    ROLES               AGE       VERSION   EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION               CONTAINER-RUNTIME
kube-master   Ready     controlplane,etcd   18d       v1.10.3   <none>        CentOS Linux 7 (Core)   3.10.0-862.11.6.el7.x86_64   docker://1.13.1
kube-node1    Ready     worker              18d       v1.10.3   <none>        CentOS Linux 7 (Core)   3.10.0-862.11.6.el7.x86_64   docker://1.13.1
kube-node2    Ready     worker              18d       v1.10.3   <none>        CentOS Linux 7 (Core)   3.10.0-862.11.6.el7.x86_64   docker://1.13.1

# Get list pods
$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
frontend-deployment-69d88649c7-bf592   2/2       Running   0          17d
frontend-deployment-69d88649c7-kz9xf   2/2       Running   0          17d
frontend-deployment-69d88649c7-ql87x   2/2       Running   0          17d
sample-pod                             1/1       Running   0          17d

# Get detail list pod info
$ kubectl get pods -o wide
NAME                                   READY     STATUS    RESTARTS   AGE       IP           NODE
frontend-deployment-69d88649c7-bf592   2/2       Running   0          17d       10.42.1.9    kube-node1
frontend-deployment-69d88649c7-kz9xf   2/2       Running   0          17d       10.42.2.10   kube-node2
frontend-deployment-69d88649c7-ql87x   2/2       Running   0          17d       10.42.2.11   kube-node2
sample-pod                             1/1       Running   0          17d       10.42.1.8    kube-node1

# Get service 
$ kubectl get svc
NAME               TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
frontend-service   NodePort       10.43.134.81    <none>           80:32253/TCP   18d
kubernetes         ClusterIP      10.43.0.1       <none>           443/TCP        18d
nginx-php-fpm      LoadBalancer   10.43.232.121   150.95.176.186   80:30312/TCP   18d

# Exec pod and specific container
$ kubectl exec -it [pod_name] -c nginx /bin/bash


Giới thiệu tiếp đến các bạn một câu lệnh rất hữu ích, đó là kubectl describe. Là command để lấy thông tin chi tiết của một resource nào đó, chẳng hạn như Pods. Ngoài một số thông tin thường thấy như post, image, container, status vv. Thì thông tin để mình có thể debug mỗi khi container không được start hay ở trạng thái lỗi. Thông tin cần quan tâm nhất khi chạy command này đó là Item "Event", nó thể hiện việc setup volume, việc pull image như thế nào và cả container life cycle.

$ kubectl describe pods nginx-pod
Name:         nginx-pod
Namespace:    default
Node:         minikube/10.0.2.15
Start Time:   Wed, 15 Aug 2018 22:06:08 +0700
Labels:       app=nginx-pod
Annotations:  kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"nginx-pod"},"name":"nginx-pod","namespace":"default"},"spec":{"containers...
Status:       Running
IP:           172.17.0.4
Containers:
  nginx-pod:
    Container ID:   docker://db2e78e82e835103d95a5538bcdc8fc7f733dd9c89e9e32944ed30efd28d2f1b
    Image:          nginx:1.12
    Image ID:       docker-pullable://nginx@sha256:72daaf46f11cc753c4eab981cbf869919bd1fee3d2170a2adeac12400f494728
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Wed, 15 Aug 2018 22:06:43 +0700
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-c4qhx (ro)
Conditions:
  Type           Status
  Initialized    True 
  Ready          True 
  PodScheduled   True 
Volumes:
  default-token-c4qhx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-c4qhx
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              50m   default-scheduler  Successfully assigned nginx-pod to minikube
  Normal  SuccessfulMountVolume  50m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-c4qhx"
  Normal  Pulling                50m   kubelet, minikube  pulling image "nginx:1.12"
  Normal  Pulled                 50m   kubelet, minikube  Successfully pulled image "nginx:1.12"
  Normal  Created                50m   kubelet, minikube  Created container
  Normal  Started                50m   kubelet, minikube  Started container

Không chỉ lấy thông tin chi tiết của Pod, với Nodes cũng tương tự.

$ kubectl describe nodes minikube
Name:               minikube
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=minikube
                    node-role.kubernetes.io/master=
Annotations:        node.alpha.kubernetes.io/ttl=0
                    volumes.kubernetes.io/controller-managed-attach-detach=true
CreationTimestamp:  Wed, 15 Aug 2018 22:03:04 +0700
Taints:             <none>
Unschedulable:      false
Conditions:
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------  -----------------                 ------------------                ------                       -------
  OutOfDisk        False   Wed, 15 Aug 2018 23:08:49 +0700   Wed, 15 Aug 2018 22:03:00 +0700   KubeletHasSufficientDisk     kubelet has sufficient disk space available
  MemoryPressure   False   Wed, 15 Aug 2018 23:08:49 +0700   Wed, 15 Aug 2018 22:03:00 +0700   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure     False   Wed, 15 Aug 2018 23:08:49 +0700   Wed, 15 Aug 2018 22:03:00 +0700   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure      False   Wed, 15 Aug 2018 23:08:49 +0700   Wed, 15 Aug 2018 22:03:00 +0700   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready            True    Wed, 15 Aug 2018 23:08:49 +0700   Wed, 15 Aug 2018 22:03:00 +0700   KubeletReady                 kubelet is posting ready status
Addresses:
  InternalIP:  10.0.2.15
  Hostname:    minikube
Capacity:
 cpu:                2
 ephemeral-storage:  16888216Ki
 hugepages-2Mi:      0
 memory:             2038624Ki
 pods:               110
Allocatable:
 cpu:                2
 ephemeral-storage:  15564179840
 hugepages-2Mi:      0
 memory:             1936224Ki
 pods:               110
System Info:
 Machine ID:                 bec9c88ab8ce41049005c3426ba5a62d
 System UUID:                3CA1DD33-875A-4CBB-BDD3-CA31B5EC0CB5
 Boot ID:                    1914b073-d566-4c12-bf0d-6731688ab339
 Kernel Version:             4.15.0
 OS Image:                   Buildroot 2018.05
 Operating System:           linux
 Architecture:               amd64
 Container Runtime Version:  docker://17.12.1-ce
 Kubelet Version:            v1.10.0
 Kube-Proxy Version:         v1.10.0
ExternalID:                  minikube
Non-terminated Pods:         (10 in total)
  Namespace                  Name                                     CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ---------                  ----                                     ------------  ----------  ---------------  -------------
  default                    nginx-pod                                0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-system                etcd-minikube                            0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-system                kube-addon-manager-minikube              5m (0%)       0 (0%)      50Mi (2%)        0 (0%)
  kube-system                kube-apiserver-minikube                  250m (12%)    0 (0%)      0 (0%)           0 (0%)
  kube-system                kube-controller-manager-minikube         200m (10%)    0 (0%)      0 (0%)           0 (0%)
  kube-system                kube-dns-86f4d74b45-764qh                260m (13%)    0 (0%)      110Mi (5%)       170Mi (8%)
  kube-system                kube-proxy-zxjnp                         0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-system                kube-scheduler-minikube                  100m (5%)     0 (0%)      0 (0%)           0 (0%)
  kube-system                kubernetes-dashboard-5498ccf677-xpq6t    0 (0%)        0 (0%)      0 (0%)           0 (0%)
  kube-system                storage-provisioner                      0 (0%)        0 (0%)      0 (0%)           0 (0%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  CPU Requests  CPU Limits  Memory Requests  Memory Limits
  ------------  ----------  ---------------  -------------
  815m (40%)    0 (0%)      160Mi (8%)       170Mi (8%)
Events:         <none>

Trong trường hợp muốn kiểm tra log của Pod được xuất ra như thế nào, sử dụng kubectl log.

# Xuất log của container bên trong Pod
$ kubectl logs nginx-pod
 
# Có thể chỉ định cụ thể log của container nào trong pod có nhiều container
$ kubectl logs nginx-pod -c nginx-container
 
# Lệnh này thì giống kiểu tail -f (follow log)
$ kubectl logs -f nginx-pod
 
# Xuất log Trong 1 giờ trước、lấy 10 record, hiển thị timestamps
$ kubectl logs --since=1h --tail=10 --timestamps=true nginx-pod

Trường hợp muốn thực thi một container nào cụ thể trong Pod, sử dụng command kubectl exec. /bin/sh là lệnh mà khi container được start sẽ chạy lệnh này, khi chạy xong ta muốn giữ nó ở trạng thái đã truy cập vào container đó thì gõ thêm option -it.

# Thực thi lệnh /bin/sh một container bên trong Pod
$ kubectl exec -it nginx-pod /bin/sh
 
# Trường hợp có nhiều container trong 1 Pod, thực thi lệnh /bin/sh đối với container được chỉ định.
$ kubectl exec -it nginx-pod -c nginx-container /bin/sh
 
# Trường hợp muốn thực thi container có parameter thêm param sau dấu 「--」
$ kubectl exec -it nginx-pod -- /bin/ls -l /

Có một trường hợp mà mình nghĩ nó rất hữu ích. Chẳng hạn như mình muốn debug một ứng dụng web chạy trong container từ máy local, hoặc là muốn kết nối mysql container từ một Database client. Trong trường hợp như vậy chúng ta sử dụng kubectl port-forward.
Bây giờ mình sẽ demo command này ở ở browser máy local của mình, truy cập đến nginx container trong nginx-pod. Khi thực thi lệnh bên dưới và gõ lên browser localhost:8888 thì nó sẽ kết nối đến container nginx port 80.

$ kubectl port-forward nginx-pod 8888:80
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80

Khi làm việc với kubectl, sẽ rất hữu ích nếu chúng ta có thể sử dụng tốt các kubectl command một cách thuần thục. Khi đó việc debug các resource của chúng ta dễ dàng hơn. kubectl còn có nhiều command hữu ích khác, các bạn hãy gõ lệnh kubectl get --help, nó sẽ gợi ý cho mình nhiều command hữu ích và ví dụ cụ thể, các bạn cứ thử thoải mái nhé. Ngoài ra các bạn có thể tham khảo thêm link bên dưới:
Kubectl Tips and Tricks
Tips and Tricks of Using Kubectl, the Kubernetes CLI

Tổng kết

Bài viết này mình đã trình bày cho mọi người liên quan đến các thành phần, resource của kubernetes và một số command thường dùng với kubectl. Bài viết cũng khá dài rồi nên mình xin tạm kết thúc ở đây. Các bài viết sau mình sẽ trình bày chi tiết từng resource.