# Kubernetes 架構

### Overview Kubernetes 架構

#### 以Components 角度看Kubernetes

* Control Pane:用於管理其他Node、Service、Pod的工具，是由K8s Server擁有，也可以透過該原件排程等等。
* DNS Server: 賦予Node、Service、Pod的Domain Name。
* Kubelete: Node 透過該工具去管理Node 中的Service、Pod。
* etcd: 儲存各種k8s的狀態。
* Kube Proxy: 用於管理除了Server Node Network。

![K8s 架構](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2F04BZXELJ3TceWUJXfKYa%2Fimage.png?alt=media\&token=6b7993e9-30fb-49e8-ad1a-241525b38d4a)

在K8s 分成兩種Node，K8s Server 與 agent兩種\[5]，***差別在於是否具有權限管理其他的Node***，也就是是否具有Control Pane 元件的Node。而Control Pane 主要能夠透過kubelete 去操作其他的Node中的Pod、Service...等等。

#### **以服務角度看Kubernetes**

在K8s定義下，Service 是抽象化一群Pod的意思，舉個例子一套系統會有各種DB、Message Queue、Functionalities 共由三個Pod，使用者可以定義這三個Pod 作為一組Service，稱Backend Service。

![Service In K8s ](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2FVRYj7eAK8YdX8DveDIBw%2Fimage.png?alt=media\&token=ddc5c2cc-4d02-4b77-9dc1-f7266f325741)

然而在實際的應用是由多個 Service 組成，像是一般網站至少有兩個Service，Frontend Service、Backend Service，以下圖為例，在k8s要組成一個應用則會有多個Service相互作用才能達成。

![A Service](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2FPMQxABh3CXfljbvs6nTf%2Fimage.png?alt=media\&token=2ce52492-32d9-4415-a775-d7c2f6788467)

Service 主要分成四種網路型態\[1]:

* ClusterIP: Exposes the Service on a cluster-internal IP.
* NodePort: Exposes the Service on each Node's IP at a static port (the `NodePort`).&#x20;
* LoadBalancer:Exposes the Service externally using a cloud provider's load balancer
* ExternalName:Maps the Service to the contents of the `externalName` field

**網路狀態看Kubernetes**&#x20;

對於開發服務的工程師而言，各Container其實才是真的功能面的最小單位，如http, ssh, mqtt等。在k8s 中是把一群的container 視為最小單位(Pod)，換句話說以**維運**的角度整體服務才是最小單位。因此k8s 需要Mapping機制使得Container, Pod, Service 這之間可以對的上。以下圖為例，**k8s 中共分成3個component分別為Container, Pod, Service。在Container 的部分維運者需要為各功能取名，如http, mqtt, ssh 等功能名稱於Pod 設定檔，此時的Pod 就被視為一個單一功能。*****而Service則會將這些功能組合成一個服務，透過Mapping Pod 中所定義的名稱、Port組合*****。最後將服務的存取位置釋放給Node，也就是Endpoint 設定。**

![k8s Node網路結構](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2FRLngw4p1e0WRBjbsSKyu%2Fimage.png?alt=media\&token=95a8ebcf-9fc1-43c6-8f12-37aeccd3a1d7)

對於在k8s 中除了Node 內部網路的設定，也還包含Cluster 中 Node 網路的設定，也就是 Ingress 。

Ingress 使用於External Client 實際Query 的請求Route，Client 不用特別指定使用的機器，而是開發者事先設定Cluster 的Routing。可參考下圖示例。

![how ingress do work?](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2FSAobmbJHGeAIWr2oIgAw%2Fimage.png?alt=media\&token=fe22a624-25c0-4efa-96d6-22d39084a6aa)

### 範例實作

由於k8s 本身的硬體需求比較龐大，因此各家機構紛紛推出自己的k8s開放工具，如Ubuntu基金會的Micro-K8s 或者 Rancher 的 k3s...等等，本範例使用k3s 進行解說，測試環境作業系統為ubuntu 20.04。共解說兩個範例1. Run A Service in K8s, 2. Run A Service in k8s agent。

**K8s ymal 檔案主要有幾個必填項目：**

* `apiVersion` - Which version of the Kubernetes API you're using to create this object
* `kind` - What kind of object you want to create
* `metadata` - Data that helps uniquely identify the object, including a `name` string, `UID`, and optional `namespace`
* `spec` - What state you desire for the object

**Attachment(1) nginx Pod config**

其中 pod中的 labels 非常重要，這裡決定Service 的selector 中要完全一樣才能夠成功mapping.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
```

#### Attachement(2) nginx Serivce config

Service 中 selector 指的是所選擇的Pod 名稱，然而也可以選擇多個但以下範例只填一個。在Service yaml 檔案中，需要住要 type 欄位，如果選擇NodePort 可以供外部電腦存取。

```yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:  
    app: nginx
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30390
```

#### **執行 pod**

```shell
sudo kubectl apply -f nginx-pod.yaml
```

#### 執行service

```
sudo kubectl apply -f nginx-service.yaml
```

#### Describe Service

![](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2FVLCQtiYt3iwpUfSAspJ2%2Fimage.png?alt=media\&token=ad9b183d-471b-4ce7-9e01-066193d1bde0)

#### Test

* curl 10.42.0.50.80 -> 透過Endpoint : port 由server 內部進入

![](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2FSkrITznC6ec5hx31GOXL%2Fimage.png?alt=media\&token=35f21387-3c57-477b-af16-7a302548522d)

* curl 172.20.10.3:30390 -> curl external ip : nodePort

![](https://853423727-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZBn9owI5fBe0HrECdk%2Fuploads%2FSeysVtLBEZqbPfJDIYj3%2Fimage.png?alt=media\&token=6391e352-b2f8-4dc3-9e4e-f3da7967d4da)

### Reference

\[1] <https://kubernetes.io/docs/concepts/services-networking/service/>\
\[2] <https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status>\
\[3] <https://rancher.com/docs/k3s/latest/>\
\[4] Luksa, Marko. *Kubernetes in action*. Simon and Schuster, 2017.\
\[5] <https://k3s.io/>
