# Lý thuyết k8s P1 - Cấu trúc và Các thành phần chính
## Kiến thức cơ bản
### Concept of container
Container là một công nghệ ảo hóa cấp hệ điều hành, nhẹ và di động, sử dụng namespace để cô lập các môi trường hoạt động phần mềm khác nhau và sử dụng mirror image để chứa môi trường hoạt động phần mềm
Từ đó container có thể dễ dàng được vận hành ở bất kỳ đâu, do kích thước nhỏ và khởi động nhanh của container. Do đó, mỗi ứng dụng có thể được đóng gói trong mỗi mirror image của container.
Việc sử dụng container không cần phụ thuộc vào môi trường cơ sở hạ tầng bên ngoài, vì mỗi ứng dụng không yêu cầu phụ thuộc bên ngoài, và không cần phụ thuộc vào môi trường cơ sở hạ tầng bên ngoài, giải quyết hoàn hảo vấn đề nhất quán từ môi trường phát triển đến môi trường sản xuất
### Pod concept
+ Đơn vị nhỏ nhất trong K8s
+ Thông thường 1 application/pod
+ mỗi pod có 1 ip address riêng biệt dùng để giao tiếp với các pod khác

```
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
-name: nginx
image: nginx
ports:
-containerPort: 80
```
### Node concept
Một Node là host thực hiện hoạt động thực của Pod, có thể là một máy vật lý hoặc một máy ảo. Để quản lý mỗi Node, cần ít nhất ba dịch vụ: Container Runtime (như Docker hoặc rkt), Kubelet và Kube-proxy.

### Service
+ pod giao tiếp với nhau thông qua service
+ permanent IP address
+ lifecycle của pod và service không kết nối với nhau
+ có 2 loại service: external(vd web) và internal(vd db)

### ConfigMap
+ External Configuration của application (VD: DB_URL=blabla,...)
+ Pod sẽ sử dụng thông tin từ configmap do đó khi ta sửa các thông số thì không cần phải rebuild lại
### Secret
+ Giống config map,nhưng dùng để chứa secret data
+ Các data được encode base64
### DataStorage
+ Nếu container hoặc pod restart, data sẽ biến mất.
+ Do đó volume được sử dụng để lưu trữ dữ liệu, volume có thể nằm trên local hoặc remote machine
+ Nếu đang chạy nhiều pod trên nhiều physical node ta nên sử dụng một remote storage để all pod có thể access.
### Deployment
Triển khai (Deployment) trong Kubernetes được sử dụng để quản lý và tự động hóa việc triển khai các ứng dụng hoạt động trên cụm Kubernetes. Đây là một phần quan trọng của việc quản lý vòng đời của ứng dụng trong môi trường Kubernetes.
+ **Quản lý số lượng bản sao (replicas):** Triển khai cho phép xác định số lượng bản sao của ứng dụng mà bạn muốn triển khai trên cụm Kubernetes. Bằng cách này, bạn có thể dễ dàng mở rộng hoặc thu nhỏ ứng dụng của mình tùy thuộc vào nhu cầu.
+ **Rolling updates**: Deployment thực hiện các bản cập nhật (updates) bằng cách sử dụng phương pháp rolling update, tức là triển khai một phiên bản mới của ứng dụng một cách dần dần, đảm bảo rằng dịch vụ vẫn hoạt động trong suốt quá trình cập nhật.
+ **Tự phục hồi (self-healing):** Nếu một pod trong triển khai gặp sự cố và không thể hoạt động, Kubernetes sẽ tự động khởi chạy một pod mới để thay thế, giúp dịch vụ tiếp tục hoạt động một cách ổn định.
### StatefulSet
StatefulSet trong Kubernetes là một trừu tượng được sử dụng để triển khai và quản lý ứng dụng yêu cầu status (stateful applications) như cơ sở dữ liệu và các ứng dụng lưu trữ status khác.
+ **Duy trì tên duy nhất cho các pod**: Các pod được triển khai bởi StatefulSet được gắn kết với một tên duy nhất, giúp duy trì tính nhất quán trong các triển khai và vận hành hệ thống.
+ **Duy trì thứ tự triển khai và dừng pod:** StatefulSet đảm bảo rằng các pod được triển khai và dừng theo thứ tự, giúp đảm bảo tính nhất quán trong dữ liệu và status của ứng dụng.
+ **Duy trì lưu trữ vĩnh viễn cho dữ liệu**: StatefulSet hỗ trợ các khả năng lưu trữ vĩnh viễn cho dữ liệu, cho phép các ứng dụng lưu trữ status hoặc dữ liệu quan trọng vào lưu trữ như PersistentVolumes hoặc PersistentVolumeClaims.
> ví dụ khi db bị hỏng, ta cần access đến một clone khác sử dụng deployment, nhưng vì db app là Stafulapplication có nghĩa nó chứa các dữ liệu, StatefulSet được sử dụng để lấy các dữ liệu này

## Architecture Overview

### Worker Node Process
+ **Kubelet**: Là đơn vị quản lý chính trên node (node) của cluster. Thành phần này thiết lập giao tiếp giữa node và kubectl, và chỉ có thể chạy các pod (qua API server). Kubelet không quản lý các container không được tạo bởi Kubernetes.
+ **Container Runtime**: Ví dụ như docker, cần được cài trên node.
+ **Kube-proxy**: Là dịch vụ chịu trách nhiệm cho giao tiếp (dịch vụ) giữa apiserver và node. Cơ sở của nó là IPtables cho các node.

### Master Node Process
+ **Api Server**: Là cách mà người dùng và các pod sử dụng để giao tiếp với quản lý tiến trình chính. Chỉ các request được xác thực mới được phép.
+ **Scheduler**: Lên lịch đảm bảo rằng các pod được kết hợp với các node để Kubelet có thể chạy chúng. Quyết định node nào có nhiều tài nguyên trống và gán pod mới vào đó. Scheduler không bắt đầu các pod mới, nó chỉ giao tiếp với quá trình Kubelet đang chạy bên trong node.

+ **Controller Manager** trong Kubernetes (K8s) là một thành phần quan trọng của hệ thống, có nhiệm vụ duy trì status của cụm bằng cách quản lý và điều khiển các controller. Bằng cách detect sự thay đổi status của Cluster.
+ **etcd**: Có thể được gọi là bộ não của cluster. Mọi thông tin thay đổi của Cluster đếu được lưu trữ ở đây dưới dạng key-value. Mọi hoạt động của Controller manager hay Scheduler đếu dựa vào các dữ liệu của etcd.

Ví dụ Cluster Set-Up

### Default Port của các thành phần:

## Minikube
Minikube có thể được sử dụng để thực hiện một số kiểm tra nhanh trên Kubernetes mà không cần triển khai một môi trường Kubernetes hoàn chỉnh. Nó sẽ chạy các tiến trình master và node trên **một máy tính**. Minikube sẽ sử dụng virtualbox để chạy node.
```
$ minikube start
😄 minikube v1.19.0 on Ubuntu 20.04
✨ Automatically selected the virtualbox driver. Other choices: none, ssh
💿 Downloading VM boot image ...
> minikube-v1.19.0.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s
> minikube-v1.19.0.iso: 244.49 MiB / 244.49 MiB 100.00% 1.78 MiB p/s 2m17.
👍 Starting control plane node minikube in cluster minikube
💾 Downloading Kubernetes v1.20.2 preload ...
> preloaded-images-k8s-v10-v1...: 491.71 MiB / 491.71 MiB 100.00% 2.59 MiB
🔥 Creating virtualbox VM (CPUs=2, Memory=3900MB, Disk=20000MB) ...
🐳 Preparing Kubernetes v1.20.2 on Docker 20.10.4 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
🔎 Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 Enabled addons: storage-provisioner, default-storageclass
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by defaul
$ minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
---- ONCE YOU HAVE A K8 SERVICE RUNNING WITH AN EXTERNAL SERVICE -----
$ minikube service mongo-express-service
(This will open your browser to access the service exposed port)
$ minikube delete
🔥 Deleting "minikube" in virtualbox ...
💀 Removed all traces of the "minikube" cluster
```

## Kubectl Basic
Kubectl là commandline tool cho Kubernetes Cluster. Nó giao tiếp với API Server của Master Process để thực hiện các hành động trong Kubernetes hoặc yêu cầu dữ liệu.
```sh=
kubectl version #Get client and server version
kubectl get pod
kubectl get services
kubectl get deployment
kubectl get replicaset
kubectl get secret
kubectl get all
kubectl get ingress
kubectl get endpoints
```
Ta sẽ work với deployment thay vì pod hoặc repicaset.

```shell=
#kubectl create deployment <deployment-name> --image=<docker image>
kubectl create deployment nginx-deployment --image=nginx
#Access the configuration of the deployment and modify it
#kubectl edit deployment <deployment-name>
kubectl edit deployment nginx-deployment
```

```shell=
#Get the logs of the pod for debbugging (the output of the docker container running)
#kubectl logs <replicaset-id/pod-id>
kubectl logs nginx-deployment-84cd76b964
#kubectl describe pod <pod-id>
kubectl describe pod mongo-depl-5fd6b7d4b4-kkt9
#kubectl exec -it <pod-id> -- bash
kubectl exec -it mongo-depl-5fd6b7d4b4-kkt9q -- bash
#kubectl describe service <service-name>
kubectl describe service mongodb-service
#kubectl delete deployment <deployment-name>
kubectl delete deployment mongo-depl
#Deploy from config file
kubectl apply -f deployment.yml
```
## Yaml Configuration File:
**Metadata:** Phần này thường bao gồm thông tin về tài nguyên, chẳng hạn như tên của nó, không gian tên (namespace), nhãn (labels), chú thích (annotations), và bất kỳ siêu dữ liệu nào khác có liên quan để quản lý tài nguyên trong Kubernetes.
```yaml=
metadata:
name: my-pod
namespace: my-namespace
labels:
app: my-app
annotations:
description: Đây là một pod mẫu
```
**Specification**: Phần này xác định các thứ cần chạy
```yaml=
spec:
containers:
- name: my-container
image: nginx:latest
ports:
- containerPort: 80
```
**Status:** Kubernetes liên tục giám sát status của các tài nguyên và cập nhật status của chúng dựa trên status hiện tại của tài nguyên. Tuy nhiên, trong file config, bạn thường không chỉ định status trực tiếp. Thay vào đó, Kubernetes cập nhật trường status dựa trên status hiện tại của tài nguyên.
```yaml=
status:
phase: Running
conditions:
- type: Ready
status: "True"
lastProbeTime: null
lastTransitionTime: "2024-03-08T00:00:00Z"
```
Kết hợp tất cả, một file config YAML cho một Pod đơn giản trong Kubernetes có thể trông giống như sau:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: my-namespace
labels:
app: my-app
annotations:
description: Đây là một pod mẫu
spec:
containers:
- name: my-container
image: nginx:latest
ports:
- containerPort: 80
status:
phase: Running
conditions:
- type: Ready
status: "True"
lastProbeTime: null
lastTransitionTime: "2024-03-08T00:00:00Z"
```
file YAML này mô tả một Pod có tên "my-pod" chạy một container Nginx trong namespace "my-namespace", với status chỉ ra rằng nó hiện đang chạy và sẵn sàng.
### More in spec:
#### Template:
Nói cách khác là một configuration file nằm trong một configuration file và đại diện cho 1 pod

#### Replicas
Số clone của pod => Phục vụ việc self healing.
#### Port vs Target Port
**Port:**
+ Mục đích: Port (cổng) là cổng mà Service (hoặc Pod) lắng nghe trên container hoặc Pod đó.
+ Định nghĩa: Port được sử dụng để xác định cổng mà Service hoặc Pod sẽ lắng nghe các kết nối đến. Nó được chỉ định trong phần port của cấu hình Service.
+ Ví dụ: Nếu một Service lắng nghe kết nối đến cổng 80, bạn sẽ thấy cấu hình port: 80.
**TargetPort:**
+ Mục đích: TargetPort (cổng đích) là cổng mà Service chuyển tiếp các kết nối đến.
+ Định nghĩa: TargetPort xác định cổng mà các kết nối đến Service sẽ được chuyển tiếp tới trong các Pod hoặc các container nằm trong Pod. Nó thường được sử dụng để chỉ định cổng mà ứng dụng hoặc dịch vụ trong Pod đang lắng nghe.
+ Ví dụ: Nếu một ứng dụng trong Pod đang lắng nghe các kết nối đến cổng 8080, bạn có thể sẽ thấy cấu hình targetPort: 8080.

## Demo:
https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/demo-kubernetes-components
##