+2

Tạo môi trường phát triển K8s bằng Minikube

Yêu cầu trước khi bắt đầu

Môi trường cần thiết là Windows 10 (đối với tôi) hoặc Windows 11 tùy các bạn.

Tải xuống các công cụ cần thiết

Hãy cài đặt Minikube từ liên kết sau:

Chúng ta sẽ sử dụng virtualbox làm driver cho Minikube.

Hãy cài đặt VirtualBox từ đây:

Chúng ta cũng sẽ sử dụng Git. Hãy cài đặt Git từ đây:

Hãy cài đặt Skaffold từ liên kết sau:

Tiếp theo, hãy cài đặt Kubernetes từ đây:

(Nếu bạn sử dụng choco hoặc scoop, việc cài đặt sẽ dễ dàng hơn)

Xác minh cài đặt

Sau khi cài đặt xong, hãy kiểm tra xem bạn có thể truy cập Minikube từ PowerShell không.

Mở PowerShell và chạy lệnh sau:

minikube version

Bạn sẽ nhận được thông tin về phiên bản Minikube:

minikube version: v1.35.0
commit: dd5d320e41b5451cdf3c01891bc4e13d189586ed-dirty

Tương tự, hãy kiểm tra phiên bản Git:

git -v
git version 2.47.1.windows.2

Chạy các lệnh sau trong PowerShell để tạo một dự án mẫu:

cd Documents
mkdir projects
cd projects
mkdir test-project
cd test-project

Bắt đầu Minikube Cluster

1. Một số thuật ngữ quan trọng

Container là gì?

  • Containers là môi trường runtime nhẹ, độc lập, đóng gói ứng dụng cùng với tất cả các phụ thuộc của nó. Containers giúp đảm bảo tính nhất quán trên nhiều môi trường khác nhau.

Pod là gì?

  • Pod là đơn vị triển khai nhỏ nhất trong Kubernetes, hoạt động như một lớp bọc chứa một hoặc nhiều container.

Cluster là gì?

  • Cluster là thành phần cấp cao nhất trong Kubernetes, bao gồm nhiều worker node chạy các Pod.

2. Khởi động Minikube Cluster

Chạy lệnh sau để khởi động Minikube:

minikube start --driver=virtualbox

Minikube sẽ bắt đầu chạy. Nếu bạn sử dụng Docker driver, bạn có thể sử dụng tùy chọn mount như sau:

minikube start --mount --mount-string="$HOME:/src" --driver=docker

Tuy nhiên, với VirtualBox, tùy chọn mount không khả dụng. (Nhưng VirtualBox miễn phí, trong khi Docker Desktop có giới hạn...)

Bây giờ, hãy cài đặt Kubernetes thông qua Minikube:

minikube kubectl -- version

Sau khi Kubernetes được cài đặt, bạn sẽ thấy thông tin về phiên bản của nó:

minikube kubectl -- version
Client Version: v1.32.0
Kustomize Version: v5.5.0
Server Version: v1.32.0

Tạo Pods

Chúng ta sẽ thiết lập môi trường PHP, Nginx, MariaDB.

1. Bật Ingress

Trước tiên, hãy bật Ingress để quản lý routing trong Kubernetes:

minikube addons enable ingress

Sau đó, vui lòng lưu phần sau dưới dạng php-mariadb.yaml. Tệp này chứa định nghĩa về các container trong pod. Xin lưu ý rằng bạn phải sử dụng "LF" cho các ngắt dòng của tệp này chứ không phải "CRLF":

# MariaDB Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  # Deployment name
  name: mariadb
  # Labels for identifying the deployment
  labels:
    app: mariadb
spec:
  # Number of MariaDB instances
  replicas: 1
  selector:
    # Matching labels for pods
    matchLabels:
      app: mariadb
  template:
    metadata:
      labels:
        app: mariadb
    spec:
      containers:
        - name: mariadb
          # Docker image for MariaDB
          image: mariadb:11.3
          # Port on which MariaDB runs
          ports:
            - containerPort: 3306
          # Environment variables for MariaDB
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "rootpassword"
            - name: MYSQL_DATABASE
              value: "mydatabase"
            - name: MYSQL_USER
              value: "myuser"
            - name: MYSQL_PASSWORD
              value: "mypassword"
          # Volume mounting for MariaDB data storage
          volumeMounts:
            - name: mariadb-storage
              mountPath: /var/lib/mysql
      # Definition of volumes
      volumes:
        - name: mariadb-storage
          emptyDir: {}
---
# MariaDB Service
apiVersion: v1
kind: Service
metadata:
  # Service name for MariaDB
  name: mariadb
spec:
  ports:
    - port: 3306
  selector:
    # Selector for connecting to MariaDB pods
    app: mariadb
---
# PHP Application Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  # Deployment name
  name: php-app
  # Labels for identifying the PHP deployment
  labels:
    app: php-app
spec:
  # Number of PHP application instances
  replicas: 1
  selector:
    matchLabels:
      app: php-app
  template:
    metadata:
      labels:
        app: php-app
    spec:
      containers:
        - name: php-app
          # Docker image for PHP application
          image: php:8.3-apache
          # Port on which PHP Apache runs
          ports:
            - containerPort: 80
          # Volume mounting for PHP application code from host machine
          volumeMounts:
            - name: php-app-code
              mountPath: /var/www/html
            - name: apache-config
              mountPath: /etc/apache2/sites-enabled/000-default.conf
              subPath: default
      # Definition of volumes
      volumes:
        - name: php-app-code
          hostPath:
            path: "/mnt/project"
            type: Directory
        - name: apache-config
          configMap:
            name: apache-config
---
# ConfigMap for Apache Configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: apache-config
data:
  default: |
    <VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        <Directory "/var/www/html">
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
            DirectoryIndex index.html index.php
        </Directory>
        ErrorLog /var/log/apache2/error.log
        CustomLog /var/log/apache2/access.log combined
    </VirtualHost>
---
# PHP Application Service
apiVersion: v1
kind: Service
metadata:
  # Service name for PHP application
  name: php-app-service
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80
  selector:
    # Selector for connecting to PHP pods
    app: php-app
---
# Ingress resource for PHP Application
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: php-app-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: localhost
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: php-app-service
                port:
                  number: 80

Sau đó, vui lòng lưu nội dung sau dưới dạng skaffold.yaml:

apiVersion: skaffold/v4beta12
kind: Config
metadata:
  name: php-mariadb-app
deploy:
  kubectl: {}
manifests:
  rawYaml:
    - php-mariadb.yaml

Bây giờ môi trường của chúng ta đã sẵn sàng!

Trước khi bắt đầu môi trường, hãy tạo một thư mục mount:

mkdir mounttest
minikube mount "$Home\\Documents\\projects\\test-project\\mounttest:/mnt/project"

Lệnh mount này sẽ tiếp tục chạy. Đối với các lệnh tiếp theo, vui lòng mở một terminal mới và chạy các lệnh trên đó.

Vui lòng chạy lệnh này (vui lòng đảm bảo rằng bạn đang ở trong thư mục test-project):

cd {the test-project directory}
skaffold delete
skaffold run --force

Lệnh này sẽ tiếp tục chạy. Đối với các lệnh tiếp theo, vui lòng mở một terminal mới và chạy các lệnh trên đó.

Vui lòng đợi một lúc... Môi trường kubernetes của bạn đang được tạo trong cụm Minikube. Việc này sẽ mất thời gian một chút.

Bây giờ PHP và MariaDB của bạn sẽ chạy. Hãy kiểm tra bằng cách sử dụng lệnh kubectl get pods:

kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
mariadb-998f96ddb-84kqs   1/1     Running   0          64s
php-app-bf6f77579-454jl   1/1     Running   0          64s

Nếu tất cả đều là "Ready 1/1", điều đó có nghĩa là môi trường của bạn đang chạy mà không có vấn đề gì.

Nhân tiện, chúng được gọi là pod:

mariadb-998f96ddb-84kqs (pod)
php-app-bf6f77579-454jl (pod)

Các containers được định nghĩa trong tệp YAML sẽ được triển khai bên trong các Pods. Một Pod có thể chứa nhiều Containers.

Đôi khi, chúng ta cần một container riêng biệt để ghi log hoặc thực hiện một chức năng bổ sung. Khi đặt container này vào cùng một Pod với container PHP, nó được gọi là Sidecar Container.

Nếu có bất kỳ Pod nào không sẵn sàng, bạn có thể kiểm tra thông tin chi tiết bằng lệnh sau:

kubectl describe pod php-app-bf6f77579-454jl 

Hoặc kiểm tra logs của Pod bằng lệnh:

kubectl logs php-app-bf6f77579-454jl 

Để xem thông tin trên toàn bộ Cluster, hãy sử dụng:

kubectl get events --sort-by='.metadata.creationTimestamp'

Sau khi các Pods đã được tạo thành công, để truy cập Minikube từ máy host, hãy chạy lệnh sau:

minikube tunnel

Lệnh này sẽ chạy liên tục để duy trì kết nối. Để thực hiện các lệnh khác trong khi tunnel đang chạy, bạn cần mở một terminal mới để tiếp tục nhập lệnh.

Mount /var/www/html lên máy Host và truy cập qua Ingress

Chạy lệnh sau để kiểm tra thông tin Ingress và nhận kết quả trả về:

kubectl get ingress
NAME              CLASS    HOSTS       ADDRESS          PORTS   AGE
php-app-ingress   <none>   localhost   192.168.59.100   80      103s

Sau đó, truy cập 192.168.59.100 từ trình duyệt. Nếu bạn thấy lỗi 404, nghĩa là cấu hình ingress đã hoạt động.

Chạy lại lệnh kiểm tra Ingress để xác nhận địa chỉ IP:

kubectl get ingress
NAME              CLASS   HOSTS       ADDRESS          PORTS   AGE
php-app-ingress   nginx   localhost   192.168.59.100   80      93s

Với địa chỉ 192.168.59.100, hãy cập nhật lại tệp php-mariadb.yaml để định cấu hình ingress.

# Ingress resource for PHP Application
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: php-app-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: 192.168.59.100.nip.io #!!! Change here !!!!
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: php-app-service
                port:
                  number: 80

Chúng ta đã mount thư mục mounttest của host PC vào /mnt/project của Minikube. Đồng thời, /mnt/project lại được mount vào /var/www/html của Pod php-apache.

Hãy tạo tệp index.php trong thư mục mounttest của dự án:

<?php
echo "Hello World!";

Lưu tệp này vào thư mục mounttest của bạn trên máy host.

Bây giờ, hãy mở trình duyệt và truy cập:

http://192.168.59.100.nip.io/

Bạn sẽ thấy dòng chữ Hello World! hiển thị trên màn hình.

  • Nếu bạn thay đổi mã PHP, bạn sẽ thấy sự thay đổi ngay lập tức.
  • Nếu thay đổi không phản ánh ngay, hãy tắt opcache trong php.ini:
opcache.enable=0
opcache.validate_timestamps=1
opcache.revalidate_freq=0

Cấu hình MariaDB để truy cập từ Máy Host

Bây giờ, hãy thay đổi dịch vụ MariaDB để có thể truy cập trực tiếp từ host PC.

# MariaDB Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  # Deployment name
  name: mariadb
  # Labels for identifying the deployment
  labels:
    app: mariadb
spec:
  # Number of MariaDB instances
  replicas: 1
  selector:
    # Matching labels for pods
    matchLabels:
      app: mariadb
  template:
    metadata:
      labels:
        app: mariadb
    spec:
      containers:
        - name: mariadb
          # Docker image for MariaDB
          image: mariadb:11.3
          # Port on which MariaDB runs
          ports:
            - containerPort: 3306
          # Environment variables for MariaDB
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "rootpassword"
            - name: MYSQL_DATABASE
              value: "mydatabase"
            - name: MYSQL_USER
              value: "myuser"
            - name: MYSQL_PASSWORD
              value: "mypassword"
          # Volume mounting for MariaDB data storage
          volumeMounts:
            - name: mariadb-storage
              mountPath: /var/lib/mysql
      # Definition of volumes
      volumes:
        - name: mariadb-storage
          emptyDir: {}
---
kind: Service
apiVersion: v1
metadata:
  name: mariadb
spec:
  type: NodePort
  selector:
    app: mariadb
  ports:
    - port: 3306
      targetPort: 3306
      protocol: TCP
      nodePort: 30036   # for example (must be within the allowed range, e.g., 30000-32767)
---
# PHP Application Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  # Deployment name
  name: php-app
  # Labels for identifying the PHP deployment
  labels:
    app: php-app
spec:
  # Number of PHP application instances
  replicas: 1
  selector:
    matchLabels:
      app: php-app
  template:
    metadata:
      labels:
        app: php-app
    spec:
      containers:
        - name: php-app
          # Docker image for PHP application
          image: php:8.3-apache
          # Port on which PHP Apache runs
          ports:
            - containerPort: 80
          # Volume mounting for PHP application code from host machine
          volumeMounts:
            - name: php-app-code
              mountPath: /var/www/html
            - name: apache-config
              mountPath: /etc/apache2/sites-enabled/000-default.conf
              subPath: default
      # Definition of volumes
      volumes:
        - name: php-app-code
          hostPath:
            path: "/mnt/project"
            type: Directory
        - name: apache-config
          configMap:
            name: apache-config
---
# ConfigMap for Apache Configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: apache-config
data:
  default: |
    <VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        <Directory "/var/www/html">
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
            DirectoryIndex index.html index.php
        </Directory>
        ErrorLog /var/log/apache2/error.log
        CustomLog /var/log/apache2/access.log combined
    </VirtualHost>
---
# PHP Application Service
apiVersion: v1
kind: Service
metadata:
  # Service name for PHP application
  name: php-app-service
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80
  selector:
    # Selector for connecting to PHP pods
    app: php-app
---
# Ingress resource for PHP Application
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: php-app-ingress
spec:
  ingressClassName: nginx
  rules:
    - host: 192.168.59.100.nip.io #!!! Change here !!!!
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: php-app-service
                port:
                  number: 80

Dịch vụ MariaDB trong Minikube hiện đang sử dụng NodePort, giúp chúng ta có thể truy cập từ máy host.

Tiếp theo, hãy dừng quá trình Skaffold đang chạy bằng cách nhấn CTRL + C trong terminal đã khởi chạy lệnh.

Sau đó, điều hướng đến thư mục dự án và chạy lại Skaffold:

cd {the test-project directory}
skaffold delete
skaffold run --force

Lệnh này sẽ xóa tài nguyên cũ và chạy lại toàn bộ quá trình triển khai.

Kế đến, chạy lệnh sau để lấy địa chỉ IP của Minikube:

minikube ip

Ví dụ, nếu địa chỉ IP trả về là 192.168.59.100, ta sẽ sử dụng nó để kết nối đến MariaDB.

Nó sẽ cung cấp cho bạn địa chỉ IP của minikube. Bạn có thể sử dụng IP này và NodePort để truy cập MariaDB.

Với tôi, địa chỉ IP là 192.168.59.100. NodePort được định nghĩa là 30036 trong tệp yaml.

Vì vậy, bằng cách sử dụng cả 192.168.59.100:30036, bạn có thể truy cập MariaDB.

Xin lưu ý rằng môi trường của MariaDB được cấu hình theo cách này:

- name: MYSQL_ROOT_PASSWORD
  value: "rootpassword"
- name: MYSQL_DATABASE
  value: "mydatabase"
- name: MYSQL_USER
  value: "myuser"
- name: MYSQL_PASSWORD
  value: "mypassword"

Bạn có thể sử dụng các thông tin trên để truy cập MariaDB từ ứng dụng PHP hoặc từ máy host.

Hy vọng thông tin trong bài sẽ giúp ích cho các bạn trong việc tạo môi trường phát triển K8s bằng Minikube.

Nếu bạn quan tâm tới Kubernetes, có thể tham khảo thêm bài viết sau: Kubernetes (K8s) là gì? Tìm hiểu cơ bản về Kubernetes


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí