Sunday, January 19, 2025

[Kubernetes 3] Tìm hiểu về node, pod trong Kubernetes

-

Bài viết này chúng ta sẽ tìm hiểu khái niệm về POD, cách khai báo tạo ra các POD manifest từ cấu hình yaml, chạy các POD và quản lý các POD tronng Kubernetes, xem log của POD, xóa POD,…

Để tương tác với Kubernetes ta sử dụng command chính là kubectl

Cú pháp: kubectl [action] [type] [name]

Trong đó:

action: hành động, ví dụ delele, get, apply,…

type: kiểu tài nguyên như ns, no, po, svc …

name:  tên đối tượng

flags: các thiết lập tùy chọn tùy vào loại lệnh

1. Node trong Kubernetes.

Trong Kubernetes Node là một máy vật lý hay máy ảo (VPS) trong cụm máy (cluster). Xem các nút (node) trong cụm (cluster) chạy lệnh:

root@k8s-standalone:~# kubectl get nodes
NAME             STATUS   ROLES                  AGE   VERSION
k8s-standalone   Ready    control-plane,master   10h   v1.23.8

Để lấy thông tin tài nguyên bộ nhớ, CPU, các container, … ở một node nào đó sử dụng lệnh dưới, với k8s-standalone là tên node

root@k8s-standalone:~# kubectl describe node k8s-standalone
Name:               k8s-standalone
Roles:              control-plane,master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=k8s-standalone
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/control-plane=
                    node-role.kubernetes.io/master=
                    node.kubernetes.io/exclude-from-external-load-balancers=
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
                    node.alpha.kubernetes.io/ttl: 0
                    projectcalico.org/IPv4Address: 192.168.13.238/23
                    projectcalico.org/IPv4IPIPTunnelAddr: 10.244.20.128
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Sat, 01 Oct 2022 03:21:24 +0000
Taints:             <none>
Unschedulable:      false
Lease:
  HolderIdentity:  k8s-standalone
  AcquireTime:     <unset>
  RenewTime:       Sat, 01 Oct 2022 14:08:39 +0000
Conditions:
  Type                 Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----                 ------  -----------------                 ------------------                ------                       -------
  NetworkUnavailable   False   Sat, 01 Oct 2022 03:46:58 +0000   Sat, 01 Oct 2022 03:46:58 +0000   CalicoIsUp                   Calico is running on this node
  MemoryPressure       False   Sat, 01 Oct 2022 14:05:34 +0000   Sat, 01 Oct 2022 03:21:21 +0000   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure         False   Sat, 01 Oct 2022 14:05:34 +0000   Sat, 01 Oct 2022 03:21:21 +0000   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure          False   Sat, 01 Oct 2022 14:05:34 +0000   Sat, 01 Oct 2022 03:21:21 +0000   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready                True    Sat, 01 Oct 2022 14:05:34 +0000   Sat, 01 Oct 2022 03:46:33 +0000   KubeletReady                 kubelet is posting ready status. AppArmor enabled
Addresses:
  InternalIP:  192.168.13.238
  Hostname:    k8s-standalone
Capacity:
  cpu:                4
  ephemeral-storage:  205310952Ki
  hugepages-2Mi:      0
  memory:             8167940Ki
  pods:               110
Allocatable:
  cpu:                4
  ephemeral-storage:  189214573050
  hugepages-2Mi:      0
  memory:             8065540Ki
  pods:               110
System Info:
  Machine ID:                 e0f5d56beeac489e9c86516cd48c2c04
  System UUID:                73F61242-4830-AC1E-B9D2-EAF353E15F1A
  Boot ID:                    55610892-1dd5-4573-b791-757493eda6d5
  Kernel Version:             4.15.0-193-generic
  OS Image:                   Ubuntu 18.04.6 LTS
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.6.8
  Kubelet Version:            v1.23.8
  Kube-Proxy Version:         v1.23.8
PodCIDR:                      10.244.0.0/24
PodCIDRs:                     10.244.0.0/24
Non-terminated Pods:          (9 in total)
  Namespace                   Name                                        CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                                        ------------  ----------  ---------------  -------------  ---
  kube-system                 calico-kube-controllers-7f76d48f74-kb5lk    0 (0%)        0 (0%)      0 (0%)           0 (0%)         10h
  kube-system                 calico-node-nz4zd                           250m (6%)     0 (0%)      0 (0%)           0 (0%)         10h
  kube-system                 coredns-64897985d-2vvw5                     100m (2%)     0 (0%)      70Mi (0%)        170Mi (2%)     10h
  kube-system                 coredns-64897985d-cd274                     100m (2%)     0 (0%)      70Mi (0%)        170Mi (2%)     10h
  kube-system                 etcd-k8s-standalone                         100m (2%)     0 (0%)      100Mi (1%)       0 (0%)         10h
  kube-system                 kube-apiserver-k8s-standalone               250m (6%)     0 (0%)      0 (0%)           0 (0%)         10h
  kube-system                 kube-controller-manager-k8s-standalone      200m (5%)     0 (0%)      0 (0%)           0 (0%)         10h
  kube-system                 kube-proxy-zhx9f                            0 (0%)        0 (0%)      0 (0%)           0 (0%)         10h
  kube-system                 kube-scheduler-k8s-standalone               100m (2%)     0 (0%)      0 (0%)           0 (0%)         10h
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests     Limits
  --------           --------     ------
  cpu                1100m (27%)  0 (0%)
  memory             240Mi (3%)   340Mi (4%)
  ephemeral-storage  0 (0%)       0 (0%)
  hugepages-2Mi      0 (0%)       0 (0%)
Events:              <none>

Một số thông tin chúng ta cần để ý như sau:

  • Ready: giá trị true chấp nhận triển khai chạy các Pod trên master
  • MemoryPressure: giá trị true nếu gần hết bộ nhớ
  • DiskPressure: giá trị true nếu gần dung lượng lưu trữ
  • NetworkUnavailable: giá trị true nếu network lỗi cấu hình
  • Capacity, Allocatable: cho biết tài nguyên có hiệu lực như CPU, bộ nhớ, số pod có thể chạy …
  • System Info: thông tin phần mềm trên hệ thống
  • Addresses: thông tin hostname và ip address của node
  • Labels: các nhãn của node

Để thiết lập nhãn cho node ta dùng lệnh

root@k8s-standalone:~# kubectl label node k8s-standalone nhanmoi=tencuanhan
node/k8s-standalone labeled

Verify lại ta thấy đã có nhãn mới như dưới

root@k8s-standalone:~# kubectl label --list nodes k8s-standalone
node-role.kubernetes.io/master=
node-role.kubernetes.io/control-plane=
nhanmoi=tencuanhan
kubernetes.io/os=linux
beta.kubernetes.io/os=linux
node.kubernetes.io/exclude-from-external-load-balancers=
kubernetes.io/hostname=k8s-standalone
beta.kubernetes.io/arch=amd64
kubernetes.io/arch=amd64

Hoặc

root@k8s-standalone:~# kubectl get node -l "nhanmoi=tencuanhan"
NAME             STATUS   ROLES                  AGE   VERSION
k8s-standalone   Ready    control-plane,master   11h   v1.23.8

Để xóa nhãn của node ta sử dụng lệnh

root@k8s-standalone:~# kubectl label node k8s-standalone nhanmoi-
node/k8s-standalone unlabeled

Verify lại ta thấy nhãn không tồn tại

root@k8s-standalone:~# kubectl get node -l "nhanmoi=tencuanhan"
No resources found

2. Pod trong Kubernetes.

Kubernetes không chạy các container một cách trực tiếp, thay vào đó nó bọc một hoặc nhiều container vào với nhau trong một cấu trúc gọi là POD. Các container cùng một pod thì chia sẻ với nhau tài nguyên và mạng cục bộ của pod.

Pod là thành phần mà Kubernetes sẽ thực hiện việc nhân bản (replication), khi cần thiết thì Kubernetes có thể cấu hình để triển khai nhân bản ra nhiều pod có chức năng giống nhau để tránh quá tải, thậm chí nó vẫn tạo ra nhiều bản copy của pod khi không quá tải nhằm phòng lỗi (ví dụ node bị die).

Pod có thể có nhiều container mà pod là đơn vị để scale (có nghĩa là tất cả các container trong pod cũng scale theo) nên nếu có thể thì cấu hình ứng dụng sao cho một Pod có ít container nhất càng tốt.

Cách sử dụng hiệu quả và thông dụng là dùng loại Pod trong nó chỉ chạy một container.

Pod loại chạy nhiều container trong đó thường là đóng gọi một ứng dụng xây dựng với sự phối hợp chặt chẽ từ nhiều container trong một khu vực cách ly, chúng chia sẻ tài nguyên ổ đĩa, mạng cho nhau.

Mỗi POD được gán một địa chỉ IP, các container trong Pod chia sẻ cùng địa chỉ IP này. Các container trong cùng một Pod có thể liên lạc với nhau qua localhost.

Một Pod có thể có nhiều ổ đĩa được chia sẻ để các container có thể truy cập đọc/ghi dữ liệu.

– Làm việc với Pod trong Kubernetes

  • Bạn có thể tạo ra Pod một cách trực tiếp (thực tế ít dùng) hoặc qua triển khai Deployment để Controller thực hiện, khi Pod được tạo ra nó được lên kế hoạch chạy trong một Node nào đó của cụm máy, nó tồn tại cho đến khi tiến trình chạy kết thúc hoặc bị xóa, bị lỗi Node …
  • Controller: Khi bạn tạo các Pod không trực tiếp, tức thông qua cấu hình Deployment thì có một Controller thực hiện việc tạo quản lý các Pod cho bạn, thực hiện cách này nó cung cấp khả năng cập nhật giám sát, phục hồi …

3. Hướng dẫn tạo Pod trong Kubernetes

Mình sẽ tạo 1 pod chứa 1 container ứng dụng monitor Prometheus như sau

cat > ./prometheus_deployment.yaml << OEF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
spec:
  selector:
    matchLabels:
      run: prometheus
  replicas: 1
  template:
    metadata:
      labels:
        run: prometheus
    spec:
      containers:
        - name: prometheus
          image: prom/prometheus
          ports:
            - containerPort: 9090
          resources:
            limits:
              memory: "150M"
              cpu: "100m"
OEF

File trên khai báo một Pod, đặt tên là prometheus, gán nhãn run: prometheus trong Pod chạy một Container từ image prom/prometheus, cổng của Container 9090

Triển khai tạo Pod từ file này, thực hiện lệnh sau

root@k8s-standalone:~# kubectl apply -f ./prometheus_deployment.yaml
deployment.apps/prometheus created

Mặc định Kubernetes không tạo và chạy POD ở Node Master để đảm bảo yêu cầu an toàn, bạn xem lại bài 2 để biết cách thiết lập cho phép tạo POD ở master node.

Sau khi triển khai xong, ta sử dụng lệnh kubectl get pod để list pod, ta thấy đã có 1 Pod mới như dưới.

root@k8s-standalone:~# kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
prometheus-697f49c94b-r9cq9   1/1     Running   0          6s

Chúng ta có thể xem chi tiết thông tin của Pod vừa triển khai bằng lệnh dưới

root@k8s-standalone:~# kubectl describe  prometheus-697f49c94b-r9cq9
error: the server doesn't have a resource type "prometheus-697f49c94b-r9cq9"
root@k8s-standalone:~# kubectl describe pod/prometheus-697f49c94b-r9cq9
Name:         prometheus-697f49c94b-r9cq9
Namespace:    default
Priority:     0
Node:         k8s-standalone/192.168.13.238
Start Time:   Sat, 01 Oct 2022 14:46:02 +0000
Labels:       pod-template-hash=697f49c94b
              run=prometheus
Annotations:  cni.projectcalico.org/containerID: bb4fb80769615ed29955e0234a9adb98fc6e9ff593891a82cc6d28cc63c165d0
              cni.projectcalico.org/podIP: 10.244.20.134/32
              cni.projectcalico.org/podIPs: 10.244.20.134/32
Status:       Running
IP:           10.244.20.134
IPs:
  IP:           10.244.20.134
Controlled By:  ReplicaSet/prometheus-697f49c94b
Containers:
  prometheus:
    Container ID:   containerd://0af788c4837a025cc7030fb0945feb6e6a63bb3c1a697f53f05032e4ee7ee187
    Image:          prom/prometheus
    Image ID:       docker.io/prom/prometheus@sha256:b591915dad4ee2375fbb24cd019c50a546aae561bc63510516efec70d69b4292
    Port:           9090/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 01 Oct 2022 14:46:06 +0000
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     100m
      memory:  150M
    Requests:
      cpu:        100m
      memory:     150M
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-rgqpm (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-rgqpm:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Guaranteed
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  2m27s  default-scheduler  Successfully assigned default/prometheus-697f49c94b-r9cq9 to k8s-standalone
  Normal  Pulling    2m26s  kubelet            Pulling image "prom/prometheus"
  Normal  Pulled     2m23s  kubelet            Successfully pulled image "prom/prometheus" in 2.287419066s
  Normal  Created    2m23s  kubelet            Created container prometheus
  Normal  Started    2m23s  kubelet            Started container prometheus

Để tra cứu logs của Pod sử dụng lệnh

root@k8s-standalone:~# kubectl logs pod/prometheus-697f49c94b-r9cq9
ts=2022-10-01T14:46:06.854Z caller=main.go:491 level=info msg="No time or size retention was set so using the default time retention" duration=15d
ts=2022-10-01T14:46:06.854Z caller=main.go:535 level=info msg="Starting Prometheus Server" mode=server version="(version=2.37.1, branch=HEAD, revision=1ce2197e7f9e95089bfb95cb61762b5a89a8c0da)"
ts=2022-10-01T14:46:06.855Z caller=main.go:540 level=info build_context="(go=go1.18.6, user=root@3caaaea7ba87, date=20220912-12:42:39)"
ts=2022-10-01T14:46:06.855Z caller=main.go:541 level=info host_details="(Linux 4.15.0-193-generic #204-Ubuntu SMP Fri Aug 26 19:20:21 UTC 2022 x86_64 prometheus-697f49c94b-r9cq9 (none))"
ts=2022-10-01T14:46:06.855Z caller=main.go:542 level=info fd_limits="(soft=1048576, hard=1048576)"
ts=2022-10-01T14:46:06.855Z caller=main.go:543 level=info vm_limits="(soft=unlimited, hard=unlimited)"
ts=2022-10-01T14:46:06.945Z caller=web.go:553 level=info component=web msg="Start listening for connections" address=0.0.0.0:9090
ts=2022-10-01T14:46:06.946Z caller=main.go:972 level=info msg="Starting TSDB ..."
ts=2022-10-01T14:46:07.042Z caller=tls_config.go:195 level=info component=web msg="TLS is disabled." http2=false
ts=2022-10-01T14:46:07.046Z caller=head.go:493 level=info component=tsdb msg="Replaying on-disk memory mappable chunks if any"
ts=2022-10-01T14:46:07.046Z caller=head.go:536 level=info component=tsdb msg="On-disk memory mappable chunks replay completed" duration=43.584µs
ts=2022-10-01T14:46:07.046Z caller=head.go:542 level=info component=tsdb msg="Replaying WAL, this may take a while"
ts=2022-10-01T14:46:07.047Z caller=head.go:613 level=info component=tsdb msg="WAL segment loaded" segment=0 maxSegment=0
ts=2022-10-01T14:46:07.047Z caller=head.go:619 level=info component=tsdb msg="WAL replay completed" checkpoint_replay_duration=99.148µs wal_replay_duration=392.146µs total_replay_duration=755.939µs
ts=2022-10-01T14:46:07.048Z caller=main.go:993 level=info fs_type=EXT4_SUPER_MAGIC
ts=2022-10-01T14:46:07.048Z caller=main.go:996 level=info msg="TSDB started"
ts=2022-10-01T14:46:07.048Z caller=main.go:1177 level=info msg="Loading configuration file" filename=/etc/prometheus/prometheus.yml
ts=2022-10-01T14:46:07.049Z caller=main.go:1214 level=info msg="Completed loading of configuration file" filename=/etc/prometheus/prometheus.yml totalDuration=818.381µs db_storage=825ns remote_storage=2.188µs web_handler=403ns query_engine=888ns scrape=277.963µs scrape_sd=33.361µs notify=37.919µs notify_sd=14.586µs rules=1.586µs tracing=6.812µs
ts=2022-10-01T14:46:07.049Z caller=main.go:957 level=info msg="Server is ready to receive web requests."
ts=2022-10-01T14:46:07.049Z caller=manager.go:941 level=info component="rule manager" msg="Starting rule manager..."

Để thi hành 1 lệnh trong Pod ta sử dụng lệnh dưới

root@k8s-standalone:~# kubectl exec pod/prometheus-697f49c94b-r9cq9 ls /etc
group
hostname
hosts
localtime
network
nsswitch.conf
passwd
prometheus
resolv.conf
services
shadow
ssl

Để truy cập vào 1 Pod ta sử dụng lệnh dưới, nếu Pod có nhiều container thì ta thêm tham số -c <container_name>

root@k8s-standalone:~# kubectl exec -it pod/prometheus-697f49c94b-r9cq9 sh
/prometheus $ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1480 qdisc noqueue
    link/ether 6a:44:71:aa:f8:05 brd ff:ff:ff:ff:ff:ff
    inet 10.244.20.134/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::6844:71ff:feaa:f805/64 scope link
       valid_lft forever preferred_lft forever

Truy cập vào Pod từ bên ngoài Cluster ta sử dụng Proxy lý do là trong thông tin của Pod ta thấy có IP của Pod và cổng lắng nghe, tuy nhiên Ip này là nội bộ, chỉ các Pod trong Cluster liên lạc với nhau. Nếu bên ngoài muốn truy cập cần tạo một Service để chuyển traffic bên ngoài vào Pod mà chúng ta sẽ tìm hiểu ở bài sau, ở bài này để tạm thời truy cập kiểm tra bằng cách chạy proxy.

root@k8s-standalone:~# kubectl proxy --address="0.0.0.0" --accept-hosts='^*$'
Starting to serve on [::]:8001

Hoặc

root@k8s-standalone:~# kubectl proxy
Starting to serve on 127.0.0.1:8001

Ta thấy ở master node đang lắng nghe cổng 8001, ta sử dụng link dưới và thay đổi một số thông tin liên quan để truy cập như sau. Bạn dùng 1 máy tính có thể kết nối được đến master node để test nhé

http://192.168.13.238:8001/api/v1/namespaces/default/pods/prometheus-697f49c94b-r9cq9:8001/proxy/

Và đây là kết quả

Để xóa Pod, sử dụng command dưới

root@k8s-standalone:~# kubectl delete -f ./prometheus_deployment.yaml
deployment.apps "prometheus" deleted

Hoặc

root@k8s-standalone:~# kubectl delete pod/prometheus-697f49c94b-89lsc
pod "prometheus-697f49c94b-89lsc" deleted

Lưu ý cách xóa thứ 2 chỉ áp dụng cho Pod triển khai trực tiếp nhé (với type là Pod)

Với Pod có nhiều container, file yaml có định dạng như dưới, ở dưới mình triển khai thêm ứng dụng Pushgateway.

cat > ./prometheus_deployment.yaml << OEF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
spec:
  selector:
    matchLabels:
      run: prometheus
  replicas: 1
  template:
    metadata:
      labels:
        run: prometheus
    spec:
      containers:
        - name: prometheus
          image: prom/prometheus
          ports:
            - containerPort: 9090
          resources:
            limits:
              memory: "150M"
              cpu: "100m"
        - name: pushgateway
          image: prom/pushgateway
          ports:
            - containerPort: 9091
          resources:
            limits:
              memory: "150M"
              cpu: "100m"
OEF

Sa khi triển khai xong chúng ta thấy Pod này có 2 container đang runing

root@k8s-standalone:~# kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
prometheus-8f6c467bd-ssx25   2/2     Running   0          2m25s

Đến đây mình đã hướng dẫn các lệnh cơ bản về node, pod và cách triển khai các pods, phần sau mình sẽ nói về lưu trữ trong Kubernetes nhé.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories