basic for beginner
從 AWS EKS 下載 k8s config
範例:
aws eks --region ap-southeast-1 update-kubeconfig --name <cluster-name> --kubeconfig <the name that we download to local>
載下來的 kube config 如何載入
載下來的 config 可以放到 ~/.kube
內
然後在 bash profile 設定環境變數 KUBECONFIG
# k8s config setting
export KUBECONFIG=~/.kube/service-prod-config:\
~/.kube/service-staging-config
使用 context
# 取得 context list
kubectl config get-contexts
# 使用特定 context
kubectl config use-context <context name>
# 詢問當前 context
kubectl config current-context
使用 kubectx
可快速切換 k8s context 的工具
# 切到 <target context>
kubectx <target context>
# 列出所有 contexts
kubectx
# 切換到上一次使用的 context
kubectx -
# 設定別名 和 使用別名
kubectx <alias context name>=<original context name>
kubectx <alias context name>
進入 pod
範例: 進入 pod 並執行 sh 指令
kubectl exec -it <pod name> -- sh
顯示 cluster 資訊
kubectl cluster-info
取得 node 資訊
# -o wide 是 output in the plain-text format with any additional information.
kubectl get nodes -o wide
查看 k8s 版本資訊
kubectl version
查看 node 資訊
kubectl describe nodes <node name>
PODs
- container 不會直接被放到 node 內
- 是透過封裝在 pod 裡面才被放到 node
- 一個 pod 是一個單一的 application (通常是一對一)
- 但還是可以在一個 pod 裡面放多個 container (一起建立/一起銷毀)
- pod 是在 k8s 內可以建立的最小單位
- 負載量過大的時候會以 pod 為單位創建新的 application
指令:
# 從 dockerhub 拉下 nginx image 並執行成 名為 nginx 的 pod
kubectl run nginx --image nginx
# 建立 pod 同時指定要開放的 port 8080
kubectl run custom-nginx --image=nginx --port=8080
# 建立 pod 同時建立 labels
kukbectl run redis --image=redis:alpine --labels=tier=db
# 建立 pod 的時候順便指定 expose 的 port,--expose 會連 service 一起建出來
kubectl run httpd --image=httpd:alpine --port=80 --expose
# 取得 pods 列表
kubectl get pods
# 取得特定 pod 的詳細描述
kubectl describe pod <pod name>
# 直接連同 deployment 一起建立
kubectl create deployment nginx --image=nginx
# 刪除 pod
kubectl delete pod <pod name>
# 透過檔案建立 pod
kubectl create -f <file name>
# 透過基本旗標建立 pod yaml
kubectl run <container name> --image=<image name> --dry-run=client -o yaml > <taget yaml file name>
# 套用 yaml 檔案
kubectl apply -f <file name>
Replications controller & ReplicaSets
讓 pods 可以執行特定數量,如果掛掉的話可以重啟回固定數量
有點像是把 Pod 包起來的概念,Replication controller 會固定在內部的 pod 數量
- Scaling
- Replication Controller 支援跨 nodes,即可以控管多數個 nodes 總共需要幾個固定數量的 pods
- Load Balancing
- Replication Controller 也做 Load balancing,把流量導去不同的 pods
ReplicaSet 要取代舊式的 Replication Controller
Deployments
把新版本的 image 部署到 node 上
可以做 rolling update / rollback
Deployment 可以視為更大的範圍(集合),包含了 Replica Set 在裡面
# 手動建立 deployment
# deployment 名稱 webapp
# image 用 kodekloud/webapp-color
# repilicaset = 3
kubectl create deployment webapp --image=kodekloud/webapp-color --replicas=3
# 建立在 namespace dev-ns 上
kubectl create deployment redis-deploy -n dev-ns --image=redis --replicas=2
Deployment Updates and Rollback
建立 deployment 的時候,會觸發 rollout
一個新的 rollout 會建立一個新的 deployment revision
(例: 第一次發布為 revision 1,第二次發布為 revision 2)
revision 可以作為進版或退版的版本
指令:
# 查看特定 deployment 的 rollout 狀態
kubectl rollout status deployment/<deployment name>
# 查看特定 deployment 的 rollout 歷史紀錄
kubectl rollout history deployment/<deployment name>
# 重新開始 resource rollout
kubectl rollout restart deployment/<deployment name>
- Deployment strategy
- recreate
- 舊版全下 接著新版全上
- 會有 downtime
- rolling update (default)
- 舊的下一個 接著上一個新的
- 一個一個更新
- 實際是會產生一個新的 ReplicaSet,然後舊的 ReplicaSet下架舊的 Pod,並在新的 ReplicaSet 上架新的 Pod
- recreate
# 使用新的 yaml 檔案來觸發新的 rollout
# 且建立新版的 deployment
kubectl apply -f deployment-definition.yaml
# 直接變更 image (會導致 yaml 和實際的物件對不起來)
kubectl get image deployment/<deployment name> <container name>=<new image name>
# rollback
kubectl rollout undo deployment/<deployment name>
# 如果要在 rollout history 顯示 CHANGE-CAUSE 的話,要補 record flag
kubectl create -f <deployment file name> --record
Network 101
- 每個 Pod 都會被給予一個 IP address
- 但是要避免 private IP conflict (要自己另外處理)
- k8s 預期我們需要自己完成的項目
- 所有的 container / pod 都不透過 NAT 達到互相溝通
- 所有的 nodes 也可以和 containers 不透過 NAT 達到互相溝通
- 可以使用的 solution 套件
- Cisco ACI network
- Cilium
- Big Cloud Fabric
- Flannel
- VMWare NSX-T
- Calico
Service
k8s 的 service 用來協調 外部和內部 application 的溝通
- Type
- NoePort
- ClusterIP
- LoadBalancer
# 靠指令直接建立出 service
# 建出名稱 redis-service
# 是要接到 pod redis 開 port 6379,然後對到 pod target port 6379
# 建出來的是 ClusterIP
kubectl expose pod redis --port=6379 --target-port=6379 --name redis-service
NodePort
- 意思是在 Node上面開一個 Port,可以從外部對應到內部的 pod
- 可以設定 mapping 給 Node port 對 Pod port
- 以 service 的觀點來看的對應
- service 就像是一個 node 內的 virtual server,在 cluster 內有他自己的 IP address
ClusterIP
- Pod 上面預期 request 進入的 port 稱為
TargetPort
- Service 上對應給 TargetPort 的 port 稱為
Port
- 開在 Node 上的 port 稱為
NodePort
,有範圍限制,default 為 30000 ~ 32767
- service 就像是一個 node 內的 virtual server,在 cluster 內有他自己的 IP address
- 在相同的 node 內的相同 pod,因為 label 一樣,所以 service 會隨機導進流量
- 不同 node 的話,開的 node port 設定一樣的話,service 仍可以共用
ClusterIP
-
在 Cluster 內建立一個 virtual IP,讓內部的 pods 間可以溝通
-
比如說有一個 backend group 裡面都是 backend pod,以及一個 frontend group 裡面都是 frontend pots
在這兩個 group 之間,需要透過 ClusterIP service 來做通訊
LoadBalancer
- 對 application 提供 Load Balancer
- LoadBalancer 是掛在 Cluster 等級,用來接外部的流量要進哪台 Node
- 大部分的 Cloud provider 都有提供這功能
- 要 Cloud Provider 提供才可以做,Virtual box 是做不到的
microservice architecture 範例
轉成 k8s 的步驟
- Deploy pods
- Create services (ClusterIP)
- redis
- db
- Create Services (NodePort)
- voting-app
- result-app
volting-app-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: voting-app-pod
labels:
name: voting-app-pod
app: demo-voting-app
spec:
containers:
- name: voting-app
image: kodekloud/examplevotingapp_vote:v1
ports:
- containerPort: 80
result-app-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: result-app-pod
labels:
name: result-app-pod
app: demo-voting-app
spec:
containers:
- name: result-app
image: kodekloud/examplevotingapp_result:v1
ports:
- containerPort: 80
redis-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: redis-pod
labels:
name: redis-pod
app: demo-voting-app
spec:
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
postgres-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: postgres-pod
labels:
name: postgres-pod
app: demo-voting-app
spec:
containers:
- name: postgres
image: postgres
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
value: "postgres"
- name: POSTGRES_PASSWORD
value: "postgres"
worker-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: worker-app-pod
labels:
name: worker-app-pod
app: demo-voting-app
spec:
containers:
- name: worker-app
image: kodekloud/examplevotingapp_worker:v1
redis-service.yaml (ClusterIP)
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
name: redis-service
app: demo-voting-app
spec:
ports:
- port: 6379
targetPort: 6379
selector:
name: redis-pod
app: demo-voting-app
postgres-service.yaml (ClusterIP)
apiVersion: v1
kind: Service
metadata:
name: db
labels:
name: postgres-service
app: demo-voting-app
spec:
ports:
- port: 5432
targetPort: 5432
selector:
name: postgres-pod
app: demo-voting-app
voting-app-service.yaml (NodePort)
apiVersion: v1
kind: Service
metadata:
name: voting-service
labels:
name: voting-service
app: demo-voting-app
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30004
selector:
name: voting-app-pod
app: demo-voting-app
result-app-service.yaml (NodePort)
apiVersion: v1
kind: Service
metadata:
name: result-service
labels:
name: result-service
app: demo-voting-app
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30005
selector:
name: result-app-pod
app: demo-voting-app
指令:
kubectl create -f voting-app-pod.yaml
kubectl create -f voting-app-service.yaml
# 取得多個物件狀態
kubectl get po,svc
kubectl create -f redis-pod.yaml
kubectl create -f redis-service.yaml
kubectl create -f postgres-pod.yaml
kubectl create -f postgres-service.yaml
kubectl create -f worker-pod.yaml
kubectl create -f result-app-pod.yaml
kubectl create -f result-service.yaml
Deploying voting app on K8s with Deployments
(承上面的範例)
上面的範例可行,但沒辦法 scale
所以這段是要透過 deployment 來做部署
voting-app-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: voting-app-deploy
labels:
name: voting-app-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: voting-app-pod
app: demo-voting-app
template:
metadata:
name: voting-app-pod
labels:
name: voting-app-pod
app: demo-voting-app
spec:
containers:
- name: voting-app
image: kodekloud/examplevotingapp_vote:v1
ports:
- containerPort: 80
redis-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deploy
labels:
name: redis-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: redis-pod
app: demo-voting-app
template:
metadata:
name: redis-pod
labels:
name: redis-pod
app: demo-voting-app
spec:
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
postgres-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deploy
labels:
name: postgres-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: postgres-pod
app: demo-voting-app
template:
metadata:
name: postgres-pod
labels:
name: postgres-pod
app: demo-voting-app
spec:
containers:
- name: postgres
image: postgres
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
value: "postgres"
- name: POSTGRES_PASSWORD
value: "postgres"
worker-app-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: worker-app-deploy
labels:
name: worker-app-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: worker-app-pod
app: demo-voting-app
template:
metadata:
name: worker-app-pod
labels:
name: worker-app-pod
app: demo-voting-app
spec:
containers:
- name: worker-app
image: kodekloud/examplevotingapp_worker:v1
result-app-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: result-app-deploy
labels:
name: result-app-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: result-app-pod
app: demo-voting-app
template:
metadata:
name: result-app-pod
labels:
name: result-app-pod
app: demo-voting-app
spec:
containers:
- name: result-app
image: kodekloud/examplevotingapp_result:v1
ports:
- containerPort: 80
指令:
kubectl create -f voting-app-deploy.yaml
kubectl create -f redis-app-deploy.yaml
kubectl create -f postgres-deploy.yaml
kubectl create -f result-app-deploy.yaml
kubectl create -f worker-app-deploy.yaml
使用 AWS EKS (Elastic Kubernetes Service)
需要準備
- AWS 帳號 (cli 要用的)
- 安裝 kubectl cli
- IAM role for Node Group
- VPC
- EC2 key pair (for SSH)
- AWS basics
- 選擇 EKS 選項
- 建立 Cluster
- 增加 Node Group (一組 worker nodes)
- 在本機設定讓 kubectl 可以操作這個 cluster
- 下 aws cli 指令把 cluster 的 kubeconfig 抓下來,即可在本機透過 kubectl 操作
# 下指令把 eks 的 kubeconfig 對應到 local 的 kube 設定
aws eks --region <region name> update-kubeconfig --name <cluster name>
# 查看 nodes 資訊
kubectl get nodes
# 使用 get svc 上面列的 EXTERNAL-IP 來做連線 (可直接貼到 browser 上)
kubectl get svc
範例中 原本 NodePort service 在上 AWS EKS 以後改成用 LoadBalancer service
即 EKS 上只有用到 ClusterIP, LoadBalancer 兩種 service