Categories
Software Architecture

Sử Dụng Kubernetes

Kubernetes, viết tắt là “k8s” hoặc “kube”, cho phép người dùng khai báo trạng thái mong muốn của một ứng dụng bằng cách sử dụng các khái niệm như “triển khai” và “dịch vụ”. Ví dụ: người dùng có thể chỉ định rằng họ muốn triển khai với ba phiên bản của ứng dụng web Tomcat đang chạy. Kubernetes khởi động và sau đó liên tục giám sát các container, cung cấp tính năng tự động khởi động lại, lên lịch lại và sao chép để đảm bảo ứng dụng luôn ở trạng thái mong muốn.

Các khái niệm chính của Kubernetes

Các tài nguyên Kubernetes có thể được tạo trực tiếp trên dòng lệnh nhưng thường được chỉ định bằng cách sử dụng Yet Another Markup Language (YAML). Các tài nguyên có sẵn và các trường cho mỗi tài nguyên có thể thay đổi với các phiên bản Kubernetes mới, vì vậy, điều quan trọng là phải kiểm tra kỹ tham chiếu API cho phiên bản của bạn để biết những gì có sẵn. Điều quan trọng nữa là sử dụng đúng “apiVersion” phù hợp với phiên bản Kubernetes của bạn. Bài tham khảo này sử dụng API từ Kubernetes 1.12, được phát hành ngày 27 tháng 9 năm 2018.

POD

Một Pod là một nhóm gồm một hoặc nhiều container. Kubernetes sẽ lên lịch tất cả các container cho một pod vào cùng một máy chủ lưu trữ, với cùng một không gian tên mạng, vì vậy tất cả chúng đều có cùng địa chỉ IP và có thể truy cập lẫn nhau bằng cách sử dụng localhost. Đây là một định nghĩa pod ví dụ:

apiVersion: v1 
kind: Pod 
spec:
  containers:
  - name: nginx
    image: nginx 
    volumeMounts:
    - mountPath: /srv/www
      name: www-data
      readOnly: true 
  - name: git-monitor
    image: kubernetes/git-monitor 
    env:
    - name: GIT_REPO
      value: http://github.com/some/repo.git 
    volumeMounts:
    - mountPath: /data
      name: www-data 
  volumes:
  - name: www-data 
    emptyDir: {}

Không chỉ các container trong một pod có thể chia sẻ cùng một giao diện mạng mà chúng còn có thể chia sẻ dung lượng, như được minh họa trong ví dụ. Ví dụ này sử dụng container “git-monitor” để giữ cho kho lưu trữ Git được cập nhật trong /data để container “nginx” có thể chạy một máy chủ web để cung cấp các tệp của kho lưu trữ.

Khi một pod được tạo, Kubernetes sẽ giám sát nó và tự động khởi động lại nếu một tiến trình kết thúc. Ngoài ra, Kubernetes có thể được định cấu hình để cố gắng kết nối với một container qua mạng để xác định xem pod đã sẵn sàng (readinessProbe) và vẫn còn sống (livenessProbe) hay không.

Triển khai (DEPLOYMENT)

Việc triển khai cung cấp các bản cập nhật thay đổi quy mô pod và cập nhật liên tục (rolling updates). Kubernetes sẽ đảm bảo rằng số lượng pod được chỉ định đang chạy và trên bản cập nhật liên tục sẽ thay thế từng pod một, cho phép cập nhật ứng dụng mà không có thời gian chết.

Các triển khai đã tốt nghiệp từ bản beta trong Kubernetes 1.11 và thay thế khái niệm cũ hơn về Bộ bản sao (Replica Sets). Việc triển khai tạo ra một tập hợp bản sao (replica set), nhưng không cần thiết phải tương tác trực tiếp với tập hợp bản sao.

apiVersion: apps/v1 
kind: Deployment 
metadata:
  name: nginx-deployment 
  labels:
    app: nginx 
spec:
  replicas: 3 
  selector:
    matchLabels: 
      app: nginx
  template: 
    metadata: 
      labels:
        app: nginx 
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.4 
        ports:
        - containerPort: 80

Việc triển khai bao gồm một “mẫu” (template) chỉ định các pod được tạo sẽ trông như thế nào, vì vậy không cần phải định nghĩa riêng một pod. Kubernetes sẽ tự động tạo số lượng pod cần thiết từ mẫu triển khai.

Lưu ý rằng việc triển khai sẽ xác định các pod phù hợp bằng cách sử dụng trường matchLabels. Trường này phải luôn có cùng dữ liệu với trường metadata.labels bên trong mẫu. Việc triển khai sẽ có quyền sở hữu bất kỳ pod nào đang chạy khác khớp với bộ chọn matchLabels, ngay cả khi chúng được tạo riêng, vì vậy hãy giữ những tên này là duy nhất.

Dịch vụ (SERVICE)

Một dịch vụ cung cấp cân bằng tải cho một triển khai. Trong triển khai, mỗi pod được gán một địa chỉ IP duy nhất và khi một pod được thay thế, pod mới thường nhận được một địa chỉ IP mới.

Bằng cách khai báo một dịch vụ, chúng ta có thể cung cấp một điểm vào duy nhất cho tất cả các pod trong một lần triển khai. Điểm nhập duy nhất này (tên máy chủ và địa chỉ IP) vẫn hợp lệ khi các pod đến và đi.

kind: Service 
apiVersion: v1 
metadata:
  name: nginx-service 
spec:
  selector: 
    app: nginx
  ports:
  - protocol: TCP
    port: 80

Các dịch vụ và triển khai có thể được tạo theo bất kỳ thứ tự nào. Dịch vụ chủ động giám sát Kubernetes để tìm các pod phù hợp với trường bộ chọn (selector). Ví dụ: trong trường hợp này, dịch vụ sẽ khớp các pod với nội dung metadata.labels của app: nginx, giống như được hiển thị trong ví dụ triển khai ở trên.

Các dịch vụ dựa vào Kubernetes để cung cấp một địa chỉ IP duy nhất và định tuyến lưu lượng truy cập đến chúng, do đó, cách các dịch vụ được định cấu hình có thể khác nhau tùy thuộc vào cách cấu hình cài đặt Kubernetes của bạn.

Yêu cầu dung lượng thường trú (PERSISTENT VOLUME CLAIM)

Kubernetes có nhiều loại tài nguyên lưu trữ. Ví dụ về Pod ở trên cho thấy đơn giản nhất, một thư mục trống được gắn vào nhiều container trong cùng một pod. Để lưu trữ thực sự thường trú, cách tiếp cận linh hoạt nhất là sử dụng một Yêu cầu Dung lượng Thường trú.

Yêu cầu Dung lượng Thường trú yêu cầu Kubernetes phân bổ động dung lượng từ Lớp lưu trữ (Storage Class). Lớp lưu trữ thường được tạo bởi quản trị viên của cụm Kubernetes và phải tồn tại. Sau khi Yêu cầu Dung lượng Thường trú được tạo, nó có thể được đính kèm vào một Pod. Kubernetes sẽ giữ bộ nhớ trong khi Yêu cầu Dung lượng Thường trú tồn tại, ngay cả khi Pod đính kèm bị xóa.

kind: PersistentVolumeClaim 
apiVersion: v1
metadata:
  name: web-static-files 
spec:
  resources: 
    requests:
      storage: 8Gi 
  storageClassName: file-store
---
apiVersion: v1 
kind: Pod 
metadata:
  name: webserver 
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: web-files 
  volumes:
  - name: web-files 
    persistentVolumeClaim:
      claimName: web-static-files

Ví dụ trên khai báo cả Yêu cầu Dung lượng Thường trú và một Pod sử dụng nó. Ví dụ này tận dụng khả năng đặt nhiều tài liệu YAML trong cùng một tệp bằng cách sử dụng — làm dấu phân tách. Tất nhiên, trong một ví dụ thực tế, sẽ tốt hơn nếu tách riêng Yêu cầu Dung lượng Thường trú để nó có thể dễ dàng được giữ lại ngay cả khi Pod bị xóa.

Để biết thêm thông tin về các nhà cung cấp có sẵn cho Lớp lưu trữ Kubernetes và để biết nhiều ví dụ về cách định cấu hình lưu trữ thường trú (persistent storage), hãy xem Kho lưu trữ Container Thường trú (Persistent Container Storage) của DZone Refcard.

Kiến trúc Kubernetes

Kubernetes sử dụng kiến trúc client-server, như được thấy ở đây:

Kiến trúc Kubernetes.

Cụm Kubernetes là một tập hợp các máy vật lý hoặc máy ảo và các tài nguyên cơ sở hạ tầng khác được sử dụng để chạy các ứng dụng. Các máy quản lý cụm được gọi là Máy chủ (Masters) và máy chạy các container được gọi là Nút (Nodes).

Máy chủ (MASTER)

Master chạy các dịch vụ quản lý cụm. Quan trọng nhất là kube-apiserver, là dịch vụ chính mà các máy khách và các nút sử dụng để truy vấn và sửa đổi các tài nguyên đang chạy trong cụm. Máy chủ API được hỗ trợ bởi: etcd, một kho lưu trữ khóa-giá trị phân tán được sử dụng để ghi lại trạng thái cụm; kube-controller-manager, một chương trình giám sát quyết định những thay đổi cần thực hiện khi tài nguyên được thêm vào, thay đổi hoặc loại bỏ; và kube-scheduler, một chương trình quyết định nơi chạy các pod dựa trên các nút có sẵn và cấu hình của chúng.

Trong bản cài đặt Kubernetes có tính khả dụng cao, sẽ có nhiều master, trong đó một bản đóng vai trò là bản chính (primary) và các bản khác đóng vai trò là bản sao (replica).

Nút (NODE)

Node là một máy vật lý hoặc máy ảo với các dịch vụ cần thiết để chạy các container. Một cụm Kubernetes nên có nhiều nút cần thiết cho tất cả các pod được yêu cầu. Mỗi nút có hai dịch vụ Kubernetes: kubelet, nhận lệnh để chạy các container và sử dụng công cụ container (container engine) (ví dụ: Docker) để chạy chúng; và kube-proxy, quản lý các quy tắc mạng để các kết nối đến địa chỉ IP dịch vụ được định tuyến chính xác đến các pod.

Như trong hình, mỗi nút có thể chạy nhiều pod và mỗi pod có thể bao gồm một hoặc nhiều container. Pod chỉ là một khái niệm của Kubernetes; kubelet định cấu hình công cụ container để đặt nhiều container trong cùng một không gian tên mạng (network namespace) để các container đó chia sẻ một địa chỉ IP.

Bắt đầu với Kubernetes

THIẾT LẬP KUBERNETES

Có nhiều cách khác nhau để thiết lập, cấu hình và chạy Kubernetes. Nó có thể được chạy trên đám mây bằng cách sử dụng các nhà cung cấp như Amazon Elastic Container Service cho Kubernetes, Google Kubernetes Engine, Azure Kubernetes Service, Packet, Pivotal Container Service, v.v. Nó cũng có thể được chạy tại chỗ (on-premise) bằng cách xây dựng một cụm từ đầu trên phần cứng vật lý hoặc thông qua máy ảo. Các tùy chọn khác nhau được mô tả trong tài liệu thiết lập Kubernetes (Kubernetes setup documentation), nơi bạn có thể tìm ra giải pháp nào tốt nhất cho mình và nhận hướng dẫn từng bước. Tùy chọn phổ biến nhất để xây dựng cụm Kubernetes đa máy chủ (multi-host) từ đầu là kubeadm, trong khi cách được khuyến nghị để bắt đầu và chạy một cụm nút đơn (single-node) để phát triển và thử nghiệm là sử dụng Minikube.

Tuy nhiên khi bạn thiết lập cụm của mình, bạn sẽ tương tác với nó bằng cách sử dụng kubectl chương trình khách dòng lệnh Kubernetes tiêu chuẩn.

MINIKUBE

Minikube sử dụng phần mềm ảo hóa như VirtualBox, VMware hoặc KVM để chạy cụm. Sau khi Minikube được cài đặt, bạn có thể sử dụng dòng lệnh minikube để bắt đầu một cụm bằng cách chạy lệnh sau:

minikube start

Để dừng cụm, bạn có thể chạy:

minikube stop

Để xác định địa chỉ IP của cụm đang sử dụng:

minikube ip

Nếu bạn đang gặp sự cố, bạn có thể xem nhật ký (logs) hoặc ssh vào máy chủ để giúp gỡ lỗi sự cố bằng cách sử dụng:

minikube logs
minikube ssh

Bạn cũng có thể mở chế độ xem bảng điều khiển trong trình duyệt để xem và thay đổi những gì đang diễn ra trong cụm.

minikube dashboard

KUBECTL

kubectl là một tiện ích dòng lệnh điều khiển cụm Kubernetes. Các lệnh sử dụng định dạng này:

kubectl [command] [type] [name] [flags]
  • [command] chỉ định thao tác cần được thực hiện trên tài nguyên. Ví dụ: create, get, describe, delete hoặc scale.
  • [type] chỉ định loại tài nguyên Kubernetes. Ví dụ: pod (po), service (svc), deployment (deploy) hoặc persistentvolumeclaim (pvc). Các loại tài nguyên không phân biệt chữ hoa chữ thường và bạn có thể chỉ định các dạng số ít, số nhiều hoặc viết tắt.
  • [name] Chỉ định tên của tài nguyên, nếu có. Tên có phân biệt chữ hoa chữ thường. Nếu tên bị bỏ qua, thông tin chi tiết cho tất cả các tài nguyên sẽ được hiển thị (ví dụ: kubectl get pods).
  • [flags] Các tùy chọn cho lệnh.

Một số ví dụ về lệnh kubectl và mục đích của chúng:

COMMANDMỤC ĐÍCH
kubectl create -f nginx.yamlTạo tài nguyên được chỉ định trong tệp YAML. Nếu tồn tại bất kỳ tài nguyên nào được chỉ định, lỗi sẽ được trả về.
kubectl delete -f nginx.ymlXóa các tài nguyên được chỉ định trong tệp YAML. Nếu bất kỳ tài nguyên nào không tồn tại, chúng sẽ bị bỏ qua.
kubectl get podsLiệt kê tất cả các pod trong không gian tên “default”. Xem bên dưới để biết thêm thông tin về không gian tên.
kubectl describe pod nginxHiển thị siêu dữ liệu cho pod “nginx”. Tên phải khớp chính xác.
kubectl –helpHiển thị danh sách đầy đủ các lệnh có sẵn.

CHẠY CONTAINER ĐẦU TIÊN CỦA BẠN

Hầu hết thời gian khi sử dụng kubectl, chúng ta tạo các tệp tài nguyên YAML, vì vậy chúng ta có thể định cấu hình cách chúng ta muốn ứng dụng của mình chạy. Tuy nhiên, chúng ta có thể tạo một Triển khai đơn giản bằng kubectl mà không cần sử dụng tệp YAML:

kubectl create deployment nginx --image=nginx deployment.apps/nginx created

Lệnh này sẽ bắt đầu một Triển khai, trong đó chứa Repilca Set, chứa một Pod, chứa một Docker container đang chạy một máy chủ web NGINX. Chúng ta có thể sử dụng kubectl để nhận trạng thái của việc triển khai:

kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 1 1 1 1 1m

Trạng thái của Replica Set có thể được nhìn thấy bằng cách sử dụng:

kubectl get rs
NAME DESIRED CURRENT READY AGE 
nginx-65899c769f 1 1 1 1m

Trạng thái của Pod có thể được nhìn thấy bằng cách sử dụng:

kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-65899c769f-kp5c7 1/1 Running 0 1m

Tất nhiên, hầu hết thời gian chúng ta sẽ sử dụng tệp cấu hình YAML:

kubectl create -f nginx-deployment.yaml

Tệp nginx-deployment.yaml chứa định nghĩa Triển khai được hiển thị ở trên.

QUY MÔ ỨNG DỤNG

Việc triển khai có thể được mở rộng và thu nhỏ:

kubectl scale --replicas=3 deploy/nginx deployment.extensions/nginx scaled

Sau đó, bộ điều khiển Kubernetes sẽ làm việc với bộ lập lịch để tạo hoặc xóa các pod nếu cần để đạt được số lượng được yêu cầu. Điều này được phản ánh trong việc triển khai:

kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 3 3m

Bạn có thể xác minh có ba pod bằng cách chạy:

kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-65899c769f-c46xx 1/1 Running 0 38s
nginx-65899c769f-j484j 1/1 Running 0 38s
nginx-65899c769f-kp5c7 1/1 Running 0 3m

Lưu ý rằng Pod ban đầu tiếp tục chạy trong khi thêm hai Pod nữa. Tất nhiên, chúng ta cũng muốn tạo một Dịch vụ (Service) để hỗ trợ cân bằng tải trong các trường hợp này; xem bên dưới để có một ví dụ đầy đủ hơn.

XÓA ỨNG DỤNG

Sau khi sử dụng xong ứng dụng, bạn có thể hủy nó bằng lệnh delete.

kubectl delete deployment nginx deployment.extensions "nginx" deleted

Vì Kubernetes giám sát các pod để đạt được số lượng bản sao mong muốn, chúng ta phải xóa Triển khai để loại bỏ ứng dụng. Chỉ cần dừng container hoặc xóa pod sẽ chỉ khiến Kubernetes tạo một pod khác.

Ứng dụng mẫu

Hãy kết hợp nhiều tính năng Kubernetes với nhau để triển khai ứng dụng Node.js cùng với máy chủ cơ sở dữ liệu PostgreSQL. Đây là kiến trúc quy hoạch (xem bên phải).

Ứng dụng mẫu.

Chúng ta sẽ làm việc từ cuối sơ đồ. Đầu tiên, chúng ta sẽ định nghĩa triển khai PostgreSQL:

apiVersion: apps/v1 
kind: Deployment 
metadata:
  name: postgresql 
  labels:
    app: postgresql 
spec:
  replicas: 1 
  selector:
    matchLabels:
      app: postgresql
  template: 
    metadata: 
      labels:
        app: postgresql 
    spec:
      containers:
      - name: postgresql
        image: postgres:10.4 
        env:
        - name: PGDATA
          value: "/data/pgdata" 
        volumeMounts:
        - mountPath: /data
          name: postgresql-data 
      volumes:
      - name: postgresql-data 
        persistentVolumeClaim:
          claimName: postgresql-data

Lưu ý rằng chúng ta sử dụng PersistentVolumeClaim để chúng ta nhận được dữ liệu thường trú; chúng ta sẽ cho rằng điều này đã được tạo vì chúng ta muốn nó tồn tại trong một thời gian dài ngay cả khi chúng ta cập nhật ứng dụng.

Mặc dù sẽ chỉ có một phiên bản cơ sở dữ liệu, chúng ta sẽ tạo một Dịch vụ để địa chỉ IP sẽ giữ nguyên ngay cả khi pod PostgreSQL được thay thế.

kind: Service 
apiVersion: v1 
metadata:
  name: postgres-service 
spec:
  selector:
    app: postgresql
  ports:
  - protocol: TCP
    port: 5432

Tiếp theo, chúng ta tạo triển khai cho ứng dụng Node.js:

apiVersion: apps/v1 
kind: Deployment 
metadata:
  name: nodejs 
  labels:
    app: nodejs 
spec:
  replicas: 3 
  selector:
    matchLabels: 
      app: nodejs
  template: 
    metadata: 
      labels:
        app: nodejs 
    spec:
      containers:
      - name: nodejs
        image: nodejs:10-alpine 
        command: ["npm"]
        args: ["start"]
        env:
        - name: NODE_ENV 
          value: production
        workingDir: /app 
        volumeMounts:
        - mountPath: /app
          name: node-app
          readOnly: true 
      - name: git-monitor
        image: kubernetes/git-monitor 
        env:
        - name: GIT_REPO
          value: http://github.com/some/repo.git 
        volumeMounts:
        - mountPath: /data
          name: node-app 
      volumes:
      - name: www-data 
        emptyDir: {}

Ví dụ này sử dụng một container “sidecar” (thùng của mô tô thùng), kubernetes/git-monitor, để giữ cho ứng dụng của chúng ta được cập nhật dựa trên kho lưu trữ Git. Sidecar điền một ổ đĩa được chia sẻ với container Node.js.

Cuối cùng, chúng ta tạo dịch vụ cung cấp điểm nhập người dùng cho ứng dụng của chúng ta:

kind: Service 
apiVersion: v1 
metadata:
  name: nodejs-service 
spec:
  selector: 
    app: nodejs
  ports:
  - protocol: TCP
    port: 3000
  type: LoadBalancer

Cung cấp dịch vụ với IP bên ngoài để chúng có thể được nhìn thấy từ bên ngoài cụm là một chủ đề phức tạp vì nó phụ thuộc vào môi trường cụm của bạn (ví dụ: cloud, máy ảo hoặc bare metal). Ví dụ này sử dụng dịch vụ LoadBalancer, dịch vụ này yêu cầu một số bộ cân bằng tải bên ngoài như Amazon Elastic Load Balancer có sẵn và được định cấu hình trong cụm.

Không gian tên, hạn ngạch tài nguyên và giới hạn

Kubernetes sử dụng không gian tên để tránh xung đột tên, để kiểm soát quyền truy cập và đặt hạn ngạch. Khi chúng ta tạo các tài nguyên ở trên, những tài nguyên này đã trở thành không gian tên default. Các tài nguyên khác là một phần của cơ sở hạ tầng cụm nằm trong không gian tên kube-system.

Để xem các pod trong kube-system, chúng ta có thể chạy:

$ kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE ...
kube-apiserver-minikube 1/1 Running 0 17m ...

CÔ LẬP TÀI NGUYÊN

Một không gian tên mới có thể được tạo từ định nghĩa tài nguyên YAML:

apiVersion: v1 
kind: Namespace 
metadata:
  name: development 
  labels:
    name: development

Khi chúng ta đã tạo không gian tên, chúng ta có thể tạo tài nguyên trong đó bằng cờ –namespace (-n) hoặc bằng cách chỉ định không gian tên trong siêu dữ liệu của tài nguyên:

apiVersion: v1 
kind: Pod 
metadata:
  name: webserver 
  namespace: development
...

Bằng cách sử dụng các không gian tên riêng biệt, chúng ta có thể có nhiều pod được gọi là webserver và không phải lo lắng về các xung đột tên.

KIỂM SOÁT TRUY CẬP

Kubernetes hỗ trợ Kiểm soát truy cập dựa trên vai trò /Role Based Access Control (RBAC).

Dưới đây là một ví dụ giới hạn các nhà phát triển quyền truy cập chỉ đọc (read-only) cho các pod trong production. Đầu tiên, chúng ta tạo một ClusterRole, một tập hợp các quyền phổ biến mà chúng ta có thể áp dụng cho bất kỳ không gian tên nào:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1 
metadata:
  name: pod-read-only 
rules:
- apiGroups: [""] # "" indicates the core API group resources: ["pods"]
  verbs: ["get", "watch", "list"]

Tiếp theo, chúng ta sử dụng RoleBinding để áp dụng ClusterRole này cho một nhóm cụ thể trong một không gian tên cụ thể:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1 
metadata:
  name: read-only
  namespace: production 
subjects:
- kind: Group
  name: developers
  apiGroup: rbac.authorization.k8s.io 
roleRef:
  kind: ClusterRole
  name: pod-read-only
  apiGroup: rbac.authorization.k8s.io

Ngoài ra, chúng ta có thể sử dụng ClusterRoleBinding để áp dụng vai trò cho người dùng hoặc nhóm trong tất cả các không gian tên.

HẠN NGẠCH TÀI NGUYÊN

Theo mặc định, pod có tài nguyên không giới hạn. Chúng ta có thể áp dụng một hạn ngạch cho một không gian tên:

apiVersion: v1 
kind: ResourceQuota 
metadata:
  name: compute-resources
  namespace: sandbox 
spec:
  hard:
    cpu: "5"
    memory: 10Gi

Kubernetes hiện sẽ từ chối các pod không giới hạn trong không gian tên này. Thay vào đó, chúng ta cần áp dụng một giới hạn:

apiVersion: v1 
kind: Pod 
metadata:
  name: webserver
  namespace: sandbox 
spec:
  containers:
  - image: nginx
    name: nginx 
    resources:
      limits:
        memory: "128Mi" 
        cpu: "500m"

Lưu ý rằng chúng ta có thể yêu cầu các phân số của CPU và sử dụng các đơn vị khác nhau cho bộ nhớ.

Leave a Reply

Your email address will not be published. Required fields are marked *