[Note] Khóa học Kubernetes cơ bản (tiếng Việt) – Phần 4 – Chap 13 -> 15

Chapter 13. ConfigMaps and Secrets

Trong quá trình triển khai ứng dụng, chúng ta có thể cần truyền vào các thông số (parameter) trong lúc ứng dụng chạy, ví dụ như thông tin cấu hình, quyền (permission), mật khẩu, khóa (key), chứng chỉ (certificate) hay token.

Ví dụ: Ta cần triển khai 10 ứng dụng khác nhau cho khách hàng, và với mỗi khách hàng, hiển thị tên công ty của họ trên giao diện. Thay vì phải tạo 10 image Docker khác nhau, ta có thể dùng chung một image mẫu và truyền tên khách hàng như là tham số lúc ứng dụng đang chạy. Trong trường hợp này, ta có thể sử dụng tài nguyên API ConfigMap.

Tương tự, khi cần truyền thông tin nhạy cảm, ta có thể sử dụng tài nguyên API Secret. Trong chương này, chúng ta sẽ tìm hiểu về ConfigMap và Secret.

Mục tiêu học tập:

  • Thảo luận về cách quản lý cấu hình cho ứng dụng trong Kubernetes bằng ConfigMap.

  • Chia sẻ dữ liệu nhạy cảm (như mật khẩu) sử dụng Secret.

ConfigMaps

ConfigMap cho phép tách rời các chi tiết cấu hình khỏi image container. Khi sử dụng ConfigMap, chúng ta truyền dữ liệu cấu hình dưới dạng các cặp key-value. Dữ liệu này có thể được sử dụng bởi Pod, các thành phần hệ thống khác, hoặc các bộ điều khiển (controller), dưới dạng biến môi trường, tập lệnh và đối số (arguments), hoặc Volume. Chúng ta có thể tạo ConfigMap từ các giá trị thiết lập sẵn (literal values), từ các file cấu hình, hoặc từ một hoặc nhiều thư mục.

Giải thích thêm:

Tách rời cấu hình: ConfigMap tách riêng thông tin cấu hình khỏi image container. Điều này giúp image container gọn nhẹ và dễ quản lý hơn.

Cặp key-value: Dữ liệu cấu hình được lưu trữ dưới dạng các cặp key-value (khóa – giá trị). Cơ chế này giúp truy cập và cập nhật các giá trị cấu hình cụ thể trở nên dễ dàng.

Các cách sử dụng: Pod, các thành phần hệ thống, hay các bộ điều khiển (controller) có thể sử dụng dữ liệu trong ConfigMap theo nhiều cách:

  • Biến môi trường: Các key trong ConfigMap có thể ánh xạ đến biến môi trường bên trong container.

  • Câu lệnh và đối số (arguments): ConfigMap định nghĩa câu lệnh và đối số thực thi trong container.

  • Volume: Dữ liệu ConfigMap có thể được gắn kết (mount) như một Volume vào Pod.

Tạo ConfigMap: Các phương thức tạo ConfigMap:

  • Giá trị trực tiếp: Chỉ định các cặp key-value ngay trong manifest của ConfigMap.

  • File cấu hình: Cung cấp đường dẫn đến một file cấu hình chứa các cặp key-value.

  • File và thư mục: Chỉ định một thư mục chứa nhiều file cấu hình.

Create a ConfigMap from Literal Values

Một ConfigMap có thể được tạo bằng lệnh kubectl create, và ta có thể xem chi tiết của nó bằng cách sử dụng lệnh kubectl get.

Tạo ConfigMap:

$ kubectl create configmap my-config \
  --from-literal=key1=value1 \
  --from-literal=key2=value2

configmap/my-config created

Display the ConfigMap details for my-config:

$ kubectl get configmaps my-config -o yaml

apiVersion: v1
data:
  key1: value1
  key2: value2
kind: ConfigMap
metadata:
  creationTimestamp: 2022-04-02T07:21:55Z
  name: my-config
  namespace: default
  resourceVersion: "241345"
  selfLink: /api/v1/namespaces/default/configmaps/my-config
  uid: d35f0a3d-45d1-11e7-9e62-080027a46057

Với tùy chọn -o yaml, chúng ta đang yêu cầu lệnh kubectl xuất dữ liệu theo định dạng YAML. Như chúng ta có thể thấy, đối tượng thuộc loại ConfigMap và nó chứa các cặp khóa-giá trị (key-value) bên trong phần dữ liệu (data). Tên của ConfigMap và các chi tiết khác là một phần của phần siêu dữ liệu (metadata).

Create a ConfigMap from a Definition Manifest

apiVersion: v1
kind: ConfigMap
metadata:
  name: customer1
data:
  TEXT1: Customer1_Company
  TEXT2: Welcomes You
  COMPANY: Customer1 Company Technology Pct. Ltd.

Trong đó chúng ta xác định loại (kind), siêu dữ liệu (metadata), và phần dữ liệu (data), nhắm tới điểm cuối v1 (endpoint) của API server.
Nếu chúng ta đặt tên cho tệp chứa định nghĩa trên là customer1-configmap.yaml, chúng ta có thể tạo ConfigMap bằng lệnh sau:

$ kubectl create -f customer1-configmap.yaml

configmap/customer1 created

Create a ConfigMap from a File

Đầu tiên, chúng ta cần tạo ra một file permission-reset.properties với cấu hình như sau:

permission=read-only
allowed="true"
resetCount=3

Sau đó, chúng ta có thể tạo ConfigMap bằng lệnh sau:

$ kubectl create configmap permission-config \
--from-file=<đường/dẫn/>permission-reset.properties

configmap/permission-config created

Giải thích:

  • Tệppermission-reset.properties Tệp này chứa các cặp key-value (khóa-giá trị) sẽ được lưu trong ConfigMap. Các cài đặt này cụ thể có vẻ liên quan đến việc kiểm soát quyền truy cập và đặt lại mật khẩu.

  • Lệnhkubectl create configmap: Lệnh này dùng để tạo ConfigMap.

    • permission-config là tên bạn đặt cho ConfigMap.

    • --from-file=<đường/dẫn/>permission-reset.properties cho biết dữ liệu cho ConfigMap sẽ được lấy từ tệp permission-reset.properties. Đảm bảo thay thế <đường/dẫn/> bằng đường dẫn chính xác đến tệp đó.

  • Thông báo “configmap/permission-config created” Thông báo này xác nhận rằng ConfigMap đã được tạo thành công.

Use ConfigMaps Inside Pods: As Environment Variables

Bên trong một Container, ta có thể lấy dữ liệu cặp khóa-giá trị (key-value) của toàn bộ ConfigMap hoặc giá trị của các khóa cụ thể trong ConfigMap dưới dạng các biến môi trường.

Trong ví dụ sau, tất cả các biến môi trường của Container myapp-full-container sẽ nhận giá trị từ các khóa của ConfigMap có tên full-config-map:

...
  containers:
  - name: myapp-full-container
    image: myapp
    envFrom:
    - configMapRef:
      name: full-config-map
...

Giải thích thêm:

  • Sự linh hoạt của ConfigMap: ConfigMap cung cấp một phương thức linh hoạt để đưa dữ liệu cấu hình vào các container của bạn. Bạn có thể sử dụng toàn bộ dữ liệu ConfigMap hoặc chỉ chọn các khóa/giá trị quan trọng cho ứng dụng.

Trong ví dụ sau, các biến môi trường của Container myapp-specific-container nhận giá trị của chúng từ các cặp khóa-giá trị cụ thể ở hai ConfigMap riêng biệt, config-map-1 và config-map-2:

...
  containers:
  - name: myapp-specific-container
    image: myapp
    env:
    - name: SPECIFIC_ENV_VAR1
      valueFrom:
        configMapKeyRef:
          name: config-map-1
          key: SPECIFIC_DATA
    - name: SPECIFIC_ENV_VAR2
      valueFrom:
        configMapKeyRef:
          name: config-map-2
          key: SPECIFIC_INFO
...

Với cấu hình như trên, chúng ta sẽ có được biến môi trường SPECIFIC_ENV_VAR1 được thiết lập thành giá trị từ khóa SPECIFIC_DATA bên trong ConfigMap config-map-1, và biến môi trường SPECIFIC_ENV_VAR2 được thiết lập thành giá trị từ khóa SPECIFIC_INFO bên trong ConfigMap config-map-2.

Use ConfigMaps Inside Pods: As Volumes

Chúng ta có thể gắn (mount) một ConfigMap (dưới dạng vol-config-map) như một Volume bên trong một Pod. Đối với mỗi key (khóa) trong ConfigMap, một file được tạo ra ở đường dẫn gắn kết (mount path) (file được đặt tên theo tên của khóa đó) và giá trị tương ứng của khóa trở thành nội dung của file:

Giải thích thêm:

  • Gắn kết ConfigMaps như Volumes: Đây là một phương pháp khác để đưa dữ liệu từ một ConfigMap vào bên trong một container trong Kubernetes. Thay vì thiết lập biến môi trường, cách này tạo ra các file chứa dữ liệu cấu hình.

  • Cơ chế: Khi một ConfigMap được gắn kết như một volume, Kubernetes tự động tạo ra các file đại diện cho từng cặp khóa-giá trị (key-value) trong cấu trúc ConfigMap.

  • Lợi ích: Cách làm này cung cấp một phương thức khác để truy cập dữ liệu ConfigMap, đặc biệt hữu ích nếu ứng dụng của bạn được thiết kế để đọc cấu hình từ các file.

...
  containers:
  - name: myapp-vol-container
    image: myapp
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: vol-config-map
...

For more details, please explore the documentation on using ConfigMaps.

Using ConfigMaps as Volumes Demo Guide

Hướng dẫn bài thực hành này được chuẩn bị cho phần trình diễn bằng video có trong chương này. Nó bao gồm một file index.html và một bản khai báo định nghĩa Deployment, có thể được sử dụng như các mẫu để tạo ra các đối tượng tương tự khác khi cần thiết. Mục tiêu của bài demo là lưu trữ file webserver index.html tùy chỉnh bên trong một đối tượng ConfigMap, sau đó được gắn kết (mount) bởi container nginx được chỉ định bởi mẫu Pod nằm trong bản khai báo Deployment.

File index của webserver:

$ vim index.html

<!DOCTYPE html>
<html>
<head>
<title>Welcome to GREEN App!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
        background-color: GREEN;
    }
</style>
</head>
<body>
<h1 style=\"text-align: center;\">Welcome to GREEN App!</h1>
</body>
</html>

The Deployment definition file:

$ vim web-green-with-cm.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: green-web
  name: green-web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: green-web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: green-web
    spec:
      volumes:
      - name: web-config
        configMap:
          name: green-web-cm
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: web-config
status: {}

Secrets

Giả sử chúng ta có một ứng dụng blog WordPress, trong đó phần giao diện (frontend) WordPress của chúng ta kết nối đến cơ sở dữ liệu MySQL (backend) bằng mật khẩu. Trong khi tạo Deployment cho WordPress, ta có thể đưa mật khẩu MySQL trực tiếp vào trong file YAML của Deployment, nhưng điều này không bảo vệ được mật khẩu. Mật khẩu sẽ có thể bị nhìn thấy bởi bất kỳ ai có quyền truy cập vào tệp cấu hình.

Trong trường hợp này, đối tượng Secret có thể giúp bằng cách cho phép mã hóa thông tin nhạy cảm trước khi chia sẻ nó. Với Secret, ta có thể chia sẻ thông tin nhạy cảm như mật khẩu, token hoặc khóa dưới dạng các cặp khóa-giá trị (key-value), tương tự như ConfigMap; do đó, ta có thể kiểm soát cách thông tin trong Secret được sử dụng, giảm nguy cơ bị lộ tình cờ. Trong Deployment hoặc các tài nguyên khác, đối tượng Secret được tham chiếu đến mà không làm lộ nội dung của nó.

Điều quan trọng cần nhớ là, theo mặc định, dữ liệu Secret được lưu trữ dưới dạng văn bản thuần túy (plain text) bên trong etcd, do đó, quản trị viên phải hạn chế quyền truy cập vào API server và etcd. Tuy nhiên, dữ liệu Secret có thể được mã hóa ở trạng thái nghỉ (at rest) trong khi lưu trữ trên etcd, nhưng tính năng này cần được bật ở cấp API server.

Giải thích thêm:

  • Lợi ích của Secrets: Sử dụng Kubernetes Secrets cung cấp một lớp bảo vệ bằng cách mã hóa (thường là Base64) thông tin nhạy cảm trước khi đưa vào hệ thống Kubernetes.

  • etcd và mã hóa: etcd là kho lưu trữ dữ liệu chính của Kubernetes. Việc bật mã hóa dữ liệu Secret ở trạng thái nghỉ (tức là khi lưu trữ trên etcd) tăng cường bảo mật hơn nữa.

Create a Secret from Literal Values

Để tạo một Secret, ta có thể sử dụng lệnh kubectl create secret:

$ kubectl create secret generic my-password
--from-literal=password=mysqlpassword

Lệnh trên sẽ tạo ra một secret có tên my-password, trong đó giá trị của khóa password được đặt thành mysqlpassword.

Sau khi tạo Secret thành công, ta có thể phân tích nó bằng các lệnh getdescribe. Các lệnh này không tiết lộ nội dung của Secret. Loại (Type) của nó sẽ được liệt kê là “Opaque”.

Giải thích thêm:

  • kubectl create secret generic: Đây là cách thông dụng để tạo các Secret cho dữ liệu nhạy cảm chung (generic). Kubernetes có các loại Secret chuyên dụng hơn cho những trường hợp như thông tin xác thực Docker.

  • --from-literal: Tùy chọn này cho phép chỉ định trực tiếp các cặp khóa-giá trị để tạo Secret.

  • Opaque Secrets: Loại “Opaque” ám chỉ rằng Secret được thiết kế cho các dữ liệu tùy ý, không có cấu trúc đặc biệt nào được Kubernetes đảm bảo.

$ kubectl get secret my-password

NAME          TYPE     DATA   AGE
my-password   Opaque   1      8m

$ kubectl describe secret my-password

Name:          my-password
Namespace:     default
Labels:        <none>
Annotations:   <none>

Type Opaque

Data
====
password: 13 bytes

Create a Secret from a Definition Manifest

Chúng ta có thể tạo Secret bằng tay từ một bản định nghĩa (manifest) YAML. Ví dụ dưới đây là một bản định nghĩa tên là mypass.yaml. Có hai loại bản đồ (map) cho thông tin nhạy cảm bên trong một Secret: data và stringData.

Với bản đồ data, mỗi giá trị của trường thông tin nhạy cảm phải được mã hóa bằng base64. Nếu muốn có một bản định nghĩa cho Secret, đầu tiên chúng ta phải tạo mã base64 cho mật khẩu của mình:

$ echo mysqlpassword | base64

bXlzcWxwYXNzd29yZAo=

and then use it in the definition manifest:

apiVersion: v1
kind: Secret
metadata:
  name: my-password
type: Opaque
data:
  password: bXlzcWxwYXNzd29yZAo=

Vui lòng lưu ý rằng mã hóa base64 không phải là mã hóa thực sự, và bất kỳ ai cũng có thể dễ dàng giải mã dữ liệu đã được mã hóa của chúng ta:

$ echo "bXlzcWxwYXNzd29yZAo=" | base64 --decode

mysqlpassword

Tại sao điều này lại quan trọng:

  • Base64 và mục đích: Base64 được thiết kế chủ yếu để đảm bảo rằng dữ liệu nhị phân có thể được truyền tải và lưu trữ trong các môi trường chỉ chấp nhận văn bản. Nó không cung cấp biện pháp bảo mật đáng kể.

  • Rủi ro bảo mật: Nếu một người dùng trái phép có quyền truy cập vào Secret được mã hóa bằng Base64, họ có thể dễ dàng giải mã nội dung bí mật.

  • Các biện pháp tốt hơn: Để bảo mật thực sự, các Secret quan trọng nên được mã hóa at rest trong etcd (bằng cách sử dụng các tính năng được Kubernetes cung cấp) hoặc sử dụng một hệ thống quản lý khóa (key management system) bên ngoài.

Hãy nhớ rằng Base64 là một công cụ hữu ích để xử lý dữ liệu nhị phân trong Kubernetes, nhưng bạn không nên dựa vào nó để bảo mật triệt để!

Vì vậy, hãy đảm bảo rằng bạn không lưu trữ file định nghĩa (definition file) của Secret trong mã nguồn (source code) của bạn.

Với bản đồ stringData, không cần phải mã hóa giá trị của từng trường thông tin nhạy cảm. Giá trị của trường nhạy cảm sẽ được tự động mã hóa khi Secret my-password được tạo:

apiVersion: v1
kind: Secret
metadata:
  name: my-password
type: Opaque
stringData:
  password: mysqlpassword

Sử dụng file định nghĩa mypass.yaml, giờ đây chúng ta có thể tạo một Secret bằng lệnh kubectl create:

$ kubectl create -f mypass.yaml

secret/my-password created

Create a Secret from a File

Để tạo Secret từ tệp (file), ta có thể sử dụng lệnh kubectl create secret.

Đầu tiên, chúng ta mã hóa dữ liệu nhạy cảm và sau đó ghi dữ liệu đã mã hóa vào một tệp văn bản:

$ echo mysqlpassword | base64

bXlzcWxwYXNzd29yZAo=

$ echo -n 'bXlzcWxwYXNzd29yZAo=' > password.txt
$ kubectl create secret generic my-file-password \
  --from-file=password.txt

secret/my-file-password created
$ kubectl get secret my-file-password

NAME               TYPE     DATA   AGE 
my-file-password   Opaque   1      8m

$ kubectl describe secret my-file-password

Name:          my-file-password
Namespace:     default
Labels:        <none>
Annotations:   <none>

Type  Opaque

Data
====
password.txt:  13 bytes

Use Secrets Inside Pods: As Environment Variables

Secrets được các Container trong Pod sử dụng dưới dạng data volume được gắn kết (mounted), hoặc dưới dạng các biến môi trường, và được tham chiếu toàn bộ hoặc bằng các cặp khóa-giá trị cụ thể.

Bên dưới, chúng ta chỉ tham chiếu khóa password của Secret my-password và gán giá trị của nó cho biến môi trường WORDPRESS_DB_PASSWORD:

....
spec:
  containers:
  - image: wordpress:4.7.3-apache
    name: wordpress
    env:
    - name: WORDPRESS_DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-password
          key: password
....

Use Secrets Inside Pods: As Volumes

Chúng ta cũng có thể gắn kết (mount) một Secret như một Volume bên trong một Pod. Ví dụ sau tạo một file riêng cho từng khóa của Secret my-password (tên của các file trùng với tên của các khóa), và mỗi file chứa giá trị tương ứng với khóa của nó trong Secret:

....
spec:
  containers:
  - image: wordpress:4.7.3-apache
    name: wordpress
    volumeMounts:
    - name: secret-volume
      mountPath: "/etc/secret-data"
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: my-password
....

For more details, you can explore the documentation on managing Secrets.

Chapter 14. Ingress

Đến cuối chương này, bạn sẽ có thể:

  • Giải thích Ingress và Ingress Controller là gì. Bạn sẽ nắm được các khái niệm cơ bản, mục đích và cách chúng hoạt động trong Kubernetes.

  • Hiểu rõ khi nào nên sử dụng Ingress. Bạn sẽ biết được những tình huống mà việc triển khai Ingress mang lại lợi ích cho ứng dụng của mình.

  • Truy cập ứng dụng từ môi trường bên ngoài sử dụng Ingress. Bạn sẽ học được cách cấu hình Ingress để định tuyến lưu lượng (traffic) từ thế giới bên ngoài đến các dịch vụ (service) cụ thể bên trong cluster Kubernetes.

Ingress

Tuyệt vời! Đây là bản dịch tiếng Việt của đoạn văn đã cho, cùng với một số nhấn mạnh quan trọng:

Với các Service (Dịch vụ), các quy tắc định tuyến được liên kết với một Service nhất định. Chúng tồn tại miễn là Service tồn tại và thường có nhiều quy tắc do có nhiều Service khác nhau trong cluster. Nếu chúng ta có thể tách rời các quy tắc định tuyến khỏi ứng dụng và tập trung quản lý chúng, khi đó ta có thể cập nhật ứng dụng mà không cần lo lắng về truy cập bên ngoài. Điều này có thể được thực hiện bằng cách sử dụng tài nguyên (resource) Ingress.

Theo trang kubernetes.io:
“Ingress là một tập hợp các quy tắc cho phép các kết nối đến (inbound) truy cập tới các Service trong cluster”.

Để cho phép kết nối đến có thể truy cập các Service trong cluster, Ingress cấu hình một bộ cân bằng tải (load balancer) HTTP/HTTPS Layer 7 cho các Service và cung cấp các tính năng sau:

  • TLS (Transport Layer Security): Hỗ trợ mã hóa để tăng cường bảo mật cho việc truyền dữ liệu.

  • Name-based virtual hosting: Cho phép nhiều tên miền có thể được phục vụ bởi cùng một Ingress (quan trọng cho kiến trúc đa dịch vụ).

  • Fanout routing: Khả năng định tuyến lưu lượng đến các Service khác nhau dựa trên các quy tắc (ví dụ: dựa trên URL)

  • Load balancing: Cân bằng tải để đảm bảo hiệu suất và độ sẵn sàng.

  • Custom rules: Cho phép các quy tắc định tuyến tinh vi và tùy chỉnh cho các trường hợp sử dụng cụ thể.

Với Ingress, người dùng không kết nối trực tiếp đến một Service. Người dùng truy cập điểm cuối (endpoint) của Ingress, và từ đó, yêu cầu được chuyển tiếp đến Service cần thiết. Bạn có thể xem một ví dụ về định nghĩa Ingress sử dụng tính năng Name-Based Virtual Hosting dưới đây:

apiVersion: networking.k8s.io/v1 
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
  name: virtual-host-ingress
  namespace: default
spec:
  rules:
  - host: blue.example.com
    http:
      paths:
      - backend:
          service:
            name: webserver-blue-svc
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  - host: green.example.com
    http:
      paths:
      - backend:
          service:
            name: webserver-green-svc
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

Trong ví dụ trên, các yêu cầu của người dùng truy cập vào cả blue.example.comgreen.example.com sẽ đến chung một điểm cuối (endpoint) của Ingress, và sau đó, chúng được chuyển tiếp đến webserver-blue-svc và webserver-green-svc tương ứng.

Sơ đồ này minh họa cho quy tắc Name-Based Virtual Hosting của Ingress:

Chúng ta cũng có thể định nghĩa các quy tắc Fanout Ingress, như trong ví dụ về định nghĩa và sơ đồ bên dưới, khi các yêu cầu đến example.com/blueexample.com/green sẽ lần lượt được chuyển tiếp đến webserver-blue-svc và webserver-green-svc:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
  name: fan-out-ingress
  namespace: default
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /blue
        backend:
          service:
            name: webserver-blue-svc
            port:
              number: 80
        pathType: ImplementationSpecific
      - path: /green
        backend:
          service:
            name: webserver-green-svc
            port:
              number: 80
        pathType: ImplementationSpecific

Tài nguyên (resource) Ingress không tự thực hiện việc chuyển tiếp yêu cầu, nó chỉ đơn thuần lưu giữ định nghĩa các quy tắc định tuyến lưu lượng. Việc thực thi Ingress được xử lý bởi Ingress Controller, một proxy ngược chịu trách nhiệm định tuyến lưu lượng dựa trên các quy tắc được xác định trong tài nguyên Ingress.

Ingress Controller

  • Ingress Controller là một ứng dụng theo dõi API server của Control Plane Node để phát hiện các thay đổi trong các tài nguyên Ingress và cập nhật bộ cân bằng tải (Load Balancer) Layer 7 cho phù hợp. Ingress Controller còn được biết đến với các tên gọi khác như Controller, Ingress Proxy, Service Proxy, Reverse Proxy, v.v.

  • Hỗ trợ đa dạng: Kubernetes hỗ trợ nhiều loại Ingress Controller khác nhau, và nếu cần, chúng ta cũng có thể tự xây dựng. GCE L7 Load Balancer Controller và Nginx Ingress Controller là những controller được sử dụng phổ biến. Một vài controller khác bao gồm Contour, HAProxy Ingress, Istio Ingress, Kong, Traefik, v.v.

  • Tùy chỉnh Controller: Để đảm bảo Ingress Controller theo dõi tài nguyên Ingress tương ứng, bản định nghĩa tài nguyên Ingress cần bao gồm phần ghi chú (annotation) ingress class với tên của controller mong muốn, ví dụ kubernetes.io/ingress.class: "nginx" (trong trường hợp dùng Nginx Ingress Controller).

Khởi động Ingress Controller trong Minikube vô cùng đơn giản. Minikube đi kèm với Nginx Ingress Controller được thiết lập dưới dạng addon, mặc định ở trạng thái tắt. Bạn có thể dễ dàng bật nó bằng lệnh sau:

$ minikube addons enable ingress

Deploy an Ingress Resource

Khi Ingress Controller đã được triển khai, ta có thể tạo một tài nguyên Ingress bằng lệnh kubectl create. Ví dụ: nếu bạn tạo một tệp virtual-host-ingress.yaml có định nghĩa Name-Based Virtual Hosting Ingress như trong phần trước, hãy dùng lệnh sau để tạo tài nguyên Ingress:

$ kubectl create -f virtual-host-ingress.yaml

Access Services Using Ingress

Với tài nguyên Ingress vừa tạo, giờ đây bạn có thể truy cập các dịch vụ webserver-blue-svc hoặc webserver-green-svc bằng các URL blue.example.comgreen.example.com. Vì thiết lập hiện tại sử dụng Minikube, bạn sẽ cần cập nhật tệp cấu hình host (/etc/hosts trên Mac và Linux) của máy trạm tới địa chỉ IP của Minikube cho các URL đó. Sau khi cập nhật, tệp sẽ có nội dung tương tự như:

$ sudo vim /etc/hosts

127.0.0.1        localhost
::1              localhost
192.168.99.100   blue.example.com green.example.com

Lệnh và các thành phần:

  • $ sudo vim /etc/hosts: Lệnh này dùng để mở file /etc/hosts bằng trình soạn thảo văn bản vim với quyền quản trị (sudo).

  • 127.0.0.1 localhost ::1 localhost: Đây là nội dung mặc định thường thấy của file /etc/hosts, nó ánh xạ tên máy “localhost” tới địa chỉ IPv4 loopback (127.0.0.1) và địa chỉ IPv6 loopback (::1).

  • 192.168.99.100 blue.example.com green.example.com: Đây là phần bạn thêm vào để ánh xạ các tên miền blue.example.comgreen.example.com đến địa chỉ IP 192.168.99.100.

Mục đích:

Mục đích của việc chỉnh sửa file /etc/hosts trong ngữ cảnh Kubernetes với Minikube là để máy tính của bạn có thể phân giải các tên miền blue.example.comgreen.example.com tới địa chỉ IP chính xác của cluster Minikube. Điều này cần thiết để bạn có thể truy cập các dịch vụ của ứng dụng được triển khai trên Minikube thông qua Ingress.

Lưu ý quan trọng:

  • Địa chỉ IP của Minikube: Hãy đảm bảo rằng 192.168.99.100 là IP thực tế của cụm Minikube của bạn. Bạn có thể kiểm tra bằng cách chạy lệnh minikube ip.

  • Quyền cao: Bạn sử dụng sudo để có được quyền cần thiết cho việc thay đổi file /etc/hosts.

Sau khi bạn lưu thay đổi trong file /etc/hosts, máy tính của bạn sẽ chuyển hướng các yêu cầu đến blue.example.comgreen.example.com tới cluster Minikube của bạn, nơi Ingress Controller xử lý chúng.

Bây giờ, chúng ta có thể mở blue.example.comgreen.example.com trên trình duyệt và truy cập vào từng ứng dụng.

Chapter 15. Advanced Topics

Cho đến thời điểm này trong khóa học, chúng ta đã dành phần lớn thời gian để tìm hiểu các khái niệm cơ bản của Kubernetes và các quy trình đơn giản nhằm xây dựng một nền tảng vững chắc.

Để hỗ trợ khối lượng công việc lớn trong môi trường production, Kubernetes cũng cung cấp các bộ điều khiển Pod đa Node, bộ điều khiển ứng dụng có trạng thái (stateful), bộ điều khiển hàng loạt (batch), tự động mở rộng quy mô, quản lý tài nguyên và hạn ngạch, quản lý gói, ngữ cảnh bảo mật, chính sách mạng và bảo mật, v.v. Trong chương này, chúng ta sẽ đề cập ngắn gọn đến một số chủ đề nâng cao như vậy, vì việc đi sâu vào chi tiết sẽ nằm ngoài phạm vi của khóa học này.

Mục tiêu học tập:

Đến cuối chương này, bạn sẽ có thể:

  • Trình bày các khái niệm Kubernetes nâng cao: StatefulSets, Helm, Network Policy, Security Admission, Security Context, v.v.

Annotations

Sử dụng Annotations, chúng ta có thể gắn dữ liệu bổ sung (metadata) tùy ý vào các đối tượng Kubernetes với định dạng cặp khóa-giá trị (key-value) như sau:

"annotations": {
  "key1": "value1",
  "key2": "value2"
}

Khác với Label (Nhãn), annotation không được dùng để nhận diện và chọn lọc đối tượng. Annotation có thể được sử dụng cho các mục đích sau:

  • Lưu trữ thông tin build/release: số hiệu phiên bản, số PR, nhánh git, v.v…

  • Thông tin liên lạc: Số điện thoại/số máy nhắn tin của người chịu trách nhiệm, hay đường dẫn tới nguồn thông tin liên lạc.

  • Liên kết/nguồn dữ liệu khác: các hệ thống logging (nhật ký hoạt động), giám sát, phân tích, kho audit (ghi nhận kiểm liệu), công cụ gỡ lỗi…

  • Thông tin về Ingress Controller

  • Thông tin về trạng thái và bản vá/sửa đổi triển khai (Deployment)

Ví dụ, khi tạo một Deployment, chúng ta có thể thêm phần mô tả (annotation) như sau:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webserver
  annotations:
    description: Deployment based PoC dates 2nd Mar'2022
....

Annotations are displayed while describing an object:

$ kubectl describe deployment webserver

Name:                webserver
Namespace:           default
CreationTimestamp:   Fri, 25 Mar 2022 05:10:38 +0530
Labels:              app=webserver
Annotations:         deployment.kubernetes.io/revision=1
                     description=Deployment based PoC dates 2nd Mar'2022
...

Quota and Limits Management

Tuyệt vời! Đây là bản dịch tiếng Việt của đoạn văn đã cho, cùng với một số nhấn mạnh thêm để làm rõ các khái niệm quan trọng:

Khi có nhiều người dùng chia sẻ một cluster Kubernetes, việc đảm bảo sử dụng tài nguyên công bằng luôn là một mối quan tâm. Một người dùng không nên chiếm dụng quá nhiều lợi thế cho riêng mình. Để giải quyết vấn đề này, các quản trị viên có thể sử dụng loại tài nguyên (resource) ResourceQuota API, cho phép đặt giới hạn tổng lượng tài nguyên được sử dụng trong mỗi namespace.

Chúng ta có thể đặt các hạn ngạch (quota) sau cho mỗi namespace:

  • Hạn ngạch tài nguyên tính toán: Giới hạn tổng lượng tài nguyên tính toán (CPU, bộ nhớ, v.v.) có thể được yêu cầu trong một namespace cụ thể.

  • Hạn ngạch tài nguyên lưu trữ Giới hạn tổng lượng tài nguyên lưu trữ (PersistentVolumeClaim, Request.storage, v.v.) có thể được yêu cầu.

  • Hạn ngạch số lượng đối tượng: Hạn chế số lượng đối tượng theo loại (Pod, ConfigMap, PersistentVolumeClaim, ReplicationController, Service, Secret, v.v).

Một tài nguyên bổ sung hỗ trợ giới hạn việc cấp phát tài nguyên cho các Pod và Container trong namespace là LimitRange, được sử dụng cùng với tài nguyên ResourceQuota. LimitRange có thể:

  • Đặt giới hạn sử dụng tài nguyên tính toán cho mỗi Pod hoặc Container trong một namespace.

  • Đặt giới hạn yêu cầu lưu trữ cho mỗi PersistentVolumeClaim trong một namespace.

  • Đặt tỷ lệ giữa yêu cầu (request) và giới hạn (limit) cho một tài nguyên trong một namespace.

  • Đặt các yêu cầu và giới hạn mặc định, tự động thêm chúng vào môi trường của Container tại thời điểm chạy (runtime).

Autoscaling

Trong khi việc thủ công quy mô một số đối tượng Kubernetes là khá dễ dàng, điều này có thể không phải là một giải pháp thực tế cho một cụm được triển khai sẵn sàng cho sản xuất, nơi mà hàng trăm hoặc hàng nghìn đối tượng được triển khai. Chúng ta cần một giải pháp quy mô động để thêm hoặc loại bỏ các đối tượng khỏi cụm dựa trên việc sử dụng tài nguyên, khả dụng và yêu cầu.

Autoscaling có thể được triển khai trong một cụm Kubernetes thông qua các bộ điều khiển định kỳ điều chỉnh số lượng đối tượng chạy dựa trên một, nhiều hoặc các chỉ số tùy chỉnh. Có nhiều loại bộ tự động quy mô khác nhau có sẵn trong Kubernetes có thể được triển khai riêng lẻ hoặc kết hợp để có một giải pháp tự động quy mô mạnh mẽ hơn:

  • Horizontal Pod Autoscaler (HPA) (https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) HPA là một tài nguyên API bộ điều khiển dựa trên thuật toán tự động điều chỉnh số lượng bản sao trong ReplicaSet, Deployment hoặc Replication Controller dựa trên việc sử dụng CPU.

  • Vertical Pod Autoscaler (VPA) VPA tự động đặt yêu cầu tài nguyên Container (CPU và bộ nhớ) trong một Pod và điều chỉnh chúng một cách động trong thời gian chạy, dựa trên dữ liệu sử dụng lịch sử, khả năng tài nguyên hiện tại và các sự kiện thời gian thực.

  • Cluster Autoscaler Cluster Autoscaler tự động thay đổi kích thước cụm Kubernetes khi không đủ tài nguyên để lên lịch các Pod mới hoặc khi có các node trong cụm bị sử dụng kém.

Jobs and CronJobs

Job tạo ra một hoặc nhiều Pod để thực hiện một nhiệm vụ cụ thể. Đối tượng Job chịu trách nhiệm về Pod failures. Nó đảm bảo rằng nhiệm vụ được giao được hoàn thành thành công. Khi nhiệm vụ hoàn thành, tất cả các Pod sẽ tự động chấm dứt. Một số cấu hình của Job bao gồm:

  • parallelism – đặt số lượng pod được phép chạy song song;

  • completions – đặt số lượng lần hoàn thành mong đợi;

  • activeDeadlineSeconds – đặt thời gian tồn tại của Job;

  • backoffLimit – đặt số lần thử lại trước khi Job được đánh dấu là thất bại.

  • ttlSecondsAfterFinished – trì hoãn việc dọn dẹp các Job đã hoàn thành.

Bắt đầu từ Kubernetes phiên bản 1.4, chúng ta cũng có thể thực hiện Job vào các thời điểm/ngày cố định với CronJob, một đối tượng Job mới sẽ được tạo với chu kỳ thực thi. Các cấu hình của CronJob bao gồm:

  • startingDeadlineSeconds – đặt thời hạn để bắt đầu Job nếu thời gian trong lịch đã qua;

  • concurrencyPolicy – cho phép hoặc không cho phép các Job đang chạy đồng thời hoặc để thay thế các Job cũ bằng Job mới.

StatefulSets

Bộ điều khiển StatefulSet (StatefulSet controller) được sử dụng cho các ứng dụng trạng thái (stateful application) – những ứng dụng đòi hỏi một định danh duy nhất, chẳng hạn như tên, nhận dạng mạng hoặc thứ tự nghiêm ngặt. Ví dụ điển hình là cụm MySQL, cụm etcd.

Bộ điều khiển StatefulSet cung cấp định danh và đảm bảo thứ tự triển khai, cũng như mở rộng quy mô cho các Pod. Tuy nhiên, bộ điều khiển StatefulSet cũng chứa các yêu cầu rất chặt chẽ về Service và Storage Volume (Ổ lưu trữ). Điều này tạo nên các thử thách cho quá trình cấu hình và triển khai. Ngoài ra, nó còn hỗ trợ mở rộng, cập nhật theo trình tự (rolling updates) và khôi phục (rollback).

Giải thích thêm:

  • Ứng dụng trạng thái (Stateful applications): Khác với các ứng dụng không trạng thái (stateless) khi dữ liệu chỉ tồn tại tạm thời, ứng dụng trạng thái lưu dữ liệu trên các ổ lưu trữ cố định. Điều này cần sự duy trì định danh của các Pod trong ứng dụng ngay cả khi chúng được khởi động lại hoặc di chuyển.

  • Ví dụ: Các hệ thống quản lý cơ sở dữ liệu (MySQL, etcd) thường là các ứng dụng trạng thái. Chúng cần ổ lưu trữ ổn định và các định danh mạng được duy trì để quản lý và phân phối dữ liệu trong toàn bộ hệ thống.

Custom Resources

Trong Kubernetes, một resource (tài nguyên) là một endpoint của API, nơi lưu trữ một tập hợp các đối tượng API. Ví dụ, resource Pod chứa tất cả các đối tượng Pod.

Mặc dù trong hầu hết các trường hợp, các tài nguyên (resource) hiện có của Kubernetes là đủ cho các yêu cầu, chúng ta cũng có thể tạo ra các tài nguyên mới bằng cách sử dụng các custom resource (tài nguyên tùy chỉnh). Với custom resource, chúng ta không cần điều chỉnh mã nguồn của Kubernetes.

Các tài nguyên tùy chỉnh có bản chất linh hoạt, chúng có thể xuất hiện hoặc biến mất trên một cluster đang hoạt động tại bất kỳ thời điểm nào.

Để tạo một tài nguyên có thể khai báo (declarative), chúng ta phải tạo và cài đặt một custom controller (bộ điều khiển tùy chỉnh) có thể giải thích cấu trúc của resource này và thực hiện các hành động cần thiết. Các custom controller có thể được triển khai và quản lý trong một cluster đang chạy.

Có hai cách để thêm các custom resource:

Custom Resource Definitions (CRDs) Đây là cách dễ dàng nhất để thêm các tài nguyên tùy chỉnh và không yêu cầu kiến thức về lập trình. Tuy nhiên, việc xây dựng một custom controller sẽ cần một số kiến thức lập trình.

API Aggregation (https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/) Để có kiểm soát chi tiết hơn, chúng ta có thể viết các API Aggregator. Đây là các dịch vụ API phụ thuộc, nằm phía sau API Server chính. API Server hoạt động như một proxy cho các request đến API – xử lý các request này dựa trên khả năng của server và ủy quyền các request khác đến các dịch vụ API phụ thuộc.

Tóm tắt các khái niệm quan trọng:

  • Resource: API endpoint trong Kubernetes, lưu trữ các đối tượng có cùng một loại.

  • Custom Resource: Tài nguyên do người dùng tự định nghĩa để mở rộng chức năng của Kubernetes.

  • Declarative: Cách mô tả trạng thái mong muốn, Kubernetes sẽ đảm bảo đạt được trạng thái đó.

  • Custom Controller: Cơ chế để Kubernetes hiểu và xử lý các custom resource.

  • CRD: Phương pháp đơn giản để định nghĩa các custom resource.

  • API Aggregation: Cơ chế cho phép kiểm soát hành vi của các custom resource một cách chi tiết.

Kubernetes Federation

Với Kubernetes Cluster Federation (Liên đoàn cụm Kubernetes) (https://github.com/kubernetes/community/tree/master/sig-multicluster#subprojects), chúng ta có thể quản lý nhiều cụm Kubernetes khác nhau từ một giao diện điều khiển duy nhất. Chúng ta có thể đồng bộ hóa các tài nguyên trên các cụm liên kết và thực hiện chức năng khám phá chéo cụm (cross-cluster discovery). Điều này cho phép chúng ta triển khai ứng dụng trên nhiều vùng miền, truy cập chúng bằng một bản ghi DNS toàn cầu và đạt được tính khả dụng cao (High Availability).

Mặc dù vẫn là một tính năng Beta, Cluster Federation rất hữu ích khi muốn xây dựng các giải pháp kết hợp (hybrid solution). Chẳng hạn, có một cụm chạy trong trung tâm dữ liệu riêng và cụm khác trên đám mây, giúp chúng ta tránh bị phụ thuộc vào một nhà cung cấp dịch vụ. Chúng ta cũng có thể gán trọng số cho từng cụm trong Federation, để phân phối tải dựa trên các quy tắc tùy chỉnh.

Security Contexts and Pod Security Admission

Đôi khi chúng ta cần phải xác định các quyền và cài đặt kiểm soát truy cập cụ thể cho Pod và Container. Ngữ cảnh Bảo mật cho phép chúng ta đặt Điều khiển Truy cập Tùy ý cho quyền truy cập đối tượng, chạy với đặc quyền, khả năng, nhãn bảo mật, v.v. Tuy nhiên, tác dụng của chúng bị giới hạn trong từng Pod và Container riêng lẻ nơi cấu hình ngữ cảnh như vậy được đưa vào phần spec.

Để áp dụng cài đặt bảo mật cho nhiều Pod và Container trên toàn cụm, chúng ta có thể sử dụng Pod Security Admission, một bộ điều khiển admission có sẵn cho Bảo mật Pod được kích hoạt theo mặc định trong API Server. Nó có thể thực thi ba Tiêu chuẩn Bảo mật Pod ở cấp không gian tên, bằng cách tự động hóa việc hạn chế ngữ cảnh bảo mật cho pod khi chúng được triển khai. Mỗi hồ sơ Tiêu chuẩn Bảo mật Pod, privileged, baseline, và restricted, xác định một cấp độ bảo mật, từ hoàn toàn không bị hạn chế (cho workload đặc quyền), đến thực thi các thực hành tốt nhất về làm cứng pod (cho các ứng dụng quan trọng về bảo mật và người dùng ít đáng tin cậy hơn). Các cấp độ bảo mật được xác định bởi các tập hợp kiểm soát ngữ cảnh bảo mật pod được xác định trước cho mỗi tiêu chuẩn.

Network Policies

Kubernetes được thiết kế để cho phép tất cả các Pod giao tiếp tự do, không hạn chế, với tất cả các Pod khác trong Không gian Tên (Namespace) của cụm. Theo thời gian, rõ ràng đây không phải là một thiết kế lý tưởng, và các cơ chế cần được đưa ra để hạn chế giao tiếp giữa một số Pod và các ứng dụng nhất định trong Không gian Tên của cụm. Chính sách Mạng (Network Policies) là các tập hợp quy tắc xác định cách thức Pod được phép trao đổi với các Pod và tài nguyên khác bên trong và bên ngoài cụm. Các Pod không thuộc phạm vi của bất kỳ Chính sách Mạng nào sẽ tiếp tục nhận lưu lượng truy cập không hạn chế từ bất kỳ điểm cuối nào.

Chính sách Mạng rất giống với các Tường lửa (Firewall) điển hình. Chúng được thiết kế để bảo vệ chủ yếu những tài sản nằm bên trong Tường lửa nhưng cũng có thể hạn chế lưu lượng đi ra ngoài dựa trên các tập hợp quy tắc và chính sách.

Tài nguyên API của Chính sách Mạng chỉ định các bộ chọn Pod (podSelectors), các loại chính sách Nhập (Ingress) và/hoặc Xuất (Egress), cùng các quy tắc dựa trên các khối IP (ipBlock)cổng (ports) nguồn và đích. Các chính sách cho phép mặc định hoặc từ chối mặc định rất đơn giản cũng có thể được xác định. Theo best practices, bạn nên xác định chính sách từ chối mặc định để chặn tất cả lưu lượng truy cập đến và đi từ Không gian Tên, sau đó xác định các tập hợp quy tắc cho phép lưu lượng cụ thể ra vào Không gian Tên.

Hãy nhớ rằng không phải tất cả các giải pháp mạng có sẵn cho Kubernetes đều hỗ trợ Chính sách Mạng. Hãy xem lại phần Giao tiếp giữa Pod với Pod (Pod-to-Pod Communication) từ chương Kiến trúc Kubernetes nếu cần. Theo mặc định, Chính sách Mạng là các tài nguyên API có không gian tên, nhưng một số plugin mạng cung cấp các tính năng bổ sung để có thể áp dụng Chính sách Mạng trên toàn cụm.

Monitoring, Logging, and Troubleshooting

Trong Kubernetes, chúng ta phải thu thập dữ liệu sử dụng tài nguyên của Pod, Dịch vụ (Services), nút (node), v.v. để hiểu mức tiêu thụ tài nguyên tổng thể và đưa ra quyết định mở rộng quy mô cho một ứng dụng nhất định. Hai giải pháp giám sát Kubernetes phổ biến là Máy chủ số liệu Kubernetes (Kubernetes Metrics Server) và Prometheus.

Máy chủ Số liệu (Metrics Server) Máy chủ số liệu là một công cụ tổng hợp dữ liệu sử dụng tài nguyên trên toàn cụm – đây là một tính năng tương đối mới trong Kubernetes.
Prometheus Prometheus, hiện là một phần của CNCF (Cloud Native Computing Foundation), cũng có thể được sử dụng để thu thập thông tin sử dụng tài nguyên từ các thành phần và đối tượng Kubernetes khác nhau. Sử dụng các thư viện máy khách của nó, chúng ta cũng có thể đo đạc (instrument) mã của ứng dụng.

Một khía cạnh quan trọng khác để khắc phục sự cố và gỡ lỗi là ghi nhật ký (logging), trong đó chúng ta thu thập nhật ký từ các thành phần khác nhau của một hệ thống nhất định. Trong Kubernetes, chúng ta có thể thu thập nhật ký từ các thành phần cụm khác nhau, đối tượng, nút, v.v. Tuy nhiên, thật không may, Kubernetes không cung cấp ghi nhật ký trên toàn cụm theo mặc định, do đó cần các công cụ của bên thứ ba để tập trung và tổng hợp nhật ký hệ thống. Một phương pháp phổ biến để thu thập nhật ký là sử dụng Elasticsearch cùng với Fluentd có cấu hình tùy chỉnh làm tác nhân trên các nút. Fluentd là một trình thu thập dữ liệu mã nguồn mở, cũng là một phần của CNCF.

Các công cụ khắc phục sự cố của bên thứ ba đang giải quyết một thiếu sót của Kubernetes về khả năng ghi nhật ký của nó. Mặc dù chúng ta có thể trích xuất nhật ký vùng chứa (container logs) từ cụm, nhưng chúng ta chỉ giới hạn ở nhật ký của các vùng chứa hiện đang chạy và trong trường hợp khởi động lại vùng chứa nhiều lần do lỗi – nhật ký của vùng chứa bị lỗi cuối cùng (sử dụng cờ -p hoặc –previous). Nhật ký có thể được hiển thị cho một Pod có một vùng chứa hoặc vùng chứa cụ thể trong Pod có nhiều vùng chứa (sử dụng cờ -c):

$ kubectl logs pod-name

$ kubectl logs pod-name -c container-name

$ kubectl logs pod-name -c container-name -p

Ngoài ra, người dùng có thể chạy một lệnh tùy chỉnh trong một vùng chứa đang chạy của Pod hoặc tương tác với vùng chứa đang chạy từ thiết bị đầu cuối (sử dụng cờ -it và gọi trình thông dịch dòng lệnh của vùng chứa):

$ kubectl exec pod-name — ls -la /

$ kubectl exec pod-name -c container-name — env

$ kubectl exec pod-name -c container-name -it — /bin/sh

Có các trường hợp khi Pod của một ứng dụng không đạt được trạng thái chạy dự kiến, có thể thấy trong đầu ra của lệnh kubectl get pods. Để khám phá nguyên nhân khiến Pod không chạy – có thể là thiếu dependency, sự cố hình ảnh vùng chứa hoặc sự cố thời gian chạy (runtime), chúng ta có thể xem các sự kiện cho toàn bộ cụm hoặc cho một Pod cụ thể trong đầu ra của lệnh describe:

$ kubectl get events

$ kubectl describe pod pod-name

Helm

Để triển khai một ứng dụng phức tạp, chúng ta sử dụng một số lượng lớn các tệp cấu hình (manifest) Kubernetes để xác định các tài nguyên API như Deployment, Service, PersistentVolume, PersistentVolumeClaim, Ingress hoặc ServiceAccount. Việc triển khai từng cái một có thể trở nên phản tác dụng. Chúng ta có thể đóng gói tất cả các tệp cấu hình này sau khi đã tạo khuôn mẫu (templatize) cho chúng thành một định dạng được xác định rõ ràng, cùng với các siêu dữ liệu khác (metadata). Gói này được gọi là một Chart. Những Chart này sau đó có thể được phục vụ thông qua các kho lưu trữ (repository), tương tự như những kho chúng ta có cho các gói rpm và deb.

Helm là một trình quản lý gói (tương tự như yum và apt cho Linux) dành cho Kubernetes, có thể cài đặt/cập nhật/xóa những Chart này trong cụm Kubernetes.

Helm là một ứng dụng dòng lệnh (CLI client) có thể chạy song song với kubectl trên máy của chúng ta, cũng sử dụng kubeconfig để giao tiếp an toàn với máy chủ Kubernetes API.

Ứng dụng Helm truy vấn các kho lưu trữ Chart để tìm kiếm Chart dựa trên các tham số tìm kiếm, tải xuống Chart mong muốn và sau đó yêu cầu máy chủ API triển khai các tài nguyên được xác định trong Chart lên cụm. Các Chart đã được gửi đến Kubernetes có sẵn ở đây.

Thông tin bổ sung về Helm Chart có thể được tìm thấy ở đây: here.

Service Mesh

Service Mesh: Giải pháp thay thế cho kết nối trong Kubernetes

  • Service Mesh là một giải pháp của bên thứ ba, thay thế cho cách kết nối và mở các ứng dụng truyền thống trong Kubernetes (thông qua Services và Ingress Controllers). Service Mesh đang trở nên phổ biến, đặc biệt với các công ty lớn quản lý các cụm Kubernetes lớn hơn, phức tạp hơn.

  • Những giải pháp này cung cấp những tính năng như phát hiện dịch vụ (service discovery), định tuyến đa đám mây (multi-cloud routing) và đo đạc lưu lượng (traffic telemetry).

Cách Service Mesh hoạt động

  • Service Mesh thường hoạt động dựa trên một thành phần proxy nằm trong Data Plane (Mặt phẳng dữ liệu), được quản lý bởi Control Plane (Mặt phẳng điều khiển).

  • Control Plane chạy các chương trình (agent) chịu trách nhiệm cho việc phát hiện dịch vụ, đo đạc, cân bằng tải, chính sách mạng và gateway.

  • Thành phần proxy của Data Plane được chèn (inject) vào các Pod, chịu trách nhiệm xử lý tất cả các giao tiếp giữa các Pod, đồng thời duy trì kết nối liên tục với Control Plane của Service Mesh.

Các triển khai phổ biến của Service Mesh:

Application Deployment Strategies

Các chiến lược triển khai ứng dụng trong Kubernetes

  • Rolling Update (Cập nhật dần dần): Kubernetes cung cấp cơ chế này thông qua “Deployment”. Chiến lược này cập nhật dần các phiên bản ứng dụng của bạn. Mặc dù tiện lợi, hạn chế của nó là trong suốt quá trình chuyển đổi, lưu lượng truy cập được gửi tới cả phiên bản ứng dụng cũ và mới mà không có cách đơn giản nào để cô lập chúng.

  • Chiến lược Canary: Giải quyết hạn chế của Rollin Update. Bạn chạy đồng thời HAI phiên bản ứng dụng khác nhau được quản lý bởi hai Deployment riêng biệt, nhưng cả hai cùng được tiếp cận bởi một Service. Bạn có thể điều chỉnh lượng truy cập mà mỗi Deployment nhận bằng cách mở rộng hoặc thu hẹp chúng, kiểm soát tỉ lệ người dùng truy cập phiên bản mới.

  • Chiến lược Blue/Green: Cũng sử dụng hai môi trường ứng dụng độc lập, nhưng chỉ MỘT môi trường nhận lưu lượng truy cập trực tiếp, trong khi môi trường thứ hai không hoạt động hoặc trải qua kiểm tra nghiêm ngặt. Sau khi đảm bảo, lưu lượng truy cập được chuyển đổi sang môi trường mới. Chiến lược này cũng cần hai Deployment độc lập, mỗi Deployment tiếp cận bởi Service riêng, nhưng cần thêm một cơ chế chuyên dụng để chuyển đổi lưu lượng, thường dùng Ingress.

Mục đích của việc sử dụng các chiến lược thay thế

Các chiến lược Canary và Blue/Green mang đến khả năng kiểm soát tốt hơn cách thức phiên bản ứng dụng mới được tiếp cận, giúp giảm thiểu rủi ro khi triển khai và cho phép thử nghiệm trong môi trường sản xuất một cách hạn chế.

Kubernetes Community

Kubernetes: Sự công nhận và cộng đồng sôi nổi

  • Sức hút mã nguồn mở: Với hơn 85 nghìn sao trên Github (85K GitHub stars), Kubernetes là một trong những dự án mã nguồn mở phổ biến nhất. Cộng đồng Kubernetes không chỉ đóng góp phát triển phần mềm, mà còn tích cực chia sẻ kiến thức về nó.

  • Các hoạt động của cộng đồng: Cộng đồng Kubernetes tham gia vào các hoạt động cả trực tuyến và ngoại tuyến, trao đổi và hỗ trợ lẫn nhau.

  • K8s Port: Công nhận đóng góp: Dự án K8s Port được tạo ra nhằm công nhận và thưởng cho các thành viên đóng góp tích cực cho Kubernetes. Các hình thức đóng góp này bao gồm: viết code, tham dự và phát biểu tại các buổi gặp mặt (meetup), giải đáp thắc mắc trên Stack Overflow, v.v.

Weekly Meetings and Meetup Groups

Weekly MeetingsA weekly community meeting happens using video conference tools. You can request a calendar invite from here.

Meetup GroupsThere are many meetup groups around the world, where local community members meet at regular intervals to discuss Kubernetes and its ecosystem.

Kubernetes Community Days

With events in Amsterdam, Bengaluru, Berlin, London, Montreal, Munich, Portland, Paris, Quebec, Tokyo, and Washington DC.

Cloud Native Community Groups

With events in Canada, Mexico, and United States.

There are some online meetup groups as well, where community members can meet virtually.

Slack Channels and Mailing Lists

Các kênh trao đổi của cộng đồng Kubernetes

  • Slack Channels:Kubernetes Slack vô cùng năng động trên nền tảng Slack. Có nhiều kênh thảo luận tập trung vào các chủ đề khác nhau, bất kỳ ai cũng có thể tham gia và đóng góp ý kiến. Để trò chuyện trực tiếp với đội ngũ Kubernetes, hãy sử dụng kênh #kubernetes-users.

  • Mailing Lists (Danh sách gửi thư): Kubernetes có danh sách gửi thư dành cho usersdevelopers , mọi người quan tâm đều có thể đăng ký tham gia.

SIGs and Stack Overflow

Special Interest Groups (SIGs) – Các nhóm quan tâm đặc biệt

  • SIGs là các nhóm tập trung vào những mảng cụ thể trong dự án Kubernetes, ví dụ như: lập lịch trình (scheduling), cấp phép (authorization), mạng (networking), tài liệu hướng dẫn (documentation), v.v.

  • Mỗi nhóm có thể có quy trình làm việc riêng biệt, phù hợp với yêu cầu công việc của họ. Bạn có thể tìm thấy danh sách đầy đủ các SIG hiện tại tại đây: https://github.com/kubernetes/community/blob/master/sig-list.md.

  • Các SIG mới có thể được thành lập dựa vào nhu cầu phát triển của dự án.

Hỗ trợ từ cộng đồng

Ngoài Slack và các mailing list, các thành viên trong cộng đồng Kubernetes cũng có thể nhận trợ giúp từ Stack Overflow. Đây là một nền tảng trực tuyến nơi bạn có thể đặt ra các câu hỏi mà bạn chưa tìm thấy câu trả lời. Đội ngũ Kubernetes cũng theo dõi các bài đăng được gắn thẻ Kubernetes trên trang web này.

What’s Next on Your Kubernetes Journey?

Đây là bản dịch và một vài gợi ý cụ thể để tiếp tục hành trình khám phá Kubernetes:

Bây giờ bạn đã hiểu rõ hơn về Kubernetes, bạn có thể tiếp tục bằng cách:

  • Tham gia cộng đồng: Trò chuyện và tham gia các hoạt động thảo luận do cộng đồng Kubernetes tổ chức.

  • Sự kiện: Tham dự các sự kiện được tổ chức bởi Cloud Native Computing Foundation (CNCF) và The Linux Foundation.

  • Học tập thêm & chứng chỉ: The Linux Foundation và CNCF cung cấp nhiều khóa đào tạo và các tùy chọn chứng chỉ khác nhau (chi tiết ở các phần sau).

  • Đóng góp cho dự án: Viết code, đóng góp tài liệu hướng dẫn, v.v.

  • Và còn rất nhiều lựa chọn khác!

Một vài gợi ý để bắt đầu