---
title: "【K8S Beginners 筆記】CH 4~6 PODs, YAML, ReplicaSet and Deployments"
date: 2022-12-30
is_modified: false
disqus: cynthiahackmd
image: https://i.imgur.com/2F0W0aE.png
categories:
- "雲端網路 › 雲端運算"
tags:
- "Udemy"
- "Docker"
- "K8S"
- "Kubernetes Beginners"
- "讀書筆記"
- "Published"
---
{%hackmd @CynthiaChuang/Github-Page-Theme %}
<br class="big">
課程都上完了,但筆記還沒寫完 Orz
但往好處想,這篇完成後,我就完成了 1/2 了,至少從章節上看來是如此 XDDD
<!--more-->
<p class="illustration">
<img src="https://i.imgur.com/2F0W0aE.png" alt="課程縮圖">
課程縮圖(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
## CH 4|Kubernetes Concepts
這章的大標雖然是 K8S 的概念,不過其實只講了 pod。對,就是在[上一篇](https://hackmd.io/@CynthiaChuang/Kubernetes-for-the-Absolute-Beginners-01#2-3|Kubernetes-Architecture)中,我自己去查相關定義的那個,這邊就看講師更有系統的說明吧。
<br class="big">
在開始前,先假設些先決條件:
1. 應用程式已經開發完成,並包成了 docker image。
2. 這個 docke image 已經上傳至 registry,無論是公開或是私人倉庫,反正 K8S 拉的回來就好。
3. K8S cluster 已經設置完成並辛勤工作中了!
### 4-1|PODs
對於 K8S 而言,終極目標是將應用程式以 container 的形式部署到 work nodes 中。但若從微觀的視角來說,container 並==不是直接部署==到 node 上,這些 container 會被封裝到 pod 中,最後會以 pod 為單位部署到 node 上執行。
<p class="illustration">
<img src="https://i.imgur.com/PKxEkJd.png" alt="Pod Instance">
Pod Instance(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
Pod 是 K8S 中==最小的運作單位==,可以將它想像成是一個應用程式運行的 instance。注意,**是一個應用程式,而不是一個 container**。雖然多數情況下,pod 跟 container 是一對一的關係,但有些應用會需要 helper containers 以支援特定的任務,如:作為服務的前端、資料庫...等,會將兩者封裝到同一個 pod 中一併啟動。
將同一應用的 containers 放置同一個 pod 中有幾個好處:
1. 同一應用的 containers 生命週期會一致,因為它們是同屬同一個 pod,方便 K8S 管理與部署。
2. 它們共享相同的 network namespace,所以容器間可用 `localhost` 直接溝通。
3. 共享存儲空間。
<p class="illustration">
<img src="https://i.imgur.com/CsYeazp.png" alt="Multi-Container PODs">
Multi-Container PODs
</p>
#### Container 的擴展
之前提過當負載出現異動時,container 會向上或向下擴展。這邊介紹 container 的擴展與 pod 之間的關係。
若要新增應用的 instances 來分擔負載,也是以 **pod 為單位來新增**,它們並非在同一個 pod 中起 container,而是會在相同 ==node 上添加一個相同的 pod==,所以才會說 pod 是最小的運作單位。是說,這也是可以想樣的,你想想如果同時起兩個負責 web 的 container,那麼那個 port 該給誰 XDDD。但若是 node 沒有足夠資源,則是會在將 pod 起在 cluster 中的其他 node 上。
反之,在縮小規模也是如此。當需求下降時,也是刪除 pod 以縮減服務,並非直接刪除 container。
<p class="illustration">
<img src="https://i.imgur.com/S7HT0QO.png" alt="Create a Nwe Container and Pod">
Create a Nwe Container and Pod(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
#### 補充資料
- [Pod Overview](https://kubernetes.io/docs/concepts/workloads/pods/)
### 4-2|Demo:PODs
我把這節的筆記跟上一節沒寫 kubectl 給合併在一起了,因為它們都在介紹跟部署 pod 的相關指令:
1. **kubectl run**
```bash=
$ kubectl run {pod-name} --image {image-name}
```
這是起 pod 用的指令,其中 image 的部分預設會從 docker hub 下載所輸入的 image。若是要從私人倉庫下載[看起來是要另外設定 K8S](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/),我們就先別管它了。
對了,這種方法看起來所啟動的 pod 跟 container 是一對一的關係。
<p class="illustration">
<img src="https://i.imgur.com/LbPXTI9.png" alt="kubectl run">
kubectl run
</p>
2. **kubectl get pods**
```bash=
$ kubectl get pods
```
可用來看 cluster 中的 pod 列表與一些簡單的資訊,如:container 狀態、運行時間...等。
<p class="illustration">
<img src="https://i.imgur.com/lwJehbW.png" alt="kubectl get pods">
kubectl get pods
</p>
<br class="big">
```bash=
$ kubectl get pods
```
如果要看稍微多點的資訊,便帶上 `-o wide`,可以看到如:、IP、所屬 node...等資訊。
<p class="illustration">
<img src="https://i.imgur.com/vu82YB6.png" alt="kubectl get pods -o wide">
kubectl get pods -o wide
</p>
3. **kubectl describe**
與 get 指令相比,describe 提供了更多的資訊,如:label、IP、所屬 node、及 pod 中所有 container 的資訊,如果有多個 container 則會在此陳列。
我認為最重要的是最後的附加訊息,它這邊呈現 pod 中所發生的所有事件,用來 debug 很好用 XDDD
<p class="illustration">
<img src="https://i.imgur.com/Wh3NXLW.png" alt="kubectl describe">
kubectl describe
</p>
對了,上述看到的 IP 的都只能從 node 內部去尋訪。但這些 container 不經配置,是從外部是無法取得的,這部分後面應該會教。
### 4-3|測驗 3:PODs
1. **The smallest unit you can create in Kubernetes object model is:**
- [ ] Service
- [ ] Application
- [x] Pod
- [ ] Container
- [ ] Process
2. **A Pod can only have one container in it**
- [ ] True
- [x] False
3. **What is the right approach to scale an application**
- [ ] Deploy additional containers in the Pod
- [x] Deploy additional Pods
- [ ] You cannot scale an application in Kuberenetes. This is not a use-case of Kubernetes.
## CH 5|YAML Introduction
看這節的投影片跟其他幾個章節的布景主題並不一致,應該是後來補充的,可能有人反應不會寫 YAML?
<p class="illustration">
<img src="https://i.imgur.com/DSYkb8q.png" alt="YAML">
YAML(圖片來源: <a href="https://zh.m.wikipedia.org/zh-hant/YAML">維基百科</a>)
</p>
### 5-1|Introduction to YAML
YAML 全名是(YAML Ain’t a Markup Language)是一個可讀性高,通常用來表達資料序列的格式,特別適合用來表達或編輯資料結構、各種設定檔。在 K8S 這邊就是使用這種語言來撰寫設定檔。
#### XML、 JSON 與 YAML 比較
這節開始前快速比較了三種常見的結構數據 XML、 JSON 與 YAML。
<p class="illustration">
<img src="https://i.imgur.com/7QNzYdg.png" alt="同資料以 XML、JSON 和 YAML 表示">
</p>
在 XML 中,每個==屬性都是以添加標籤的方式來增加==,雖然不影響數據表示,但冗餘資料是三者之中最多。相較之下,JSON 比 XML 簡潔得多,因為它改==以 key-value pair 的方式來記錄資料==,且改採 `:` 分隔 key-value、 `,` 區隔每筆資料,並以 `{...}` 表示物件、 `[...]` 表示陣,因此 JSON 還是比 XML 要小,而且耗時更少。
至於 YAML 也是以 key-value pair 來表示,它甚至移除所有的括號與逗號,因此可以進一步壓縮大小。至於撰寫方式等等一起記錄在下一節好了。
#### 撰寫規則
<p class="illustration">
<img src="https://i.imgur.com/P0sD5ps.png" alt="YAML 撰寫規則">
YAML 撰寫規則(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
1. **key-value pair**
它與 JSON 一樣==冒號==來分隔 key-value。而且跟 JSON 一樣,**冒號後面記得加個空白**,不然會跟我一樣抓蟲抓個半天 XDDD
2. **Array/List**
至於如果是 array,則需要在==每個 array 元素之前加上破折號==。
3. **Dictionary/Map**
若要製作 dictionary 則在其對應鍵值之下列,填上相對應元素,且在**每項之前則是會加上相同數量的空格**。在 YAML 中==縮排的空格數目不重要,重要的是相同層級要左對齊。==
4. **List of dictionary**
其實沒這東西啦,就是 array 的元素是 dictionary,這種時候需特別注意縮排跟破折號,別歸錯類了。
5. **註釋**
YAML 的註解是以 `#` 開頭的。
<br class="big">
至於何時用 dictionary、何時用 array?
1. 無序集合用 dictionary,有序集合用 array。
2. 表示某個物件的構成元素用 dictionary,例如:汽車由顏色、型號、價格...之類的屬性所構成。
### 5-2|編碼練習:YAML
1. **Update the food.yml file to add a Vegetable - Carrot.
Not sure how to solve this? Check the answer in the answer.yaml file.**
```yaml=
Fruit: Apple
Drink: Water
Dessert: Cake
```
答:
```yaml=
Fruit: Apple
Drink: Water
Dessert: Cake
Vegetable: Carrot
```
2. **Update the food.yml file to add a list of Vegetables - Carrot, Tomato, Cucumber**
```yaml=
Fruits:
- Apple
- Banana
- Orange
```
答:
```yaml=
Fruits:
- Apple
- Banana
- Orange
Vegetables:
- Carrot
- Tomato
- Cucumber
```
3. **We have updated the food.yml file with nutrition information for Fruits. Similarly update the nutrition information for Vegetables. Use the below table for information**
| Vegetables | Calories | Fat |Carbs |
| -------- | -------- | -------- |-------- |
| Carrot | 25 | 0.1 | 6 |
| Tomato | 22 | 0.2 | 4.8 |
| Cucumber | 8 | 0.1 | 1.9|
```yaml=
Fruits:
- Apple:
Calories: 95
Fat: 0.3
Carbs: 25
- Banana:
Calories: 105
Fat: 0.4
Carbs: 27
- Orange:
Calories: 45
Fat: 0.1
Carbs: 11
```
答:
```yaml=
Fruits:
- Apple:
Calories: 95
Fat: 0.3
Carbs: 25
- Banana:
Calories: 105
Fat: 0.4
Carbs: 27
- Orange:
Calories: 45
Fat: 0.1
Carbs: 11
Vegetables:
- Carrot:
Calories: 25
Fat: 0.1
Carbs: 6
- Tomato:
Calories: 22
Fat: 0.2
Carbs: 4.8
- Cucumber:
Calories: 8
Fat: 0.1
Carbs: 1.9
```
4. **Jacob is 30 year old Male working as a Systems Engineer at a firm. Represent Jacob's information (Name, Sex, Age, Title) in YAML format. Create a dictionary named Employee and define properties under it.**
答:
```yaml=
Employee:
Name: Jacob
Sex: Male
Age: 30
Title: Systems Engineer
```
5. **Update the YAML file to represent the Projects assigned to Jacob. Remember Jacob works on Multiple projects - Automation and Support. So remember to use a list.**
```yaml=
Employee:
Name: Jacob
Sex: Male
Age: 30
Title: Systems Engineer
```
答:
```yaml=
Employee:
Name: Jacob
Sex: Male
Age: 30
Title: Systems Engineer
Projects:
- Automation
- Support
```
6. **Update the YAML file to include Jacob's pay slips. Add a new property "Payslips" and create a list of pay slip details (Use list of dictionaries). Each payslip detail contains Month and Wage.**
| Month | Wage |
| ------ | ---- |
| June | 4000 |
| July | 4500 |
| August | 4000 |
```yaml=
Employee:
Name: Jacob
Sex: Male
Age: 30
Title: Systems Engineer
Projects:
- Automation
- Support
```
答:
```yaml=
Employee:
Name: Jacob
Sex: Male
Age: 30
Title: Systems Engineer
Projects:
- Automation
- Support
Payslips:
- Month: June
Wage: 4000
- Month: July
Wage: 4500
- Month: August
Wage: 4000
```
## CH 6|Kubernetes Concepts - Pods, ReplicaSets, Deployments
這章來學怎麼為 K8S 寫 YAML 文件,以用來部署 Pod、Service、ReplicaSets 與 Deployment。
### 6-1|PODs with YAML
在標準的 K8S 定義文件中包含 ==4 個必需根屬性:`apiVersion`、`kind`、`metadata` 和 `spec`==。
<p class="illustration">
<img src="https://i.imgur.com/vtkrTEP.png" alt="標準的 K8S 定義文件所包含的根屬性">
標準的 K8S 定義文件所包含的根屬性(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
#### apiVersion
> Which version of the Kubernetes API you're using to create this object
簡單來說,就是我們所使用的 K8S API 版本,最常用的大概是 `v1`、`apps/v1`,其他還有諸如:`apps/v1beta1`、`extensions/v1beta1`...等。這些 api 版本的差別後面課程會說,如果講師忘了這件事的話回頭再來[啃文件](https://kubernetes.io/docs/concepts/overview/kubernetes-api/)吧。
是說,總感覺它跳版跳得很隨意,不僅名字很隨意,連功能也是。有些功能在前一版還是 beta,下一版就跳到 stable ...等等,你的 rc 呢?
#### kind
> What kind of object you want to create
就是你所要建立的物件類型,在這節就是填寫 Pod。其他可以填的值還有 ReplicaSet、Deployment 或 Service。另外,不同類型的物件類型搭配的 apiVersion 不盡相同,如上表所示,使用時需注意。
#### metadata
> Data that helps uniquely identify the object, including a name string, UID, and optional namespace
`metadata` 這部分是用來擺放描述性資料地方,常見包含 `name`、 `label` 跟 `annotation`...等,其中 `name` 算是必備的,其他 `label` 跟 `annotation` 則是便於對物件進行識別、分群、管理與部署。需注意的是 `metadata` 的子屬性必須符合 K8S 的規範,但在 `label` 或 `annotation` 之下,你可以填寫任何你想記錄的 key-value pair。
與前 2 個都是字串的根屬性不同,metadata 是採 **dictionary** 的資料格式,所以撰寫時注意空格與對齊,別認錯父親了 XDDD
#### spec
> What state you desire for the object
定義完相關資訊後,`spec` 這邊則是對內容物的定義,像是最重要的 container 與其 image 就是在此段配置。像我們之前討論過的一個 pod 中存在多個 containers 就是在此處定義,列出個別 container 與其對應的 image。
對了,spec 的資料格式 dictionary,但其子屬性 `containers` 的資料格式是 list,別搞混了。注意別忘記了 `containers` 有 `s` 阿!忘了它的話,蟲會抓超久 XDDD
### 6-2|Demo:PODs with YAML
這節的目的就是嘗試寫一份 yaml 並啟動。
<br class="big">
首先先建立一個名為 `pad.yml`,並使用任一編輯器,如:記事本、vim...等,來撰寫定義文件。根據上節所介紹的 4 個根屬性依序撰寫下來,不過撰寫時需要注意的是:
1. **apiVersion**:pod 搭配的版號是 `v1`。
2. **kind**:pod 使用的物件類型是 `Pod`,因為 YAML 是大小寫敏感的,所以**開頭 P 大寫**是有意義的。
3. **輸寫注意**:同階層的縮排要對齊、還有該有 `s` 的屬性別忘了吧!
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: cynthia-pod-2
labels:
app : nginx
tier: frontend
spec:
containers:
- name: nginx
image: nginx
```
<br class="big"><br class="big">
一旦準備好定義文件後,就可以透過指令來建立 pod:
```bash=
$ kubectl create -f pod.yml
or
$ kubectl apply -f pod.yml
```
<p class="illustration">
<img src="https://i.imgur.com/2V0KQKO.png" alt="透過指令來建立 pod">
透過指令來建立 pod
</p>
這邊有 2 個指令 `create` 與 `apply` 可用,至於兩者有何不同?雖然講師說 It doesn't matter,不過我還是很好奇兩者的差異。
由資料看來,kubectl create 是以**命令(Imperative)** 的方式建立資源。此方法是直接告訴 K8S API 要創建新資源,一旦資源已經存在,就會丟出錯誤訊息:
```bash=
$ kubectl get pods
No resources found.
$ kubectl create -f pod.yml
pod/cynthia-pod-2 created
$ kubectl create -f pod.yml
Error from server (AlreadyExists): error when creating “pod.yml”: pods “cynthia-pod-2” already exists
```
<br class="big">
kubectl apply 則是以**聲明(Declarative)** 的方式建立資源。它會告知 K8S 所要部署資源的定義,將如何部署資源交由 cluster 來決定,如果資源不存在會配置新資源;若資源已經存在,則是根據目前的定義去調整資源。
兩者最直觀的差異,大概就是 `apply` 可以透過修改 YAML 來更改配置,但 `create` 無法,若要更改只能借助其他指令或是刪除資源重新建立。
<p class="illustration">
<img src="https://i.imgur.com/zBhPPFc.png" alt="Kubectl apply vs Kubectl create">
Kubectl apply vs Kubectl create(圖片來源: <a href="https://blog.csdn.net/textdemo123/article/details/104400985">大鹏blog|CSDN</a>)
</p>
<br class="big">
但無論是用哪個方法,在此階段都完成 pod 的建立,可以查看其狀態:
```bash=
$ kubectl get pods
```
<p class="illustration">
<img src="https://i.imgur.com/AUmNLdt.png" alt="檢查 pods 狀態">
檢查 pods 狀態
</p>
或是用更進一步查詢:
```bash=
$ kubectl describe pod {name}
```
<p class="illustration">
<img src="https://i.imgur.com/1P7SjDt.png" alt="查看 pod 詳細狀況">
查看 pod 詳細狀況
</p>
### 6-3|K8S YAML Validation in IDEs
這邊介紹下一些可以支援 K8S YAML 的 IDE,雖然用 vim 跟筆記本也撰寫,但遇到大型 YAML 這會使難度直線上升阿,再加上大家都被 autocomplete 給慣壞了 XDDD
1. **JetBrains 系列**
JetBrains 系列它有支援 YAML,能夠幫忙檢查排版與結構的錯誤。但若要支援 K8S YAML,需額外安裝 [plugin](https://plugins.jetbrains.com/plugin/9354-kubernetes-and-openshift-resource-support)。
2. **VS code**
它也是需要安裝 plugin 以支援 K8S YAML。影片中是用 [RedHat 所發布的 YAML](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)。安裝完後基本上支援 YAML,但要支援 K8S YAML 需額外設定:
`設定` → 選擇作用域 `User` / `Workspace` → `Yaml:Schems` → 在 `settings.json` 內編輯。在 `settings.json` 中,找到 `yaml.schemas` 並增加 `kubernetes`:
```json=
"yaml.schemas": {
"kubernetes": "*.yaml"
}
```
<br class="big">
不過這些都只能檢查 K8S YAML 的排版、結構以及一些特定屬性,其他的標籤與設定必須等到執行階段才能確定。
### 6-4|編碼練習:PODs
1. **Let us start simple! Given a pod-definition.yml file. We are only getting started with it. I have added two root level properties - apiVersion and kind.**
Add the missing two properties - metadata and spec
```yaml=
apiVersion:
kind:
```
答:
```yaml=
apiVersion:
kind:
metadata:
spec:
```
2. **Let us now populate values for each property. Start with apiVersion.**
Update value of apiVersion to v1. Remember to add a space between colon (:) and the value (v1)
```yaml=
apiVersion:
kind:
metadata:
spec:
```
答:
```yaml=
apiVersion: v1
kind:
metadata:
spec:
```
3. **Update value of kind to Pod.**
```yaml=
apiVersion: v1
kind:
metadata:
spec:
```
答:
```yaml=
apiVersion: v1
kind: Pod
metadata:
spec:
```
4. **Let us now get to the metadata section.**
Add a property "name" under metadata with value "myapp-pod". Remember to add a space before 'name' to make it a child of metadata
```yaml=
apiVersion: v1
kind: Pod
metadata:
spec:
```
答:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
```
5. **Let us add some labels to our Pod**
Add a property "labels" under metadata with a child property "app" with a value "myapp". Remember to have equal number of spaces before "name" and "labels" so they are siblings
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
```
答:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
```
6. **We now need to provide information regarding the docker image we plan to use.**
Add a property containers under spec section. Do not add anything under it yet.
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
```
答:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
```
7. **Containers is an array/list. So create the first element/item in the array/list and add the following properties to it: name - nginx and image - nginx**
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
```
答:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
8. **Perfect! You have successfully created a Kubernetes-Definition file. Let us try it one more time, this time all on your own!**
Create a Kubernetes Pod definition file using values below:
- Name: postgres
- Labels: tier => db-tier
- Container name: postgres
- Image: postgres
答:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
tier: db-tier
spec:
containers:
- name: postgres
image: postgres
```
9. **Postgres Docker image requires an environment variable to be set for password.**
Set an environment variable for the docker container. POSTGRES_PASSWORD with a value mysecretpassword. I know we haven't discussed this in the lecture, but it is easy. To pass in an environment variable add a new property 'env' to the container object. It is a sibling of image and name. env is an array/list. So add a new item under it. The item will have properties name and value. name should be the name of the environment variable - POSTGRES_PASSWORD. And value should be the password - mysecretpassword
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
tier: db-tier
spec:
containers:
- name: postgres
image: postgres
```
答:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
tier: db-tier
spec:
containers:
- name: postgres
image: postgres
env:
- name: POSTGRES_PASSWORD
value: mysecretpassword
```
### 6-5|Hands-On Labs:PODs
- [🚪 Familiarise with the lab environment](https://kodekloud.com/topic/labs-familiarize-with-lab-environment-2/)
<br class="big">
因為這是第一次使用 Lab 所以在操作 Pod 前,先熟悉下環境。
1. **How many nodes are part of the cluster?**
**答**:1
<p class="illustration">
<img src="https://imgur.com/GbXESmt.png" alt="How many nodes are part of the cluster?">
</p>
2. **What is the version of Kubernetes running on the nodes ?**
**答**:v1.24.1+k3s1
<p class="illustration">
<img src="https://i.imgur.com/k6ggkyu.png" alt="What is the version of Kubernetes running on the nodes ?">
</p>
3. **What is the flavor and version of Operating System on which the Kubernetes nodes are running?**
**答**:Alpine Linux
<p class="illustration">
<img src="https://i.imgur.com/48bh9RF.png" alt="What is the flavor and version of Operating System on which the Kubernetes nodes are running?">
</p>
<br class="big">
熟悉完環境後,就開始本章重點吧 ~!
- [🚪PODs with YAML](https://kodekloud.com/topic/labs-pods-with-yaml-2/)
<br class="big">
1. **How many pods exist on the system? In the current(default) namespace.**
**答**:0
<p class="illustration">
<img src="https://i.imgur.com/Hi71hKq.png" alt="How many pods exist on the system? In the current(default) namespace.">
</p>
2. **Create a new pod with the nginx image.**
**答**:
<p class="illustration">
<img src="https://i.imgur.com/sBEngaD.png" alt="Create a new pod with the nginx image.">
</p>
3. **How many pods are created now?**
Note: We have created a few more pods. So please check again.
**答**:4
<p class="illustration">
<img src="https://i.imgur.com/iJhiBTB.png" alt="How many pods are created now?">
</p>
4. **What is the image used to create the new pods?**
You must look at one of the new pods in detail to figure this out.
**答**:busybox。喔對,別選自己建的那個,那個 image 絕對是 nginx 呀 XDDD
<p class="illustration">
<img src="https://i.imgur.com/MNaQWsS.png" alt="What is the image used to create the new pods?">
</p>
5. **Which nodes are these pods placed on?**
You must look at all the pods in detail to figure this out.
**答**:controlplane
<p class="illustration">
<img src="https://i.imgur.com/3NkzFZp.png" alt="Which nodes are these pods placed on?">
</p>
6. **How many containers are part of the pod webapp?**
Note: We just created a new POD. Ignore the state of the POD for now.
**答**:2
<p class="illustration">
<img src="https://i.imgur.com/vmZd2hv.png" alt="How many containers are part of the pod webapp?">
</p>
7. **What images are used in the new webapp pod?**
You must look at all the pods in detail to figure this out.
**答**:agentx & nginx
<p class="illustration">
<img src="https://i.imgur.com/Oxzt7Ux.png" alt="What images are used in the new webapp pod?">
</p>
8. **What is the state of the container agentx in the pod webapp?**
Wait for it to finish the ContainerCreating state
**答**:error & waiting
<p class="illustration">
<img src="https://i.imgur.com/c087JPu.png" alt="What is the state of the container agentx in the pod webapp?">
</p>
9. **Why do you think the container agentx in pod webapp is in error?**
Try to figure it out from the events section of the pod.
**答**:A docker image with this name doesn't exist on Docker Hub
<p class="illustration">
<img src="https://i.imgur.com/0puQHFA.png" alt="Why do you think the container agentx in pod webapp is in error?">
</p>
10. **What does the READY column in the output of the kubectl get pods command indicate?**
**答**: Rununing / Totoal contaier on pod。回顧看來,在 webapp pod 中要求了 2 個 container,其中一個順利建立,但另一個因為 ErrImagePull 而啟動失敗。
<p class="illustration">
<img src="https://i.imgur.com/jpbWKVE.png" alt="What does the READY column in the output of the kubectl get pods command indicate?">
</p>
11. **Delete the webapp Pod.**
Once deleted, wait for the pod to fully terminate.
**答**:
<p class="illustration">
<img src="https://i.imgur.com/8w7WwEd.png" alt="Delete the webapp Pod.">
</p>
12. **Create a new pod with the name redis and with the image redis123.**
Use a pod-definition YAML file. And yes the image name is wrong!
**答1**:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis123
```
<p class="illustration">
<img src="https://i.imgur.com/wVsZ5jQ.png" alt="Create a new pod with the name redis and with the image redis123.-1">
</p>
<br class="big">
**答2**:是不用準備 YAML 檔,直接建立物件。
<p class="illustration">
<img src="https://i.imgur.com/kNR7u1F.png" alt="Create a new pod with the name redis and with the image redis123.-2">
</p>
在執行時,可添加 `-o yaml` 將物件輸出成 YAML 檔 submit 出去。此時通常會搭配 `--dry-run=client` 使用,在 submit 時會先拿掉一些 default 參數。恩...如果沒加輸出的 YAML 檔會這麼長:
<p class="illustration">
<img src="https://i.imgur.com/O7cuqwG.png" alt="Create a new pod with the name redis and with the image redis123.-3">
</p>
13. **Now change the image on this pod to redis.**
Once done, the pod should be in a running state.
**答1**:直接修改 YAML 檔,再使用 apply 套用修改。
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
```
<p class="illustration">
<img src="https://i.imgur.com/8dksFo8.png" alt="Now change the image on this pod to redis.-1">
</p>
<br class="big">
**答2**:也可利用 `kubectl edit` 來修改 pod
<p class="illustration">
<img src="https://i.imgur.com/e37ElOd.png" alt="Now change the image on this pod to redis.-2">
</p>
### 6-6|Replication Controllers and ReplicaSets
之前說過 controllers 是 orchestration 背後的大腦,且依照不同的用途出現了不同的 controller。
這節介紹負責產生副本的 controller - **replication controller** 顧名思義就是負責**控制複製**,會依照所宣告的副本(replica)數目,==生成並維持相對應 pod 數量==。
<p class="illustration">
<img src="https://i.imgur.com/kmnrnBt.png" alt="Replica">
</p>
<br class="big">
而 **replica sets** 是在新版本的 K8S 中被建議用以取代 replication controller。不過在本質上兩者沒有的不同,只是 ==replica sets 多支援集合式的 selector==,且此**屬性(selector)是必備的**。
Replica sets 會透過 selector 來篩選匹配 `label` 的 pod 進行管理,這樣的機制會使 replica sets 的管轄範圍不限於 replica sets 中所宣告的 pod,而是擴及所有的 pod 無論是已建立或是未來建立的。
#### Advantages
基於 **備援性**、 **擴展性**、 **共享性**:
1. **High Availability**
如前面所說,replication controller 可以**生成並維持**指定數量的 pod。換句話說,如果有 pod 異常,會生成新的 pod 來替代;而若有多出來的 pod 也會自動回收。
因此一旦 pod 失效或故障,replication controller 會立即生成一個新的 pod 填補空缺,防止使用者無法尋訪應用,從而提供高可用性。這新生成的 pod 會依照 node 資源使用狀況,被分配到原 node 或新的 node 上。
<p class="illustration">
<img src="https://i.imgur.com/3q2qPC0.png" alt="High Availability">
High Availability(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
2. **Load Balancing & Scaling**
另一個使用 replication controller 的原因是為了建立多個 pod 來共享它們之間的負載。當使用者增加時,可以部署額外的 pod 來平衡兩個 pod 之間的負載,以擴展所提供的應用;反之,當使用者減少時,也可以適量減少 pod。
<p class="illustration">
<img src="https://i.imgur.com/0kPbrvX.png" alt="Load Balancing & Scaling">
Load Balancing & Scaling(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
#### RC & RS with YAML
這邊來看看如何撰寫 YAML。
1. **RC with YAML**
<p class="illustration">
<img src="https://i.imgur.com/keUY2Dm.png" alt="RC with YAML">
RC with YAML(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
如同前面所說,標準的 K8S 定義文件需包含 4 個必需根屬性:apiVersion、kind、metadata 和 spec。在撰寫 replication controller 的 YAML 時,需將 `kind` 設為 `ReplicationController` ,而對應的 `apiVersion` 則設為 `v1`。
與 pod 的 YAML 最大的差異在於 `spec`。在撰寫 replication controller 時,會在 `spec` 之下新增 `template` 的子屬性,用以記錄 replication controller 所要控制的 pod。基本上,在這邊撰寫 pod 與直接撰寫 pod YAML 無異,但唯一的不同之處在於無需宣告 `kind`,因為這邊都是 pod,而無需宣告 `kind`,也就無須宣告 `apiVersion`。
在 `spec` 中除了新增 `template` 的子屬性外,還會添加 `replicas` 屬性用以表明需要多少份副本。最後需要注意的是, `template` 和 `replicas` 是 `spec` 的直接子屬性,所以他們倆個的縮排必需一致。
2. **RS with YAML**
<p class="illustration">
<img src="https://i.imgur.com/YPXY28P.png" alt="RS with YAML">
RS with YAML(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
ReplicaSet 的撰寫與 ReplicationController 非常相似,但有個不同之處:
1. **`kind` 與 `apiVersion`**
這邊 `kind` 是要改成 `ReplicaSet`,重要的是 `ReplicaSet` 的 `apiVersion` 要改成 `apps/v1`。若持續使用 `v1`,則會得到下列錯誤訊息:
<p class="illustration">
<img src="https://i.imgur.com/nzPQTWj.png" alt="引用錯誤 apiVersion">
引用錯誤 apiVersion(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
2. **selector**
前面提過 replication controller 與 replica sets 兩者最關鍵的差別在於 **集合式的 selector** 的支援。因此必須 `spec` 加上 `selector`,常見情況下會搭配 `matchLabels` 使用。
### 6-7|Demo:ReplicaSets
這節的目的就是嘗試寫一份 YAML 並啟動。雖然在前面介紹了 rc 與 rs 兩種 YAML 寫法,但在實做上會建議採用較新的 ReplicaSets。
<br class="big">
基本重點在上一節已經介紹過了,所以這邊就直接上工了。不過撰寫時需要注意的是:
1. **apiVersion**:ReplicaSet 搭配的版號是 `apps/v1`。
2. **selector**:selector 的 label 需與 pod 的 label 可以相互匹配,不然 ReplicaSet 管不到這些 pod 呀 XDDD。不過 ReplicaSet 的 label 則無須配合,那是說明它本身的特性,而不是它的守備範圍。
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: cynthia-app-replicaset
labels:
app: cynthia-app
spec:
selector:
matchLabels:
tier: frontend
replicas: 3
template:
metadata:
name: cynthia-pod-2
labels:
app : nginx
tier: frontend
spec:
containers:
- name: nginx
image: nginx
```
<br class="big">
一旦準備好定義文件後,就可以透過指令 `create` 或 `apply` 來建立 pod:
```bash=
$ kubectl create -f replicasets.yaml
or
$ kubectl apply -f replicasets.yaml
pod/cynthia-pod-2 created
```
<br class="big">
完成 replicasets 建立後,可以查看其狀態:
```bash=
$ kubectl get replicaset
```
<p class="illustration">
<img src="https://i.imgur.com/PbTmFND.png" alt="檢查 replica set 狀態">
檢查 replica set 狀態
</p>
<br class="big">
觀察 pod 數目,可以注意到一旦 replicasets 建立後,就會生成並維持相對應 pod 數量:
```bash=
$ kubectl get pods
```
<p class="illustration">
<img src="https://i.imgur.com/FNWW34X.png" alt="觀察 pod 數目">
觀察 pod 數目
</p>
即便刪除一個 pod,會立即生成新的 pod 來替代:
<p class="illustration">
<img src="https://i.imgur.com/rpjVcQF.png" alt="刪除 pod 後生成新的 pod">
刪除 pod 後生成新的 pod
</p>
更進一步查詢 replica set 的狀況,可以看到持續維持 3 個 replicas,在 Event 的部分也可以看到有 4 個 create 紀錄,因為我們之前刪了一個 pod:
<p class="illustration">
<img src="https://i.imgur.com/QW9zTn0.png" alt="查看 replica set 詳細狀況">
查看 replica set 詳細狀況
</p>
若是試圖新增一個 pod,會注意到 pod 在生成過程一旦超過指定數量的 pod 就會中止:
<p class="illustration">
<img src="https://i.imgur.com/LyCCOox.png" alt="新增超過指定數量的 pod 會被中止">
新增超過指定數量的 pod 會被中止
</p>
<br class="big">
另外的情境是如何縮放 replicas?
1. **`edit`**
不過用這個方法是直接需改正在執行的暫存檔,因此需要非常小心,可能會出現出乎意外的副作用。
```bash=
$ kubectl edit replicaset cynthia-app-replicaset
```
<p class="illustration">
<img src="https://i.imgur.com/KTsNh3S.png" alt="暫存 YAML 檔">
暫存 YAML 檔
</p>
一旦將 replicas 增加到 4,會自動生成新的 pod,以彌補數量的不足之處:
<p class="illustration">
<img src="https://i.imgur.com/IsX032m.png" alt="增加 replicas 會新增pod以彌補數量的不足之處">
增加 replicas 會新增pod以彌補數量的不足之處
</p>
2. **`scale`**
另一種也是一次性的修改,但無須修改 YAML 檔:
```bash=
$ kubectl scale replicaset cynthia-app-replicaset --replicas=2
```
<p class="illustration">
<img src="https://i.imgur.com/l9v7mcV.png" alt="scale 縮放 replica set">
scale 縮放 replica set
</p>
3. **`apply`**
也可以透過修改 YAML 來更改配置,並使用 `apply` 去調整資源。
<p class="illustration">
<img src="https://i.imgur.com/KT5DA6F.png" alt="使用 apply 去調整資源">
使用 apply 去調整資源
</p>
### 6-8|編碼練習:ReplicaSet
1. **Let us start with ReplicaSets! Given a blank replicaset-definition.yml file. We are only getting started with it, so let's get it populated. Add all the root level properties to it.**
**Note**: Only add the properties, not any values yet.
**答:**
```yaml=
apiVersion:
kind:
metadata:
spec:
```
2. **Let us now add values for ReplicaSet. ReplicaSet is under apiVersion - apps/v1. Update values for apiVersion and kind**
```yaml=
apiVersion:
kind:
metadata:
spec:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
spec:
```
3. **Let us now add values for metadata. Name the ReplicaSet - frontend. And add labels app=>mywebsite and tier=> frontend.**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
spec:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
```
4. **Let us now get to the specification. The spec section for ReplicaSet has 3 fields: replicas, template and selector. Simply add these properties. Do not add any values yet.**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas:
selector:
template:
```
5. **Let us update the number of replicas to 4.**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas:
selector:
template:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
template:
```
6. **The template section expects a Pod definition. Luckily, we have the one we created in the previous set of exercises. Next to the replicaset-definition.yml you will now find the same pod-definition.yml file that you created before. Let us now copy the contents of the pod-definition.yml file, except for the apiVersion and kind and place it under the template section. Take extra care on moving the contents to the right so it falls under template.**
pod-definition.yml:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
template:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
template:
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
7. **Let us now link the pods to the ReplicaSet by updating selectors. Add a property "matchLabels" under selector and copy the labels defined in the pod-definition under it.**
**Note**: This may not work in play-with-k8s as it runs on 1.8 version of kubernetes. ReplicaSets moved to apps/v1 in 1.9 version of Kubernetes.
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
template:
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
**答:**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
matchLabels:
app: myapp
template:
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
### 6-9|Hands-On Labs:ReplicaSet
- [🚪 Replica Sets](https://kodekloud.com/topic/labs-replica-sets-2/)
<br class="big">
1. **How many PODs exist on the system?**
**答:** 0
<p class="illustration">
<img src="https://i.imgur.com/ZqIs642.png" alt="How many PODs exist on the system?">
</p>
2. **How many ReplicaSets exist on the system?**
**答:** 0
<p class="illustration">
<img src="https://i.imgur.com/bCfZomQ.png" alt="How many ReplicaSets exist on the system?">
</p>
3. **How about now? How many ReplicaSets do you see?**
**答:** 1
<p class="illustration">
<img src="https://i.imgur.com/lP4bbHw.png" alt="How many ReplicaSets do you see?">
</p>
4. **How many PODs are DESIRED in the new-replica-set?**
**答:** 4
<p class="illustration">
<img src="https://i.imgur.com/RGEcEPR.png" alt="How many PODs are DESIRED in the new-replica-set?">
</p>
5. **What is the image used to create the pods in the new-replica-set?**
**答:** busybox777
<p class="illustration">
<img src="https://i.imgur.com/UWBbpbw.png" alt="What is the image used to create the pods in the new-replica-set?">
</p>
6. **How many PODs are READY in the new-replica-set?**
**答:** 0
<p class="illustration">
<img src="https://i.imgur.com/c7f9MUp.png" alt="How many PODs are READY in the new-replica-set?">
</p>
7. **Why do you think the PODs are not ready?**
**答:** The image busybox777 doesn't exist
<p class="illustration">
<img src="https://i.imgur.com/BkrIZwk.png" alt="Why do you think the PODs are not ready?">
</p>
8. **Delete any one of the 4 PODs.**
<p class="illustration">
<img src="https://i.imgur.com/FnYwkEt.png" alt="Delete any one of the 4 PODs.">
</p>
9. **How many PODs exist now?**
**答:** 4
<p class="illustration">
<img src="https://i.imgur.com/FnYwkEt.png" alt="How many PODs exist now?">
</p>
10. **Why are there still 4 PODs, even after you deleted one?**
**答:** replica set ensures that desired number of pods always run
11. **Create a ReplicaSet using the replicaset-definition-1.yaml file located at /root/.
There is an issue with the file, so try to fix it.**
```yaml=
apiVersion: v1
kind: ReplicaSet
metadata:
name: replicaset-1
spec:
replicas: 2
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: nginx
image: nginx
```
**答:**
可以立刻發現是 `apiVersion` 填錯了,把它由 `v1` 改成 `apps/v1` 即可。
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-1
spec:
replicas: 2
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: nginx
image: nginx
```
<p class="illustration">
<img src="https://i.imgur.com/ra9vNby.png" alt="Create a ReplicaSet using the replicaset-definition-1.yaml file located at /root/.">
</p>
是說如果沒有注意到的話,直接 `create` 也會跑錯誤訊息給你:
<p class="illustration">
<img src="https://i.imgur.com/toR1JHT.png" alt="Create replicaset-definition-1.yaml error msg">
</p>
如果有注意到,但不確定應該換成哪個版號,則可以透過 `explain` 來取得相關資訊:
```bash=
$ kubectl explain replicaset
```
<p class="illustration">
<img src="https://i.imgur.com/8eTSMya.png" alt="kubectl explain">
</p>
12. **Fix the issue in the replicaset-definition-2.yaml file and create a ReplicaSet using it.
This file is located at /root/.**
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-2
spec:
replicas: 2
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: nginx
spec:
containers:
- name: nginx
image: nginx
```
**答:**
selector 的 label 跟 pod 的 label 無法相匹配。有兩個改法,一是改 selector 的 label,讓它與 pod 的 label 一致;另一種改法就是反過來了。
```yaml=
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-2
spec:
replicas: 2
selector:
matchLabels:
tier: nginx
template:
metadata:
labels:
tier: nginx
spec:
containers:
- name: nginx
image: nginx
```
<p class="illustration">
<img src="https://i.imgur.com/opF7X9q.png" alt="Fix the issue in the replicaset-definition-2.yaml file and create a ReplicaSet using it.">
</p>
一樣直接跑 `create` 也會丟錯誤訊息給你:
<p class="illustration">
<img src="https://i.imgur.com/MIRyoA1.png" alt="Create replicaset-definition-2.yaml error msg">
</p>
13. **Delete the two newly created ReplicaSets - replicaset-1 and replicaset-2**
<p class="illustration">
<img src="https://i.imgur.com/5uPpcwX.png" alt="Delete the two newly created ReplicaSets - replicaset-1 and replicaset-2">
</p>
對了,如果嫌 replicaSet 太長,可以直接使用縮寫 rs
```yaml=
$ kubectl get rs
```
14. **Fix the original replica set new-replica-set to use the correct busybox image.**
Either delete and recreate the ReplicaSet or Update the existing ReplicaSet and then delete all PODs, so new ones with the correct image will be created.
**答:**
```yaml=
$ kubectl edit replicaset new-replica-set
```
將 container 的 image 修改由 busybox777 成 busybox
<p class="illustration">
<img src="https://i.imgur.com/07HAS2p.png" alt="kubectl edit replicaset new-replica-set">
</p>
然後刪掉就有的 pod,讓 replica set 重起 pod 以套用新的修改。
<p class="illustration">
<img src="https://i.imgur.com/OmCCfHH.png" alt="kubectl edit replicaset new-replica-set">
</p>
15. **Scale the ReplicaSet to 5 PODs.**
Use kubectl scale command or edit the replicaset using kubectl edit replicaset.
<p class="illustration">
<img src="https://i.imgur.com/MrxGRZl.png" alt="Scale the ReplicaSet to 5 PODs.">
</p>
16. **Now scale the ReplicaSet down to 2 PODs.**
Use the kubectl scale command or edit the replicaset using kubectl edit replicaset.
<p class="illustration">
<img src="https://i.imgur.com/3NjCUdF.png" alt="Now scale the ReplicaSet down to 2 PODs.">
</p>
### 6-10|Deployments
> a Deployment is a higher-level concept that manages ReplicaSets and provides declarative updates to Pods along with a lot of other useful features.
由[官網](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/#when-to-use-a-replicaset)的敘述可得知,K8S 建議使用 deployments 來部署 pod 與 replicaset,它可使用聲明式的方式為 pod 與 replicaset 提供設定與更新。
<p class="illustration">
<img src="https://i.imgur.com/Dxw6RxA.png" alt="Deployment">
Deployment(圖片來源: <a href="https://medium.com/aspnetrun/deploying-microservices-on-kubernetes-35296d369fdb">aspnetrun|Medium</a>)
</p>
#### Pain points
在未使用 K8S 前,若要部署應用,可能會遭遇以下痛點:
1. **需手動多個 instance**
服務可能會需要多個元件 instance,或是基於負載會啟動多個 instance,這些都需一一手動啟動。
2. **升級麻煩**
當有新的 image 時,這些 instance 一一升級,費時且費力。此外,升級時為達到無停機服務遷移或為不影響使用者的使用,必須逐個升級 instance,這會需要花費更多的心力去管理。是說,這樣的更新策略有個專有名詞稱之為**滾動更新(RollingUpdate)**,這在之後的章節有詳細說明。
3. **撤消更新困難**
若某個升級出現意外錯誤,要撤消更新並 Rollback 到先前版本,得把升級動作反向執行,這過程非常麻煩且容易錯誤。
上述這些痛點正是 Deployment 特性。
#### Deployments with YAML
<p class="illustration">
<img src="https://i.imgur.com/cb5hlUD.png" alt="Deployments with YAML">
Deployments with YAML(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
基本上 `Deployment` 與 `ReplicaSet` 的 YAML 基本一致,只需要把 `kind` 那攔改成 `Deployment` 即可。
### 6-11|Demo:Deployments
這邊一樣嘗試寫 YAML 並啟動。我直接複製 ReplicaSet 的 YAML 檔,並將 `kind` 改成 `Deployment` 。
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: cynthia-app-deployment
labels:
app: cynthia-app
spec:
selector:
matchLabels:
tier: frontend
replicas: 3
template:
metadata:
name: cynthia-pod-2
labels:
app : nginx
tier: frontend
spec:
containers:
- name: nginx
image: nginx
```
<br class="big">
一旦準備好定義文件後,就可以透過指令 `create` 或 `apply` 來建立 deployment:
<p class="illustration">
<img src="https://i.imgur.com/aDOIFDx.png" alt="create deployment">
</p>
<br class="big">
完成 deployment 建立後,可以查看其狀態:
<p class="illustration">
<img src="https://i.imgur.com/Ml5PHiy.png" alt="get deployment">
</p>
<p class="illustration">
<img src="https://i.imgur.com/0sevHud.png" alt="get replicaset">
</p>
<p class="illustration">
<img src="https://i.imgur.com/oELfxkA.png" alt="get pods">
</p>
<br class="big">
如果一一查看各狀態有點麻煩可以直接用:
```bash=
$ kubectl get all
```
<p class="illustration">
<img src="https://i.imgur.com/Gz6yrVo.png" alt="get all">
</p>
### 6-12|編碼練習:Deployments
1. **Let us start with Deployments! Given a deployment-definition.yml file. We are only getting started with it, so let's get it populated. Add all the root level properties to it. Note: Only add the properties, not any values yet.**
**答:**
```yaml=
apiVersion:
kind:
metadata:
spec:
```
2. **Let us now add values for Deployment. Deployment is under apiVersion apps/v1. Update values for apiVersion and kind.**
```yaml=
apiVersion:
kind:
metadata:
spec:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
spec:
```
3. **Let us now add values for metadata. Name the Deployment frontend. And add labels app=>mywebsite and tier=> frontend.**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
spec:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
```
4. **Let us now get to the specification. The spec section for Deployment has 3 fields: replicas, template and selector. Simply add these properties. Do not add any values.**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas:
selector:
template:
```
5. **Let us update the number of replicas to 4.**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas:
selector:
template:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
template:
```
6. **The template section expects a Pod definition. Luckily, we have the one we created in the previous set of exercises. Next to the deployment-definition.yml you will now find the same pod-definition.yml file that you created before. Let us now copy the contents of the pod-definition.yml file, except for the apiVersion and kind and place it under the template section. Take extra care on moving the contents to the right so it falls under template**
pod-definition.yml:
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
template:
```
**答:**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
template:
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
7. **Let us now link the pods to the Deployment by updating selectors. Add a property "matchLabels" under selector and copy the labels defined in the pod-definition under it.**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
template:
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
**答:**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: mywebsite
tier: frontend
spec:
replicas: 4
selector:
matchLabels:
app: myapp
template:
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
```
### 6-13|Hands-On Labs:Deployments
- [🚪 Deployments](https://kodekloud.com/topic/labs-deployments-2/)
<br class="big">
1. **How many PODs exist on the system?**
**答:** 0
<p class="illustration">
<img src="https://i.imgur.com/zYtD0X8.png" alt="How many PODs exist on the system?">
</p>
2. **How many ReplicaSets exist on the system?**
**答:** 0
<p class="illustration">
<img src="https://i.imgur.com/X52bNJt.png" alt="How many ReplicaSets exist on the system?">
</p>
3. **How many Deployments exist on the system?**
**答:** 0
<p class="illustration">
<img src="https://i.imgur.com/5S4UbXN.png" alt="How many Deployments exist on the system?">
</p>
4. **How many Deployments exist on the system now?**
**答:** 1
<p class="illustration">
<img src="https://i.imgur.com/azDWvvM.png" alt="How many Deployments exist on the system now?">
</p>
5. **How many ReplicaSets exist on the system now?**
**答:** 1
<p class="illustration">
<img src="https://i.imgur.com/ArkNJn6.png" alt="How many ReplicaSets exist on the system now?">
</p>
6. **How many PODs exist on the system now?**
**答:** 4
<p class="illustration">
<img src="https://i.imgur.com/YJ7W6Sq.png" alt="How many PODs exist on the system now?">
</p>
7. **Out of all the existing PODs, how many are ready?**
**答:** 0
<p class="illustration">
<img src="https://i.imgur.com/D0Pxcaf.png" alt="Out of all the existing PODs, how many are ready?">
</p>
8. **What is the image used to create the pods in the new deployment?**
**答:** busybox888
<p class="illustration">
<img src="https://i.imgur.com/Ik4w03z.png" alt="What is the image used to create the pods in the new deployment?">
</p>
9. **Why do you think the deployment is not ready?**
**答:** the image busybox888 doesn't exist
<p class="illustration">
<img src="https://i.imgur.com/r1DQHxm.png" alt="Why do you think the deployment is not ready?">
</p>
10. **Create a new Deployment using the deployment-definition-1.yaml file located at /root/.
There is an issue with the file, so try to fix it.**
```yaml=
apiVersion: apps/v1
kind: deployment
metadata:
name: deployment-1
spec:
replicas: 2
selector:
matchLabels:
name: busybox-pod
template:
metadata:
labels:
name: busybox-pod
spec:
containers:
- name: busybox-container
image: busybox888
command:
- sh
- "-c"
- echo Hello Kubernetes! && sleep 3600
```
**答:**
直接跑 create 可以看到錯誤訊息,看起來如果不是 `apiVersion` 有誤,就是 `kind` 出差錯了。
<p class="illustration">
<img src="https://i.imgur.com/dvkwjmd.png" alt="Create a new Deployment using the deployment-definition-1.yaml">
</p>
打開 YAML 可以看到是 `kind` 寫錯了,把它改成 `deployment`
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-1
spec:
replicas: 2
selector:
matchLabels:
name: busybox-pod
template:
metadata:
labels:
name: busybox-pod
spec:
containers:
- name: busybox-container
image: busybox888
command:
- sh
- "-c"
- echo Hello Kubernetes! && sleep 3600
```
再重新執行一次 `create` ,就能看到 deplyment 被執行了:
<p class="illustration">
<img src="https://i.imgur.com/lo2KudY.png" alt="create">
</p>
11. **Create a new Deployment with the below attributes using your own deployment definition file.**
- Name: httpd-frontend;
- Replicas: 3;
- Image: httpd:2.4-alpine
**答**:
按照上面的條件寫一份 YAML,因為沒給 label,所以我直接把 name 當 label 用了 XDDD
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-frontend
spec:
replicas: 3
selector:
matchLabels:
name: httpd-frontend
template:
metadata:
labels:
name: httpd-frontend
spec:
containers:
- name: httpd-frontend
image: httpd:2.4-alpine
```
然後 `create` 就行了,你要 `apply` 也行:
<p class="illustration">
<img src="https://i.imgur.com/2Fil98M.png" alt="Create a new Deployment with the below attributes using your own deployment definition file.">
</p>
解答則是沒寫 YAML 全用指令代入:
<p class="illustration">
<img src="https://i.imgur.com/XvyWTMM.png" alt="Create a new Deployment with the below attributes using your own deployment definition file.">
</p>
### 6-14|Update and Rollback
<p class="illustration">
<img src="https://i.imgur.com/pPyRp2C.png" alt=" Rolling and Rollback Deployments work">
Rolling and Rollback Deployments work(圖片來源: <a href="https://yankeexe.medium.com/how-rolling-and-rollback-deployments-work-in-kubernetes-8db4c4dce599">Yankee Maharjan|Medium</a>)
</p>
這節還是跟 deployment 有關,不過這節會更詳細說明滾動更新(RollingUpdate)與回復舊版(RollBack)的功能。阿對,我對筆記內容做了調整,跟指令相關的部份我全部放到下一節跟 Demo 一併整理,這一節我只留下理論的部份。
#### Deployment Update Strategy
前一節在提及 pod 的更新,其實有隱約提過更新策略,這邊做更進一步的說明。在 K8S 中有 2 種部署策略:
1. **Recreate**
這策略是會先銷毀所有的 instance,再建立新版的 instance。但這部署策略的缺點是顯而易見的,==在新舊版本交替間使用者是無法尋訪的==。
<p class="illustration">
<img src="https://i.imgur.com/5UEsNkY.png" alt="Recreate">
Recreate(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
2. **Rolling Update**
這種策略與 recreate 不同的是,它並不會一次性銷毀全部的 instance,而是用新版本一個接一個地替換運行中舊版。這樣的更新可以達到==無停機服務遷移==的目的,但這樣的個更新方式有可能會同時出現新舊內容。
在 K8S 中建置 deployment 時,若沒有指定部署策略**預設會採用 RollingUpdate**。在此基礎上,還衍生出 Ramped slow rollout、Best-effort controlled rollout 幾種變形,恩...也不算變形,嚴格來說還它們也是 Rolling Update 策略,就是針對 maxSurge 與 maxUnavailable 兩個參數的調整,用以控制更新與系統的穩定度,兩個參數我們後面再提。
<p class="illustration">
<img src="https://i.imgur.com/au8q8dY.png" alt="Rolling Update">
Rolling Update(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
<br class="big">
假設目前存在一個 deployment,它會建立一 replica set,創建滿足 replica 數量所需的 pod 數量。當試圖升級應用時,K8S 會建立一個新的 replica set,並按照 RollingUpdate 的策略刪除舊 replica set 中的 pod。
<p class="illustration">
<img src="https://i.imgur.com/8aneM3g.png" alt="Rolling Update 實況">
Rolling Update 實況(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
如果用 `kubectl get replicasets` 觀看 replica sets,可以看到僅剩 0 個 pod 的舊 replica set 和具有 5 個 pod 的新 replica set。
<p class="illustration">
<img src="https://i.imgur.com/bjr7kKV.png" alt="Rolling Update 實況">
Rolling Update 實況(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
說到部署策略,除了 Recreate 跟 RollingUpdate 外,我在查資料時還有看到 Blue-Green Deployment(Red-Black Deployment)、 Canary deployment、 Shadow Deployment 跟 A/B Testing...等部署策略。但那些策略看起來更像 DevOps 的部署,且也不是撰寫 YAML 時會直接涉及的策略,所以這邊就先跳過吧。
如果對這幾種部署策略有興趣,可以看看這兩篇文章:
- [〈5 Kubernetes Deployment Strategies: Roll Out Like the Pros|pot〉](https://spot.io/resources/kubernetes-autoscaling/5-kubernetes-deployment-strategies-roll-out-like-the-pros/)
- [〈Top 6 Kubernetes Deployment Strategies and How to Choose|codefresh〉](https://codefresh.io/learn/software-deployment/top-6-kubernetes-deployment-strategies-and-how-to-choose/)
#### Revision and Rollback
在討論 rollback 前,必須先到知道 K8S 也是有版本管控的,不過這邊不是稱為 commit 而是 revision。每次 create 新的 deployment 或是升級現有 deployment 時都會觸發記錄,當然也可以主動去記錄。
就是有這些紀錄的存在,才有可能去做 rollback。至於如何進行 rollback,這就是取決於你的部署策略是 Recreate 還是 Rolling Update 了。
<p class="illustration">
<img src="https://i.imgur.com/iR9zje7.png" alt="Revision">
Revision(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
<br class="big">
若要回復舊版,則會刪除新的 replica set,並回覆舊的 replica set 中。
<p class="illustration">
<img src="https://i.imgur.com/pkn29pd.png" alt="Rollback 實況 1">
Rollback 實況 1(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
如果用 `kubectl get replicasets` 指令比較 rollback 前後的 replica sets 狀況,可以看到新舊 replica set 的 pod 的變化。
<p class="illustration">
<img src="https://i.imgur.com/DNB8mVJ.png" alt="Rollback 實況 2">
Rollback 實況 2(圖片來源: <a href="https://www.udemy.com/course/learn-kubernetes/">課程截圖</a>)
</p>
#### Update Strategy with YAML
<p class="illustration">
<img src="https://i.imgur.com/aXZBq67.png" alt="Revision and Rollback">
Revision and Rollback
</p>
YAML 的撰寫主要延續自前面的 `Deployment`,但為因應部署策略的調整,需要在 `spec` 下添加 `strategy` 的子屬性。在 `strategy` 下最主要的是 **`type`** 屬性,這個屬性就是決定要採用 `Recreate` 或是 `RollingUpdate`。
若是最終決定採用 `RollingUpdate` 策略,在 `strategy` 下就會多一個 `rollingUpdate` 的子屬性。在這個子屬性中所要設定就是前面所提及 `maxSurge` 與 `maxUnavailable`:
- **`maxSurge`**
預設值為 25%。這參數是指==允許超過 replicas 的最大比例==。可將此數設定為整數(例如:5),或是指定為所需 pod 總數的百分比(例如:10% 但結果會四捨五入向上取整)。
舉例來說,如果該值設定為 2,這表示會建立 2 個新 pod 後刪除舊的 pod。若假設 replicas 為 3,整個升級過程中最多會有 3+2 個 pod。
- **`maxUnavailable`**
預設值為 25%。該值表示在升級過程中,==最多可以有幾個 pod 無法服務==。跟 maxSurge 一樣,此數可設定為整數或百分比。
需要注意的是,根據[文件](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-unavailable)說明,==此值與 maxSurge 不可同時為 0;換句話說,當 maxSurge 不為零時,此值才可為 0==。會特別這句話是因為我在查資料的時候看到一句話:「maxSurge 不為 0、maxUnavailable 亦不得為 0」,我就在想有什麼情況這兩個值會同時為 0,同時為 0 的話應該更新不動?看來應該是筆者筆誤了?
### 6-15|Demo:Update and Rollback
開始時先建立一個 deployment:
<p class="illustration">
<img src="https://i.imgur.com/W3XKxzH.png" alt="create deployment">
</p>
此時可以用 rollout 指令查詢部署或升級狀況:
```bash=
$ kubectl rollout status deployment <deployment>
```
<p class="illustration">
<img src="https://i.imgur.com/MoN9e0F.png" alt="kubectl rollout status">
</p>
每次 create 新的 deployment 或是升級現有 deployment 時都會觸發記錄,若想查看紀錄可以透過:
```bash=
$ kubectl rollout history
```
<p class="illustration">
<img src="https://i.imgur.com/bnRWOwX.png" alt="kubectl rollout history">
</p>
不過這樣的紀錄就像是沒有寫 commit message 的 commit,想知道究竟是記錄了什麼非常考驗記憶力,所以通常在下指令時會搭配 `--record` 使用。如此一來 history 的 change-cause 就會記錄下產生變動的指令:
<p class="illustration">
<img src="https://i.imgur.com/nd8YqSq.png" alt="--record">
</p>
<br class="big">
完成部署後,可以來嘗試升級。升級的方式有幾種:
1. **如果想直接使用指令更改單一狀態**
可以用 `kubectl scale`/`kubectl set image` ...等。
2. **如果修改參數較多可以直接修改 YAML**
YAML 的修改有可以分成直接修改執行中暫存的 `kubectl edit`,或者直接修改最初配置的 `kubectl apply`/`kubectl replace`。不過直接修改最初配置的文件,可能會導致下次使用同一文件所產生的 deployment 不合最初預期,需要注意。
這邊使用 `kubectl set image` 來更新 images,並使用 `kubectl rollout status` 來觀察資源配置的狀況:
<p class="illustration">
<img src="https://i.imgur.com/Asbwykl.png" alt="set image">
</p>
如果出現任何問題想暫停更新可以使用 `kubectl rollout pause`:
```bash=
# 暫停滾動升級
$ kubectl rollout pause deployment <deployment>
# 繼續滾動升級
$ kubectl rollout resume deployment <deployment>
```
<br class="big">
關於 `Recreate` 或是 `RollingUpdate` 的差別在 describe 的 event 中也可見端倪。在使用 `Recreate` 策略時,可以看到舊的 replica set 首先縮小到 0,新的 replica set 再擴大到 5;但當使用 `RollingUpdate` 策略時,則是舊的 replica set 逐漸縮小同時新的 replica set 逐漸擴大。
<p class="illustration">
<img src="https://i.imgur.com/XlYjbIQ.png" alt="`Recreate` 或是 `RollingUpdate` 的差別">
</p>
<br class="big">
嘗試幾次升級後,可以看到歷史紀錄中多了幾筆 revision,若想倒回去的話,則是使用:
```bash=
$ kubectl rollout undo deployment <deployment>
```
<p class="illustration">
<img src="https://i.imgur.com/twhRHB9.png" alt="rollout undo">
</p>
不過跟我想像的有點不太一樣的是,它 undo 後不太像是 git,會將最後的 commit 給移除,而是把原本的 revision 2 改成 revision 4 並移到最上層:
<p class="illustration">
<img src="https://i.imgur.com/eGdxnha.png" alt="`Recreate` 或是 `RollingUpdate` 的差別">
</p>
<br class="big">
最後貼張指令表:
<p class="illustration">
<img src="https://i.imgur.com/5gw4SCD.png" alt="指令表">
</p>
### 6-16|Hands-On Labs:Update and Rollback
- [🚪 Practice Test Rolling Updates and Rollbacks](https://kodekloud.com/topic/labs-practice-test-rolling-updates-and-rollbacks/?utm_source=udemy&utm_medium=labs&utm_campaign=kubernetes)
<br class="big">
1. **We have deployed a simple web application. Inspect the PODs and the Services. Wait for the application to fully deploy and view the application using the link called Webapp Portal above your terminal.**
它只要我們檢查,也沒要我們做啥,所以我就用了 `get all`:
<p class="illustration">
<img src="https://i.imgur.com/g1bTOC8.png" alt="We have deployed a simple web application.">
</p>
順便依照要求看看 Portal 長怎樣:
<p class="illustration">
<img src="https://i.imgur.com/rFpoqll.png" alt="Webapp Portal">
</p>
2. **What is the current color of the web application? Access the Webapp Portal.**
**答:** blue
3. **Run the script named curl-test.sh to send multiple requests to test the web application. Take a note of the output. Execute the script at /root/curl-test.sh.**
就照要求跑個 script,看看結果:
<p class="illustration">
<img src="https://i.imgur.com/LEuHNX1.png" alt="Run the script named curl-test.sh">
</p>
4. **Inspect the deployment and identify the number of PODs deployed by it.**
**答:** 4
<p class="illustration">
<img src="https://i.imgur.com/mHW3cni.png" alt="Inspect the deployment and identify the number of PODs deployed by it">
</p>
5. **What container image is used to deploy the applications?**
**答:** kodekloud/webapp-color:v1
<p class="illustration">
<img src="https://i.imgur.com/gmBXiMg.png" alt="What container image is used to deploy the applications">
</p>
6. **Inspect the deployment and identify the current strategy**
**答:** RollingUpdate
<p class="illustration">
<img src="https://i.imgur.com/04z3cwf.png" alt="Inspect the deployment and identify the current strategy">
</p>
7. **If you were to upgrade the application now what would happen?**
**答:** Pods are upgraded few at a time
8. **Let us try that. Upgrade the application by setting the image on the deployment to kodekloud/webapp-color:v2. Do not delete and re-create the deployment. Only set the new image name for the existing deployment.**
透過 `edit` 直接更改 image:
<p class="illustration">
<img src="https://i.imgur.com/uKkjYdG.png" alt="Upgrade the application by setting the image">
</p>
改完後可以觀察下升級結果,不過我指令下晚了已經更新完了 XDDD
<p class="illustration">
<img src="https://i.imgur.com/jV02cgR.png" alt="Upgrade the application by setting the image">
</p>
不過可以直接從 Webapp Portal 觀看更新結果,他的底色已經從藍色變成綠色了:
<p class="illustration">
<img src="https://i.imgur.com/yweYnrN.png" alt="Webapp Portal">
</p>
9. **Run the script curl-test.sh again. Notice the requests now hit both the old and newer versions. However none of them fail. Execute the script at /root/curl-test.sh.**
<p class="illustration">
<img src="https://i.imgur.com/LV1u61D.png" alt="Run the script curl-test.sh again">
</p>
10. **Up to how many PODs can be down for upgrade at a time. Consider the current strategy settings and number of PODs - 4.**
**答:** 1
這邊 max unavailable 為 25%,$4*25\%=1$
<p class="illustration">
<img src="https://i.imgur.com/604lbAO.png" alt="Run the script curl-test.sh again">
</p>
11. **Change the deployment strategy to Recreate. Delete and re-create the deployment if necessary. Only update the strategy type for the existing deployment.**
因為我沒找到現成的 YAML 檔,所以先用 get 匯出 YAML 檔,再刪除 deployment 後重建。
<p class="illustration">
<img src="https://i.imgur.com/vmb9HRJ.png" alt="Run the script curl-test.sh again">
</p>
在改 YAML 檔時,除了把 type 改成 Recreate 外,別忘了把 rollingUpdate 給移除:
<p class="illustration">
<img src="https://i.imgur.com/4nRGXVK.png" alt="Run the script curl-test.sh again">
</p>
12. **Upgrade the application by setting the image on the deployment to kodekloud/webapp-color:v3. Do not delete and re-create the deployment. Only set the new image name for the existing deployment.**
這邊其實跟前面的操作相仿:
<p class="illustration">
<img src="https://i.imgur.com/tn7bMcE.png" alt="Upgrade the application">
</p>
13. **Run the script curl-test.sh again. Notice the failures. Wait for the new application to be ready. Notice that the requests now do not hit both the versions. Execute the script at /root/curl-test.sh.**
截錯圖了 XDD 不過我有記得截圖 Portal,script 表示他是紅色的,但我怎麼看都是橘色的?
<p class="illustration">
<img src="https://i.imgur.com/JrIGWk5.png" alt="Run the script curl-test.sh again.">
</p>
## 其他連結
1. 課程內容:[Kubernetes for the Absolute Beginners - Hands-on](https://www.udemy.com/course/learn-kubernetes/)
2. 目錄: [【K8S Beginners 筆記】目錄](https://hackmd.io/@CynthiaChuang/Kubernetes-for-the-Absolute-Beginners-Contents)
## 參考資料
1. CharyGao (2021-07-30)。[XML 與 JSON 優劣對比,TOML、CSON、YAML](https://www.twblogs.net/a/610398bf9eb5e3210c708c18)。檢自 台部落 (2022-11-11)。
2. 天府云创 (2021-04-13)。[Kubernetes之YAML语法](https://blog.csdn.net/enweitech/article/details/115674083)。檢自 天府云创的博客|CSDN (2022-11-11)。
3. FoxuTech (2022-04-13)。[Kubectl apply vs Kubectl create.](https://foxutech.medium.com/kubectl-apply-vs-kubectl-create-8d946ed603a1) 。檢自 Medium (2022-11-16)。
4. Will 保哥 (2022-10-24)。[Kubernetes 101:釐清 kubectl create 與 kubectl apply 的差異](https://blog.miniasp.com/post/2022/10/24/Kubernetes-101-diff-between-kubectl-create-and-kubectl-apply) 。檢自 The Will Will Web (2022-11-17)。
5. Bob Reselman (2021-07-27)。[Kubectl apply vs. create: What's the difference?](https://www.theserverside.com/answer/Kubectl-apply-vs-create-Whats-the-difference)。檢自 TheServerSide (2022-11-16)。
6. 大鹏blog (2020-02-19)。[kubernetes: kubectl create与kubectl apply的区别](https://blog.csdn.net/textdemo123/article/details/104400985)。檢自 大鹏blog的博客|CSDN (2022-11-16)。
7. (2022-11-21)。[ReplicationController 和 ReplicaSet](https://doc.cncf.vip/kubernetes-handbook/gai-nian-yu-yuan-li/controllers/replicaset)。檢自 kubernetes中文手册 (2022-11-21)。
8. godleon (2022-08-31)。[[Kubernetes] Deployment Overview](https://godleon.github.io/blog/Kubernetes/k8s-Deployment-Overview/)。檢自 小信豬的原始部落 (2022-11-23)。
9. Andy Chen (2020-02-12)。[Kubernetes 那些事 — Deployment 與 ReplicaSet(一)](https://medium.com/andy-blog/kubernetes-那些事-deployment-與-replicaset-一-406234a63d43) 。檢自 Andy的技術分享blog|Medium (2022-11-23)。
10. Akhil Chawla (2021-09-02)。[Deployment Strategies In Kubernetes](https://auth0.com/blog/deployment-strategies-in-kubernetes/)。檢自 auth0 (2022-11-24)。
11. [Top 6 Kubernetes Deployment Strategies and How to Choose](https://codefresh.io/learn/software-deployment/top-6-kubernetes-deployment-strategies-and-how-to-choose/)。檢自 codefresh (2022-11-24)。
12. [5 Kubernetes Deployment Strategies: Roll Out Like the Pros](https://spot.io/resources/kubernetes-autoscaling/5-kubernetes-deployment-strategies-roll-out-like-the-pros/)。檢自 Spot by NetApp (2022-11-24)。
13. Kevin Yang (2021-07-16)。[[K8s] 開始學習 Kubernetes - Deployment Strategies](https://blog.kevinyang.net/2021/07/16/k8s-note-002/)。檢自 CK's Notepad (2022-11-24)。
14. sixinshuier (2020-08-26)。[文kubectl create / replace 与kubectl apply 的区别章文稱](https://www.cnblogs.com/shix0909/p/13566148.html)。檢自 sixinshuier|博客园 (2022-11-25)。
## 更新紀錄
:::spoiler 最後更新日期:2022-12-30
- 2022-12-30 發布
- 2022-11-25 完稿
- 2022-11-04 起稿
:::
{%hackmd @CynthiaChuang/Github-Page-Footer %}