CKAD_20210928_change

▲ CKAD 新舊版差異


119. Define, build and modify container images


非常基礎的 Docker Image (container image) 介紹,我之前就打過一篇在公司 Bookstack 了~
《Docker Image 介紹》

使用 dockerpodman

大部分情況 dockerpodman syntax 很接近~

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
## docker multi tags
sudo docker build -t registry.killer.sh:5000/sun-cipher:latest -t registry.killer.sh:5000/sun-cipher:v1-docker .

## pod man build image
podman build -t registry.killer.sh:5000/sun-cipher:v1-podman .

## podman run container
podman run -d --name sun-cipher registry.killer.sh:5000/sun-cipher:v1-podman

## podman show process
podman ps

## podman logs
podman logs sun-cipher


121. Authentication, Authorization and Admission Control


除了 master,worker node 本身的安全機制 (例如: SSH public key ONLY) 以外
kube-apiserver 在 K8s cluster 當中扮演非常關鍵的角色必須要被嚴格控管,接下來的章節會介紹 How to
一開始我們先來探討一下 Who can access?What can they do?


Who can access?


who_can_access

  • Files - username and passwds
  • Files - username and tokens
  • Certification
  • 外部授權平台 (例如: LDAP)
  • Service Account

What can they do?

其實我不知道中文怎麼翻.. What can they do ?? 總之看起來像 K8s 的授權 (Authorization) 控管方式:

  • RBAC Authorization. (Role Base Access Control)
  • ABAC Authorization. (Attribute Base Access Control)
  • Webhook Mode

tls_certs

▲ K8s cluster 內各個元件在溝通時都透過 TLS 加密


122. Authentication


本章節的重點會放在三種不同 user 如何透過 Authentication 機制安全的訪問 K8s cluster

  • K8s cluster admin
  • Developer
  • End User (在這邊被移除,講師認為 sercurity 責任應該在 app 本身)
  • Bots (service account)

k8s_account_0

▲ Kubernetes cluster 原始狀態並沒有提供使用者的功能


k8s_account_1

▲ 不管是透過 kubectl 或者 curl (通常不會這樣用啦) 都要找 kube-apiserver。首先會 (1) Authenticate Users (2) Process request。


k8s_account_2

驗證 (authentication) 的方式有這些:

  • Static Password File
  • Static Token File
  • Certificates
  • External service (EX: LDAP)

File

前兩項都是以 file 的形式去給定使用者帳號跟密碼。 兩種都不建議使用

1
2
## <passwd>,<username>,<user_id>,<group_name>
password123,user1,u0001

k8s_account_3

▲ 然後在啟動 kube-apiserver 的時候傳進去


k8s_account_4

curl 搭配 user/passwd 的認證方式


k8s_account_5

token 的部分


123. KubeConfig


kube_config_0

▲ 正常來說,透過 kubectl 或者 curl 來取得 pod 的資訊,指令應該長這樣。
因為使用起來太麻煩了,我們會把這些資訊放在 KubeConfig file ($HOME/.kube/config) 裡面


kube_config_1

▲ config file 裡面包含三個東西: Cluster, Context, Users。而 Context 就是串連 ClusterUser 的東西。
其實這東西在前面章節的 LAB 就應該要接觸到了 (我記得我的筆記也有打) kubectl config set-context --current --namespace= 有印象了吧!


kube_config_2

▲ config file 內容是 YAML


kube_config_3

▲ 使用 kubectl config use-context <context_name> 來切換。


125. API Groups


一直以來 kubectl 都是在跟 api-server 互動,這個章節要講的是 API Groups。
接下來的動作會需要使用 curlapi-server 互動,達成這個需求最簡單的方式就是使用 kubectl proxy 在 localhost 幫我們扮演一個 reverse proxy 的角色,這樣一來就能很簡單的使用 curl 不會複雜!

Access Clusters Using the Kubernetes API

1
2
3
4
5
6
7
8
## run proxy in bg
kubectl proxy --port=8080 &

## bg -> fg
fg

## show bg jobs
jobs
1
curl http://localhost:8080/api/

api_groups_0

▲ 列出 api-server 的 IP address


api_groups_1

▲ 列出所有選項


api_one_page

▲ 一頁式 api page 能夠很清楚的知道各個 K8s Object 屬於哪個 API Group


api_groups_2

▲ 每個 Resources 底下的都有 Verbs (動作)


126. Authorization


authorization_0

▲ 本章節目的很簡單,權限區分。根據不同使用者給予不同權限


Authorization Mode 列表如下:

  • AlwaysAllow
  • Node
  • ABAC
  • RBAC
  • WebHook
  • AlwaysDeny

Node Authorizer

Node Authorizer 是專門給 worker node 與 api-server 之間溝通使用。


node_mode_0

kubelet 必須在 SYSTEM:NODES group 裡面 (使用 certification)。


ABAC Authorizer

全名: Attribute Base Access Control
針對每個 user 設定權限 (1:1 關係)


abac

▲ 每一次 新增/刪除 都需要重啟 api-server。很麻煩,所以有了 RBAC


RBAC Authorizer

全名: Role Base Access Control


rbac


WebHook Authorizer


webhook

▲ 其實不難懂,就是透過 webhook 去請外部 server 授權


node_mode_1

api-server 預設使用 AlwaysAllow


node_mode_2

▲ 講師建議的配置,會依序授權。授權失敗往下一個,授權成功返回。


127. Role Based Access Controls


建立 Role 的方式很簡單,只需要記住 --resources=--verb= 即可。

1
kubectl create role role-test --resource=pod --verb=get --verb=list --verb=watch --dry-run=client -o yaml

可以看到 pod 自動變成 pods 了! 由於 resource pod 屬於 core api 所以 .rules.apiGroups[] 可以是空白。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: role-test
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

rbac_0

▲ 透過指定 --resource-name 可以指定對象。


接著我們要把 Role 綁到 user 身上 => rolebinding

只需要記住 --role=--user= 即可。

1
kubectl create rolebinding rb-test --role=role-test --user=beta --dry-run=client -o yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: rb-test
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: role-test
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: beta

測試權限

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kubectl auth can-i create pod
kubectl auth can-i delete deployment
kubectl auth can-i get service

## as user
kubectl auth can-i create pod --as=beta
kubectl auth can-i delete deployment --as=beta
kubectl auth can-i get service --as=beta

## particular namespace
kubectl auth can-i create pod --as=beta --namespace=say-my
kubectl auth can-i delete deployment --as=beta --namespace=say-my
kubectl auth can-i get service --as=beta --namespace=say-my

128. Cluster Roles


diff_between_namespace_and_cluster_scope

▲ 首先要先介紹 namespace ed 與 Cluster scope 旗下物件的差異。


namespaced_true

kubectl api-resources --namespaced 可以列出需要 namespace 的 K8s resource。
反之 kubectl api-resources --namespaced=false


cluster_role_0

▲ 舉例: 使用 clusterrole 讓 cluster-admin 可以管理 worker-node。不過 clusterrole 並沒有限定 resource 只能是 namespaced == false 的物件! 當使用者使用 clusterrole 建立 resource == pod 的 RBAC 時,等於 namespace == 所有 K8s cluster 內的 namespace


cluster_role_1

▲ K8s cluster 已經內建許多 clusterrole


130. Admission Controllers


前面兩個 A (Authentication, Authorization) 有點像是控制 api-server 的「大門」,Admission controllers 是針對進入大門之後的操作做控制。


admission_controller_0

▲ 講師舉了一個預設開啟的 NamespaceExists 當作例子。當我們要在不存在的 namespace == blue 建立 pod 時會出現錯誤就是因為 Admission controller 當中的 NamespaceExists == Enabled 造成的。


使用 Minikube (docker) 的話,可以透過 minikube ssh 登入 control plane。接著 docker exec -it f099fdd513e0 kube-apiserver --help | grep 'enable-admission-plugins'
或者使用

1
2
## PLEASE NOTICE, the pod name won't the same
kubectl exec kube-apiserver-mini-k8s -n kube-system -- kube-apiserver --help | grep 'enable-admission-plugins'

K8s cluster 預設開啟以下 plugin:

1
--enable-admission-plugins strings       admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionWebhook, ResourceQuota).

admission_controller_1

▲ 講師示範開啟 NamespaceAutoProvision,當 namespace 不存在時會自動建立。


132. Validating and Mutating Admission Controllers


Admission Controllers 分為兩種形式:

  • Validation: 驗證
  • Mutating: 自動補齊

mutation_admission_controller

▲ Mutating (變種、變異) Admission controller 能夠自動幫我們補齊 YAML file 當中遺漏的 key-value。上圖是以漏寫 storageClassName 為例子。

一般來說 Mutating 的順序會在 Validation 前面。


內建的用不夠 ? 沒關係,可以使用 Webhook 外包:

  • MutatingAdmission Webhook
  • ValidationAdmission Webhook

admission_webhook_0

▲ 以 JSON format 傳送請求,外包 server 也會以 JSON 回應回來。


admission_webhook_1

▲ webhook server 當然可以被建在 K8s cluster 裡面 (如左圖),接著我們必須建立 ValidatingWebhookConfiguration 或者 MutatingWebhookConfiguration (如右圖)

考試的時候不知道會不會這麼硬~


LAB Tips: 建立 TLS secret kubectl create secret tls webhook-server-tls --cert /root/keys/webhook-server-tls.crt --key /root/keys/webhook-server-tls.key --dry-run=client -o yaml記住 --cert, --key


134. API Versions


api_version_0

▲ 只有 Alpha 預設是 Disabled


同一個 api group 可以有很多版本,但只會有一個版本被設定成 preferredstorage


api_version_1

▲ 當下達 kubectl get deployment 或者 kubectl explain deployment 使用的 api version 即為 preferred version。
storage version 是以哪個版本儲存在 etcd 裡 (即使你的 YAML file 使用其他版本,都會被轉換)。


api_version_2

▲ 使用 curl 查詢 preferred api version。
storage version 現階段只能透過 query etcd 查詢。


api_version_3

▲ 開啟 alpha version。


135. API Deprecations


Kubernetes Deprecation Policy 這個章節在講發布 api version 的規則,有興趣的自己去翻官網吧!
本章的重點只有一個: kubectl convert 轉換 YAML file 使用的 api version。


api_deprecation_0

▲ 如果沒辦法使用 kubectl convert 的話需要安裝 plug-in。 Install kubectl convert plugin


137. Custom Resource Definition


這個章節介紹的 CRD 用途是讓我們自定 Kubernetes resources (前面筆記有時候可能被我稱為 K8s 元件)。
CRD 只是可以讓 custom resources 資訊可以被放入 etcd 這個 key-value database 當中 實際上要「動作」必須還要有 Controller。


crd_0

▲ controller 負責 monitoring etcd 然後依據變化執行動作。


crd_1

▲ 眾多 resources 與 controllers


假設今天我們想創建一個 FlightTicket 物件來幫我們訂機票


crd_2

好久沒看到台灣廉航福利社發機票文喔


1
2
3
4
5
6
7
8
apiVersion: flights.com/v1
kind: FlightTicket
metadata:
  name: my-flight-ticket
spec:
  from: TPE
  to: KIX
  number: 2

crd_3

▲ 因為沒有 CRD 的關係,所以這個 resource 被拒絕惹


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  # name must match the spec fields below, and be in the form: <plural>.<group>
  name: flighttickets.flights.com
spec:
  # group name to use for REST API: /apis/<group>/<version>
  group: flights.com
  # list of versions supported by this CustomResourceDefinition
  versions:
    - name: v1
      # Each version can be enabled/disabled by Served flag.
      served: true
      # One and only one version must be marked as the storage version.
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                from:
                  type: string
                to:
                  type: string
                number:
                  type: integer
  # either Namespaced or Cluster
  scope: Namespaced
  names:
    # plural name to be used in the URL: /apis/<group>/<version>/<plural>
    plural: flighttickets
    # singular name to be used as an alias on the CLI and for display
    singular: flightticket
    # kind is normally the CamelCased singular type. Your resource manifests use this.
    kind: FlightTicket
    # shortNames allow shorter string to match your resource on the CLI
    shortNames:
    - ft

各項上面都有註解,我就不多做解釋了


crd_4

▲ 有了 CRD resource 就可以成功被建立!


138. Custom Controllers


kubernetes/sample-controller 官方提供以 Golang 撰寫的 controller 範本。


139. Operator Framework


Operators are software extensions to Kubernetes that make use of custom resources to manage applications and their components. Operators follow Kubernetes principles, notably the control loop.

總之 Operator Framwork 就是一個 Operator 框架 (在講廢話逆) 方便讓使用者 擴充/管理 客製化的 resources。


講師感覺就很簡單的帶過這個章節~ 單純介紹而已吧!


140. Deployment Strategy - Blue Green


在之前的章節有介紹過 rolling upgrade,這種部屬策略不會像 re-create 一樣把舊的 pod 一次全部刪除,而是 one by one 的替換,使服務不中斷。
Blue Green 部屬策略則是先將新版本 部屬、測試 後,透過 edit service selector 的方式將流量導過去
講完,沒了!


blue_green

▲ Blue Green 部屬策略


141. Deployment Strategy - Canary


canary deployment - 金絲雀部屬,做法是將新版 app 部屬一小部分。什麼意思呢? 看圖~


canary_deployment

▲ canary deployemt


要解決的兩件事:

  • service 將流量同時導到兩個 deployment。所以我們需要 在兩個 deployment 擁有一個相同的 label,而且 service selector 也只能有相同的部分
  • 只將小部分流量導到新版。這個部分透過控制新版 replicas 達成 (若要精準控制百分比,需要 Istio 或類似服務幫忙)

143. Helm Introduction


假設今天要透過 Kubernetes 架設 WordPress 我們需要….

  • WordPress pod/deployment
  • secret (儲存設定時的機敏資訊)
  • Persistant Volume (PV)
  • Persistant Volume Cliam (PVC)
  • service (對外服務)

所需的 resources 很碎片化,可是又牽一髮動全身的感覺,各個 resoruce 環環相扣…
部屬麻煩、客製化修改麻煩、更新麻煩,什麼都很麻煩! 所以有了 Helm 這個 package manager (登楞!


Helm 一樣保有 K8s deployment 的特性,可以

1
2
3
helm install wordpress
helm upgrade wordpress
helm delete wordpress

helm_values

▲ Helm 設定值都在 values.yml 裡面了


Install Helm

Installing Helm

1
2
3
4
5
## bash completion
helm completion bash > /etc/bash_completion.d/helm

## sourced it right now.
source <(helm completion bash)

146. Helm Concepts


要使用 Helm 之前,必須把 Kubernetes resources YAML file 裡面的值變成變數 => 這個 YAML file 被稱為 Template
使用者只須要在 values.yaml 設定參數即可~
串聯打包這些東西的東西叫做 Chart.yaml

Helm uses a packaging format called charts. A chart is a collection of files that describe a related set of Kubernetes resources.


helm_template

▲ 由 bitnami 出產的 WordPress Helm template。 source


helm_value_wordpress

▲ 由 bitnami 出產的 WordPress Helm values.yamlsoruce


helm_chart

▲ 由 bitnami 出產的 WordPress Helm Chart.yamlsource


Helm repo

安裝完 helm 預設是沒有任何 repositry 的~ 就來新增吧! bitnami 是 VMware 創立的,另外一個是開源 for CNCF 的 ArtifactHub.io (給我的感覺是比較偏包山包海、路人甲乙都能上傳自己的 chart)

1
2
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo list

helm_repo_add

▲ 新增 helm repo


helm_search

▲ 透過 helm search repo 使用剛剛加入的 bitnami 搜尋 package。


How to install package

1
2
## helm install <release-name> <chart>
helm install my-release bitnami/wordpress

helm_install_release

▲ 各個 release 各自獨立


Helm 常用指令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
## list all release
helm list

## uninstall
helm uninstall <release-name>

## just download package NOT install
helm pull --untar bitnami/nginx

## rollback
helm rollback <release name>

## show Chart variables
helm show values bitnami/apache | grep 'replica'

## set replica (in namespace 'mercury')
helm -n mercury install internal-issue-report-apache bitnami/apache --set replicaCount=2

Kill.sh 筆記


這邊會記錄做完 kill.sh 的模擬考後 (心虛) 需要再加強的地方 or 小技巧。如果能找到相對應的章節 (例如: Helm) 就會在該章節補充;反之找不到適合的地方就會放在這邊。


利用 pod 裡面的 command 執行指令

1
2
3
4
kubectl run tmp --image=nginx:alpine --rm -i -- curl https://ipinfo.io/

## visit svc like this. http://<svc name>.<namespace>:<port>
curl http://project-plt-6cc-svc.pluto:3333

--rm 與 Docker 一樣,使用後即拋棄。 -i 開啟 tty 互動介面。 -- 不加的話會被當前 shell 解析。


tmp_pod_using_command


Restart Deployment

1
kubectl rollout restart deployment my-nginx

restart_deployment

restart 的方式是先產生一個新的 pod 再把舊的砍掉。


service 除錯


svc.spec.selector 是指向 pod 的 labels 而不是 Deployment 的!!