owned this note
owned this note
Published
Linked with GitHub
# 鐵人賽 10篇
## DAY11 Rancher 基本介紹
Rancher 唯一套管理Kubernetes 叢集的一套軟體,其除了能夠在各大作業系統如:Windows,Linux 和 macos 上做佈建之外,也支援已有容器或叢集部屬經驗的人透過Docker或Kubernetes進行部屬

[Rancher官方網站](https://rancher.com/)
使用者透過Rancher 可遠端監控叢集的資源使用,提供WEB UI進行服務與其他套件的安裝,也可協助使用者處理在Kubernetes的網路問題。
而Rancher在監控時會起大量的服務和Api-server,若配備不足則會導致系統死當,因此官方有提供建議的配備

以下為作本人所使用的環境配備:
系統/套件 | 版本 |
--------------|:-----:|
ubuntu | 20.04 |
docker | 19.03.xx |
Rancher | 2.6.3 |
CPU | 4 cores
memory | 8GB
下次則會介紹Rancher的安裝與import當前主機的K8s進入Rancher進行管理
## DAY12 Rancher安裝與import(1)
Rancher本身的WebUI透過Docker的安裝非常簡單,只要下docker run 後就能直接安裝,而安裝的script有附上含docker的安裝,若已有安裝docker的話則只要使用最後一行docker run即可
```bash=
sudo apt update
sudo apt install -y curl apt-transport-https ca-certificates software-properties-common net-tools htop
# Grab debs from Docker
curl -Ol https://download.docker.com/linux/ubuntu/dists/focal/pool/stable/amd64/containerd.io_1.4.9-1_amd64.deb
curl -Ol https://download.docker.com/linux/ubuntu/dists/focal/pool/stable/amd64/docker-ce_19.03.10~3-0~ubuntu-focal_amd64.deb
curl -Ol https://download.docker.com/linux/ubuntu/dists/focal/pool/stable/amd64/docker-ce-cli_19.03.10~3-0~ubuntu-focal_amd64.deb
# Install Docker
sudo dpkg -i *.deb
rm containerd.io_1.4.9-1_amd64.deb docker-ce_19.03.10~3-0~ubuntu-focal_amd64.deb docker-ce-cli_19.03.10~3-0~ubuntu-focal_amd64.deb
sudo usermod -aG docker $USER
sudo systemctl start docker
sudo systemctl enable docker
sudo docker version
systemctl status --no-pager docker
sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 --privileged rancher/rancher:v2.6.3
```
等到Rancher Dashboard成功啟動後,在網頁上則會看到這個畫面

因剛進去 rancher Dashboard的時候 Rancher會先幫妳設一個密碼 輸入預設密碼後才能重新設定密碼


設定密碼的畫面
第一個選項是使用預設的密碼(由Rancher隨機產生)
第二個選項是使用自己的密碼(限定要12個字元以上)
然後底下兩個使用規範記得要勾選
進到主畫面後即代表設定完成

## DAY13 安裝kubernetes 與import existing node
為了import自己機器上的k8s叢集,因此我們需要先安裝kubernetes在我們的主機上
```bash=
# 添加K8s的Repo
sudo su -c "curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -"
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
sudo apt update
# 指定版本並安裝k8s套件
version=1.18.6-00
echo $version
apt-cache show kubectl | grep "Version: $version"
sudo apt install -y kubelet=$version kubectl=$version kubeadm=$version
sudo apt-mark hold kubelet kubeadm kubectl
# Essential Tweaks
cat << EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
sudo free -m
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
# Init cluster
## For Master Node
sudo kubeadm init --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16 --v=6
### Copy Config
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
### Flannel CNI
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
### Waiting until Ready
kubectl cluster-info
#watch -n 1 kubectl get nodes
### Taint(if needed)
kubectl taint nodes --all node-role.kubernetes.io/master-
```
Rancher 有提供兩種方式進行import K8s 一為import機器上現有的k8s 二為透過RKE (Rancher Kubernetes Engine)透過Docker使用RKE2進行k8s安裝與import 而因官方建議RKE要在不同機器上安裝,因此這邊使用import已經安裝好的K8s
進到home目錄後下方有一個 impot Exsiting

進去之後選generic



名稱設定好之後 就按照上面的指示 選擇中間的script並到想要import的主機上貼上,之後Rancher會在主機上起一個Rancher Agent並啟動API server cattle system等服務進行監控

看到Active就是deploy好了
**在安裝時可能遇到的問題**
有些人可能沒有多餘的主機可進行部屬因此使用VM進行安裝與測試,若在import的時候deploy時一直卡在waiting API server,可先嘗試看看F5後網頁有沒有卡住 如果出現拒絕連線先看看VM或是你在用的機器CPU與記憶體使用量有沒有過高(<80%是最好的) 如果有就開多一點CPU (Rancher是建議 4核8G 有些服務至少要5核以上)
再重新開機看是否能正常運行
## DAY14 透過Rancher進行服務部屬
Rancher 有提供介面操作部屬與透過API進行部屬等兩種方式進行操作
要進行部屬 首先要先進到自己的cluster 然後左邊選擇workload的deployment

進來後選Create 會進到設定


按下Create之後 就可以看到rancher正在部屬剛剛設定的nginx

看到他是Active的狀態後到 Pods

可以看到image是nginx的Pod 進去點Show Annotations就可以看到Pod的IP

在瀏覽器打Pod的IP就能看到Nginx的畫面

同樣的部屬其他image也是同樣方式(這邊以grafana6.7.3做部屬)
跟nginx不同的是這邊有幫Grafana額外設定port

create完成後一樣可以從pod那邊看到IP
從網頁上也能看到我們Grafana的畫面

## DAY15 透過rancher API部屬服務
Rancher 本身有提供本機的API服務 因Rancher2.0後無官方文件所以這邊用rancher網頁做介紹
首先要先去取得API token 首先先到右上角的帳號設定打開API key的頁面

然後按Create API key 進入設定頁面 並選取API KEY可以存取的範圍(如果沒有特別限定只能存取的cluster就不用設定)與期限

按create後 會得到 API token API key 與 Bearer token

**這邊要注意API KEY只能在現在看到,如果按下done之後沒有儲存就只能重創一個新的**
取得API key先測試登入 這邊使用Bearer token進行驗證

確認可以登入後就先去取得你的cluster與 system project id
cluster id 可以從網址上看到

project id 則可以從與相關project有關的namespace上看到


取得System project id 後就可以進行Deploy 測試
首先上面部屬時可以看到我們需要填那些欄位 事實是打API時要帶的data也可用同樣方式查看

從上方的圖可以看出 我們主要需要談的欄位有namespace name image 跟 imagePullPolicy 還有container name
``` python=
import requests
#ACCESS_KEY = 'token-fbn4t'
#ACCESS_SECRET = 'dt7bmbkwwcdmfpvjmmwg9pkdlgd4zttr9t7ts4tnts4cfdnvhzdbzh'
headers = {"Authorization": "Bearer token-7gqj9:4jp2r7m78b5cxq7wr4krfthr8tvvsjpzw6x9v5jgvfxzflbs8gcflf"}
config = {
"containers": [{
"imagePullPolicy": "IfNotPresent",
"image": "nginx:latest",
"name": "nginx-test"
}],
"namespaceId": "test-namespace",
"name": "nginx-test"
}
response=requests.post('https://(rancher ip)/v3/projects/(cluster id:project id)/workloads', json=config, headers=headers,verify=False)
print(response.status_code)
```
之後執行程式

也可從rancher上看到我們部屬的nginx-test

如果要新增其他欄位也可以


從上方POST回傳的DATA可以看到 annotation 的KEY叫做workloadAnnotations 而從create workload裡的yaml檔可以看到名稱要叫做field.cattle.io/description 因此我們要將一個deployment新增 description的話需要這樣做修改
```python=
config = {
"containers": [{
"imagePullPolicy": "IfNotPresent",
"image": "ubuntu/apache2:latest",
"name": "apache-test"
}],
"namespaceId": "test-namespace",
"name": "apache-test",
"workloadAnnotations":{
"field.cattle.io/description": "FOR-API-TEST"
}
}
```
執行程式
同樣可以看到我們的workload有新增(如果是第一次部屬的話要等他pullimage)

點進去後也能看到我們的description

再到pod看我們剛剛部屬的apache server的ip

在網頁上打上ip則也可看到apache的網頁

## DAY16 透過 Rancher 進行資源控管
透過rancher 進行Pod資源控管可以有很多種方式,透過namespace 透過project做限制 或是利用PVC的方式
首先先介紹透過project去限制資源使用量

進到project的畫面後選擇create project

從這邊就能去創建自己的project 要設定限制資源的旁邊選擇Resource Quotas

三個選項分別是 資源類型,project的限制,namespace的限制

這邊設定兩個 分別是 CPU 與 Memory的上限
CPU設定為project只能使用1000 namespace在創建的當下會預設為500
memory則是限制為2GB namespace預設是1GB 這邊namespace預設的數值在創建namespace時都可以在重新調整

創建好後接下來來創建自己的namespace 同樣的先點create namespace

這邊可以看到一開始就幫我們設定好我們resource quotas了
因為我們前面設定過project的resource了
這邊我們就先不去做調整按create namespace

這邊可以看到 如果我們不去做調整 這個project就只能在創建一個namespace
#### Rancher的project create API 和 namespace API
前面有說透過Rancher創建project和namespace 這邊介紹透過API去做建立的動作,首先要先知道API的位址 首先先到v3/cluster的地方找到自己的cluster 之後在自己的cluster的的地方找到project

如果懶的話也可以照deploy API的方法在v3/cluster的後面打上/cluster id
找到project APi的位址後
就可以來測試創建一個project
```python=
import requests
headers = {"Authorization": "Bearer token-7gqj9:4jp2r7m78b5cxq7wr4krfthr8tvvsjpzw6x9v5jgvfxzflbs8gcflf"}
config = {
"name" : "resourceTEST",
"namespaceDefaultResourceQuota":{
"limit": {
"limitsMemory": "512Mi"
}
},
"resourceQuota":{
"limit":{
"limitsMemory": "1024Mi"
}
}
}
response=requests.post('https://192.168.182.162/v3/clusters/c-d8dqp/projects', json=config, headers=headers,verify=False)
print(response.text)
print(response.status_code)
```
從上面建立時的欄位可以看到 基本上project在不需要其他設定的情況下,只需要我們填名稱就可以了 這邊有多新增resource的用量限制欄位資料
而資料欄位一樣可以透過創建時的yaml去做查看

這邊可以看到我們設定的Resource Quotas的欄位在yaml上長這樣

所以這邊我們再新增一個
```python=
import requests
headers = {"Authorization": "Bearer token-7gqj9:4jp2r7m78b5cxq7wr4krfthr8tvvsjpzw6x9v5jgvfxzflbs8gcflf"}
config = {
"name" : "resourceTEST",
"namespaceDefaultResourceQuota":{
"limit": {
"limitsCpu":"500m",
"limitsMemory": "512Mi"
}
},
"resourceQuota":{
"limit":{
"limitsCpu":"1024m",
"limitsMemory": "1024Mi"
}
}
}
response=requests.post('https://192.168.182.162/v3/clusters/c-d8dqp/projects', json=config, headers=headers,verify=False)
print(response.text)
print(response.status_code)
```
在按下執行

可以看到我們創建的成功了
接下來換namespace
因為我們project設定過了所以我們直接創建一個namespace
```python=
import requests
headers = {"Authorization": "Bearer token-7gqj9:4jp2r7m78b5cxq7wr4krfthr8tvvsjpzw6x9v5jgvfxzflbs8gcflf"}
config = {
"name" : "hackmdtest",
"projectId" : "c-d8dqp:p-4mrpn"
}
response=requests.post('https://192.168.182.162/v3/clusters/c-d8dqp/namespace', json=config, headers=headers,verify=False)
print(response.text)
print(response.status_code)
```
按下執行
同樣可以看到我們新創建的namespace有被預設限制容量

如果我們要從沒限制的project創建一個有被限制資源使用量的namespace的話
可透過containerDefaultResourceLimit的欄位去做限制
```python=
import requests
headers = {"Authorization": "Bearer token-7gqj9:4jp2r7m78b5cxq7wr4krfthr8tvvsjpzw6x9v5jgvfxzflbs8gcflf"}
config = {
"name" : "512resourcetest",
"projectId" : "c-d8dqp:p-dnzcn",
"containerDefaultResourceLimit": {
"limitsCpu":"512m",
"limitsMemory":"512Mi",
"requestsCpu":"512m",
"requestsMemory":"512Mi"
}
}
response=requests.post('https://192.168.182.162/v3/clusters/c-d8dqp/namespace', json=config, headers=headers,verify=False)
print(response.text)
print(response.status_code)
```
創建後同樣可以看到在config中有被設定好限制512M的記憶體與CPU了

## DAY 17 透過 Rancher 創建PV 與 PVC
K8s裡面有一個所謂PV(PersistentVolumes )和PVC(PersistentVolumesclaims)
PV會去切一塊本機或雲端上的空間而PVC會將PV所切出來的空間再去作分割給Pod做使用
而Rancher也提供我們介面設定PV與PVC
首先登入Rancher 並選擇你的cluster 左邊選單打開會看到Storage的地方

可以看到PV與PVC
點進去PV之後按create

Volume Plugin 選HostPath

可以看到我們的PV建立好了

而透過API建立的部分則是在v3的api中找到自己的cluster底下的PersistentVolumes
```python=
import requests
headers = {"Authorization": "Bearer token-7gqj9:4jp2r7m78b5cxq7wr4krfthr8tvvsjpzw6x9v5jgvfxzflbs8gcflf"}
config = {
"name": "testpv",
"accessModes":["ReadWriteOnce"],
"capacity":{
"storage":"10Gi"
},
"hostPath":{
"path":"/mnt/test"
},
"storageClassName": ""
}
response=requests.post('https://192.168.182.162/v3/clusters/c-d8dqp/persistentvolumes', json=config, headers=headers,verify=False)
print(response.text)
print(response.status_code)
```
這時切換到PVC去做設定

同樣Create一個PVC
而Volume Claim 選 use 現有的PV

這樣就創建好PVC了
但是Rancher提供在Deploy 服務時可以同時創建PV 與PVC的方式
## DAY18 透過Rancher安裝longhorn
上次有提到創建PV與PVC並assign給POD進行資源的儲存與控制,而如果不想每次都自己去進行創建呢?
這時就需要使用Storage class
這邊我們直接使用Rancher公司所開發的Longhorn
透過Rancher安裝時要先到App&Market place 的chart去安裝longhorn

安裝好後左方會出現longhorn 點進去後可以看到longhorn的dashboard

確認可以看到dashboard後同樣到Storage 的Storage class

create一個Storage class

create好了之後 回到deployment
在deployment create的地方左邊可以看到Storage
點了之後安add volume 選擇 create Persistent Volume Claim

並使用我們剛剛建立的Storage account

建立完成之後 回到剛剛的longhorn畫面
在上方volume的地方可以一個volume已經attach到我們的Storage class

而到pv 與 pvc 上則個都可以看到storage class 幫我們建好的pv與pvc


**而若要透過已經創建好的PVC去Assign給POD呢**
方法同樣是去create deployment

進到create之後選擇左下角的Storage
在add volume裡面選擇 Persistent Volume Claim

填上需要的資料後就能按craete

看到她active後就代表他成功部屬起來了

而API的部分則可透過deployment的API或是透過Yaml 進行post data查看

並使用我們之前做deployment時的API網址
```python=
import requests
headers = {"Authorization": "Bearer token-7gqj9:4jp2r7m78b5cxq7wr4krfthr8tvvsjpzw6x9v5jgvfxzflbs8gcflf"}
config = {
"containers": [{
"imagePullPolicy": "IfNotPresent",
"image": "ubuntu/apache2:latest",
"name": "apache-test",
"volumeMounts":[{
"name": "pvc-volume",
"mountPath": "/mnt/test"
}]
}],
"namespaceId": "test-namespace",
"name": "pod-pvc-test",
"labels":{
"test": "label_test"
},
"workloadAnnotations":{
"field.cattle.io/description": "FOR-PVC-TEST"
},
"volumes":[{
"name": "pvc-volume",
"persistentVolumeClaim": {
"persistentVolumeClaimId": "test-namespace:test123456",
"claimName": "test123456",
"type": "/v3/project/schemas/persistentVolumeClaimVolumeSource"
},
"type": "/v3/project/schemas/volume"
}],
}
response=requests.post('https://192.168.182.162/v3/projects/c-d8dqp:p-dnzcn/deployments', json=config, headers=headers,verify=False)
print(response.text)
print(response.status_code)
```
在執行程式時可以看到他回傳我們剛剛輸入的資料 如果沒有看到代表說rancher deploy時並沒有吃到我們的資料

可能的原因有三種 欄位名稱打錯,少中括號[],或是他其實沒有支援
資料欄位是否需要加上中括號可以從yaml 或是透過API查看目前有部屬的服務時查看


在yaml上有減號的代表前一個欄位後要加中括號
在看我們部屬的狀況

有看到我們部屬成功了
## DAY19 config map 和 secret
有用過k8s的對於config map 應該都不陌生 很多程式都會需要先設定環境變數才能讓它正常的啟動
而rancher 的config map 同樣也在Storage 的地方


按下create config map 後可以看到他會要求輸入key與value


key 與value輸入完後
按下create 回到workload的deployment 去進行create
進到craete設定畫面後往底下划可以看到Environment Variables(環境變數)

按下add variable type 選 config map key

並選擇剛剛輸入的config map 與選擇剛剛設定的key
確認其他應有設定都設定好後就可進行create
啟動好後這時回到主機上 使用
```bash=
docker exec -it container-id bash
```
進入剛剛啟動的pod裡面後打env 就可看到我們剛剛設定的環境變數被吃進去了


### secret
而secret 跟 config map 很像都會將一串DATA 跟 KEY放進pod裡面
而config map 也能做到跟secret 一樣的事 不過就如他的名稱secret config map 的資料比較容易在部屬時被查看 而secret可以避免這個情況發生
而RANCHER要設定secret 首先先點開volume 的最底下會有secret

之後按下 create 會要求你選擇你要的secret的類型

<!-- 這邊先選擇我們要放SSH 的金鑰
將自己電腦的私鑰與公鑰放進去

之後按create
回到deployment create服務 在image的底下有pull secret

選擇我們剛剛的secret -->
這邊先選擇 http basic auth
然後填入我們所設定的帳號密碼

之後按create
回到deployment create 一個新的pod
左邊選擇storage 後新增secrets

選擇我們剛剛的secret
並打上位址
之後按create 之後到終端機 進到pod裡面查看我們剛剛的位址 應該可看到user 跟 password

# DAY 20 Rancher import Helm Chart
Rancher 可透過helm chart安裝應用程式 而Rancher一開始就有他們預設的幾個helm chart

而若要加入自己的helm chart則可透過兩種方式
一是可透過用https 的方式到透過helm 建立的index去取得需要的資訊
二是可透過git的方式取得Helm chart的資訊

而這次透過git的方式添加第三方的APP 使用的repo(https://github.com/openfaas/faas-netes)
若對方有提供helm chart就可直接添加 首先先到左邊的repositoreis並按create

之後就會到剛剛的畫面 選擇透過含有helm chart 或cluster template資訊的git Repository
若添加的git沒有需要認證的限制就可直接按Create

而若沒問題就可以看到Active

而回到Charts 可看到剛剛添加的faas在最底下可以被看到

而自己建立的helm chart也可添加進去

而這邊就不做修改直接推上github
(https://github.com/kanic1111/helm_test)
之後透過同樣的步驟添加至repository

而同樣可以在Charts上看到我們添加的helm charts

而若使用者自己安裝application到主機上Rancher也可以做監控
這邊我們以存放docker image,kubernetes yaml,helm chart 並協助使用者掃描與協助簽署憑證確保資料安全的一個軟體HARBOR做舉例
首先先到自己的cluster 右上角會有 kubectl shell(自己SSH進到主機也可以) 可以使用Rancher所提供的terminal進行操作
連線成功後再terminal打
```bash=
helm repo add harbor https://helm.goharbor.io
helm fetch harbor/harbor --untar
cd harbor
sed -i 's/ type: ingress/ type: clusterIP/g' values.yaml
sed -i 's/ commonName: ""/ commonName: "harbor"/g' values.yaml
kubectl create ns harbor
helm install harbor . -n harbor
```
打完後就會進行安裝 而Rancher上也能看到installed app 中出現Harbor
等Harbor完全設定完成後就可看到幾個服務被部屬成功


而這邊到Harbor登入網頁會遇到一個問題 因為所有的Service都是由Harbor透過Rancher起的 因此再透過Rancher連線至網頁時會發現API打的時候的網址會是導到Rancher自己的網頁導致登入失敗。

為了確保他API連線到的是正確的位址因此我們要去Deployment的地方新增Service把Pod的Port對出來外面,因此到Deployment的地方修改Harbor- nginx Networking

將80,443,4443 port 透過nodeport去做對外

之後再到設定的443port的位址去做連線

就能成功登入了