k8s的安裝教程可以看上一篇 https://developer.aliyun.com/article/806212
1.資源
k8s中所有的對象可以稱為k8s的資源,之前安裝k8s時就已經體驗過k8s的資源了
k8s中資源的建立方式:
- 指令行
- yaml 如安裝calico時使用的yaml
2. NameSpace
命名空間,主要用來隔離資源,預設不隔離網絡
2.1 使用指令行操作名稱空間:
# 檢視名稱空間
kubectl get ns/namespace
# 建立名稱空間
kubectl create ns [名稱空間名]
# 删除名稱空間 會删除該名稱空間下的所有資源
kubectl delete ns [名稱空間名]
同樣的,可以解析下之前用過的指令
# -A是擷取所有資源,如果不加-A 會預設使用default名稱空間 也可以指定名稱空間
kubectl get pod -A
# 指定名稱空間
kubectl get pod -n [名稱空間名]
2.2 使用yaml操作名稱空間
建立如下yaml配置檔案 hello.yaml
建立時注意格式,注釋需要去掉
apiVersion: v1 #版本号
kind: Namespace #資源類型 指定為namespace
metadata: #中繼資料
name: hello #命名空間名稱
# 建立名稱空間資源
kubectl apply -f hello.yaml
# 删除名稱空間資源
kubectl delete -f hello.yaml
k8s中使用配置檔案建立的資源都可以通過配置檔案删除
3. pod
pod是k8s中運作的最小機關,也是運作的一組容器
pod相對于k8s來說,與docker中的容器概念類似
如下圖所示,解釋pod的概念
docker是k8s運作的基礎環境,
pod是k8s的最小機關,但是一個pod中可以有多個容器在運作,不同的pod是互相隔離的

3.1 pod基本操作指令
3.1.1 指令行方式操作pod
# 建立pod
kubectl run [pod名] --image=[鏡像名]
example:
kubectl run mynginx --image=nginx
# 檢視pod建立日志
kubectl describe pod [pod名]
# 删除pod 可以在後面加上-n [namespace名]
kubectl delete pod [pod名]
3.1.2 YAML方式操作pod
建立如下内容yaml pod.yaml
apiVersion: v1
kind: Pod #資源類型
metadata:
labels:
run: mynginx
name: mynginx # pod名稱
spec:
containers:
- image: nginx #鏡像
name: mynginx
kubectl apply -f pod.yaml
# 删除pod
kubectl delete -f pod.yaml
3.1.3 dashboard操作pod
界面化操作,略
3.1.4 pod的一些常用指令
pod的指令與docker 容器的相關指令類似
# 檢視pod運作日志
kubectl logs [-f] [pod名]
# 檢視pod詳細資訊 -owide檢視詳細資訊 包括pod的ip
kubectl get pod [-n namespace] -owide
# 進入pod
kubectl exec -it [pod名] -- /bin/bash
3.1.5 多容器pod
建立如下内容的yaml, multicontainers.yaml
kind: Pod
run: myapp
name: myapp
- image: nginx
name: nginx
- image: tomcat:8.5.68
name: tomcat
kubectl apply -f multicontainers.yaml
一個pod中不能啟動兩個相同的容器,端口沖突導緻啟動失敗
4. Deployment
通過Deployment使pod擁有多副本,自愈,擴縮容的能力
# 原來的建立pod
# 通過Deployment建立pod
kubectl create deployment my_deployment_nginx --image=nginx
通過deployment建立的pod,再删除(當機)後會自動重新建立一個pod,這就是k8s的自愈能力
# 删除deployment
kubectl delete deploy my_deployment_nginx
4.1 多副本
deployment可以啟動多個pod,稱之為副本
# 建立多副本 replicas副本數
kubectl create deployment my_tomcat_deployment --image=tomcat:8.5.68 --replicas=3
dashboard同樣可以操作
4.2 擴縮容
通過deployment可以對pod進行擴縮容,增加/減少pod的數量
4.2.1 指令行擴縮容
# 擴縮容 指定副本數即可
kubectl scale deployment/[deployment名] --replicas=5
4.2.2 yaml擴縮容
# 使用edit指令
kubectl edit deploy [deployment名]
# 修改replicas屬性 儲存後即可
4.2.3 dashboard擴縮容
4.3 自愈&故障轉移
自愈: pod發生故障後,k8s重新開機該pod後正常,稱為自愈
故障轉移: pod所在機器可能發生故障(斷電等特殊情況),k8s在其他節點重新拉起故障節點的pod,稱為故障轉移
# 測試自愈 在某個pod所在節點 停止容器
docker stop [容器名]
# 可以看到k8s會自動重新開機該pod
# 測試故障轉移,直接将某個pod所在節點關機
# 可以看到5min後,k8s會重新開機拉起一個pod
4.4 滾動更新
滾動更新: 在修改deployment的鏡像時(更新),會先新啟一個新版本的pod,當新版本的pod啟動後,再停止老版本的pod,依次對老版本的pod進行此操作,最終達到更新鏡像的效果
# 滾動更新 鏡像名可以通過deployment的yaml中尋找,就是- image下的name屬性
kubectl set image deploy/[deployment名] [鏡像名]=[新鏡像名] --record
4.5 版本回退
一個deployment經過多次更新後,會産生多個版本,可以通過版本回退回退到某一個版本
# 檢視曆史版本 加--revision 可以看到某一個版本的詳情
kubectl rollout history deployment/[deployment名]
# 回退到某一個版本 不加--revision預設會復原到上一個版本
kubectl rollout undo deployment/[deployment名] --revision=[通過檢視曆史看到的版本号]
# 檢視復原後的deployment的yaml配置檔案
kubectl get deploy/[deployment名] -oyaml | grep [查找項]
版本回退的過程也是一次滾動更新
4.6 其他工作負載
deployment是其中一種工作負載
deployment是無狀态的,針對于微服務這種業務資料都存在與中間件中的應用
除此之外,還有其他的工作負載
- 有狀态工作負載: StatefulSet 提供穩定的存儲,網絡等功能
- 守護應用工作負載: DaemonSet 比如日志收集元件,每個機器運作一份
- 定時應用工作負載: Job/CronJob 比如垃圾清理元件,定時運作
5. Service
Service:是将多個pod對外暴露成一個服務,可以實作對pod的服務發現和負載均衡
舉例:
有三個微服務pod,每個pod有自己的IP,前端調用的時候無法自動的負載,需要背景來暴露出唯一的一個ip,通過service就可以做到,而且當某一個pod挂了之後,Service就可以将之後的流量打入其他兩個pod中,實作服務發現的功能
# 暴露服務 --port為暴露端口 --target-port為目标端口即原pod的端口
kubectl expose deploy [deployment名] --port=8000 --target-port=80
# 檢視服務 可以擷取暴露服務的ip
kubectl get service
此時可以使用服務ip:服務port通路該Service
同時在叢集容器内部,可以使用 域名:port 通路
域名規則: Service名.NameSpace名.svc
這種叢集内部可以通路的方式 就是ClusterIP方式 即叢集ip方式
這個時候傳回來看之前的 k8s-dashboard的搭建,當時修改了type為 NodePort,即節點端口方式
5.1 服務發現
Service會對pod進行動态的發現,當某個pod離線後,就不會将流量繼續負載給該pod,當擴容一個pod後,Service也會自動将該pod納入負載的範圍内,根據一定的政策将流量分發至該pod
5.2 端口暴露方式
Service主要就是端口的暴露,分為兩種方式
5.2.1 ClusterIP
# ClusterIP模式也是預設的 即不加--type就是ClusterIP
kubectl expose deploy [deployment名] --port=[暴露端口] --target_port=[pod服務端口] --type=ClusterIP
以叢集IP的方式暴露端口,此時在叢集内部可以通過
- 叢集内部ip:port的方式通路
- 也可以通過域名:端口的方式通路
5.2.2 NodePort
以目前機器節點的方式暴露端口
kubectl expose deploy [deployment名] --port=[暴露端口] --target_port=[pod服務端口] --type=NodePort
# 此時查詢service
kubectl get svc
可以看到除了叢集ip port之外,又多一個端口 這就是目前伺服器的端口
此時可以通過伺服器ip+此端口即可通路(注意放行安全組)
k8s生成的NodePort node範圍為 30000- 32767之前,可以在安全組内直接對此範圍内的端口放行
6. Ingress
Ingress是k8s-Service的入口,相當于統一網關,底層是Nginx
通過Ingress将不同的請求分發至不同的Service
官網:
https://kubernetes.github.io/ingress-nginx/deploy/6.1 安裝
k8s預設沒有安裝Ingress,需要手動安裝
# 下載下傳ingress-nginx
wget
https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml# 修改ingress-nginx的鏡像源 改為阿裡雲
vi deploy.yaml
registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0
# 安裝
kubectl apply -f deploy.yaml
# 檢視安裝服務
kubectl get pod,svc -n ingress-nginx
# 放行svc端口
6.2 使用
安裝後,檢視服務就可以看到ingress-nginx 命名空間下的服務,可以通過此服務暴露的端口來通路
Ingress也是一個Service
注意: Ingress會暴露兩個端口
80的為http請求端口
443的為https請求端口
6.2.1 測試
測試的目的是通過Ingress來通路不同的Service
架構如下:
6.2.1.1 準備工作
6.2.1.1.1 建立deploy/Service
建立兩個deploy,并将其暴露成Service
建立如下yaml, test.yaml
apiVersion: apps/v1
kind: Deployment
name: hello-server
replicas: 2
selector:
matchLabels:
app: hello-server
template:
metadata:
labels:
app: hello-server
spec:
containers:
- name: hello-server
image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
ports:
- containerPort: 9000
---
app: nginx-demo
name: nginx-demo
app: nginx-demo
app: nginx-demo
- image: nginx
name: nginx
kind: Service
ports:
- port: 8000
protocol: TCP
targetPort: 80
app: hello-server
targetPort: 9000
裡面分别建立了兩個 Deployment 并暴露成Service,啟動兩個Deployment的鏡像就是簡單的hello-server和nginx
通路hello-server傳回一個hello字元串
通路nginx傳回nginx的首頁
# 建立如上資源
kubectl apply -f test.yaml
6.2.1.1.2 建立Ingress
建立如下yaml ingress.yaml,
rules配置的很類似gateway的配置
host就是請求的域名,根據域名來轉發到不同的Service
apiVersion: networking.k8s.io/v1
kind: Ingress
name: ingress-host-bar
ingressClassName: nginx
rules:
- host: "hello.zy.com"
http:
paths:
- pathType: Prefix
path: "/" # 字首是/後的所有請求會被轉發至service
backend:
service:
name: hello-server # 轉發至的service
port:
number: 8000 # service端口
- host: "demo.zy.com" # 多個規則
path: "/"
name: nginx-demo
number: 8000
# 建立ing
kubectl apply -f ingress.yaml
6.2.1.2 使用域名測試
便于測試,我們就直接修改windows hosts檔案,不使用公網ip解析
将任意k8s節點ip配置至hosts檔案
[ip] hello.zy.com
[ip] demo.zy.com
浏覽器通路 hello.zy.com 轉發到 hello-server的service處理
浏覽器通路 nginx.zy.com 轉發到 nginx-demo的service處理
6.2.2 重寫路徑
上述Ingress的配置檔案中配置的是/後的所有請求會被轉發到對應的Service,我們也可以對轉發的路徑進行重寫,類似于GateWay/Nginx重寫路徑的方式
官網文檔:
https://kubernetes.github.io/ingress-nginx/examples/rewrite/kind: Ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2 # 第二個參數
name: rewrite
namespace: default
- host: rewrite.bar.com
- path: /something(/|$)(.*) # 通配符
pathType: Prefix
name: http-svc
port:
number: 80
6.2.3 流量控制
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limiting參考文檔增加如下annotations參數即可
# rps不能大于1 否則傳回503 預設503 可以修改
nginx.ingress.kubernetes.io/limit-rps: "1"
6.3 總結
通過ingress來回顧一下k8s安裝初始化主節點時的指令
kubeadm init \
--apiserver-advertise-address=172.16.0.208 \
--control-plane-endpoint=cluster-endpoint \
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=192.168.0.0/16
其中最後兩個參數
service-cidr
pod-network-cidr
此時就可以明白啥意思
- service-cidr 為service層的網絡範圍
- pod-network-cidr 為pod的網絡範圍
而此時也可以建立起k8s的網絡模型
7. 存儲
docker有将容器内的目錄挂載到主控端的能力,同樣的k8s也可以挂載,但是不能像docker一樣直接挂載到實體機的某個目錄
原因是 我們的pod/deploy存在故障轉移的能力,如果将某個pod的檔案挂載到固定的機器下,當我們的pod發生了故障轉移之後,再另外一個節點上重新啟動了一個pod時,就會發生找不到之前的資料的問題,如果我們的pod是一個存儲類的中間件 如mysql時,找不到之前的資料将是災難的
針對如上的情況,k8s将存儲抽象出來,作為一個單獨的存儲層,存儲層使用分布式的檔案存儲系統來實作,如NFS
NFS會把各個節點的檔案進行同步
通過分布式檔案存儲系統的特性,使我們的pod即時在别的節點重新開機也可以擷取到之前挂載在分布式檔案存儲系統的資料.
k8s對存儲是開放的,可以使用多種分布式檔案存儲系統.
7.1 NFS搭建
我們對k8s的三台伺服器搭建nfs
# 所有節點安裝nfs工具包
yum install -y nfs-utils
# 主節點初始化目錄
# 暴露nfs/data目錄,此目錄可以自定義
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
# 建立上述暴露目錄
mkdir -p /nfs/data
# 啟動
systemctl enable rpcbind --now
systemctl enable nfs-server --now
# 使nfs配置生效
exportfs -r
此時主節點已經初始化完畢,有一個/nfs/data的目錄暴露出來
# 從節點檢視主目錄 ip為主節點IP 此處可以使用區域網路ip 前提處于一個vpc下
showmount -e 172.31.0.4
# 從節點建立目錄
# 從節點目錄挂載 ip為主節點ip 目錄為上述建立目錄
mount -t nfs 172.31.0.4:/nfs/data /nfs/data
# 測試 在任意一節點新增/修改檔案,檢視另外兩個節點是否同步
echo "hello nfs server" > /nfs/data/test.txt
7.2 deployment挂載目錄
yaml配置如下
app: nginx-pv-demo
name: nginx-pv-demo
app: nginx-pv-demo
app: nginx-pv-demo
volumeMounts: # 挂載
- name: html # 挂載名稱
mountPath: /usr/share/nginx/html # 容器内要挂載的目錄
volumes: # 挂載配置
- name: html # 對應上面配置的name
nfs: # 此處可以改為其他fs
server: 172.31.0.4 # nfs ip
path: /nfs/data/nginx-pv # nfs路徑,需要先在nfs上建立出對應的路徑,否則會挂載失敗
kubectl apply -f [xx.yml]
這樣就将多個pod中的檔案挂載到nfs上,隻要nfs上的檔案修改,每個節點的檔案都會随之修改,并且容器内部的檔案也會随之修改(類似Docker).
7.3 挂載問題
上面的挂載存在兩個問題:
- pod删除,nfs裡的檔案不會随之删除
- 挂載時,無法指定某個pod挂載目錄的可使用空間
為了解決上面的問題,有兩種方案:
- PV&PVC
7.3.1 PV&PVC
PV(Persistent Volume): 持久卷 存儲資料
PVC(Persistent Volume Claim): 持久卷申明 說明持久卷的規格(大小)
PV和PVC都是k8s的資源類型
概述: PV就是資料存儲的地方,PVC就是描述PV大小的說明,一個pod建立的時候可以指定自己的PVC,通過PVC再綁定一個PV,這樣就達到上面pod的挂載問題
7.3.1.1 PV的使用
PV分為靜态配置設定和動态配置設定兩種
7.3.2.1 靜态配置設定
7.3.2.1.1 PV池
提前建立一個PV池,配置設定好各種規格的PV,當使用PVC綁定PV的時候會根據PVC中指定的大小來自适應(向上取大)擷取合适大小的PV.
如下yaml,建立pv池 pv.yml
kind: PersistentVolume
name: pv01-10m #pv名字
capacity:
storage: 10M # pv的大小
accessModes:
- ReadWriteMany
storageClassName: nfs
nfs:
path: /nfs/data/01 #nfs的檔案路徑
server: 172.31.0.4 #nfs的ip
name: pv02-1gi
storage: 1Gi
path: /nfs/data/02
server: 172.31.0.4
name: pv03-3gi
storage: 3Gi
path: /nfs/data/03
# 建立如上三個pv
kubectl apply -f pv.yml
# 檢視pv池
kubectl get pv
7.3.2.1.2 PVC建立
如下yaml,建立PVC pvc.yml
kind: PersistentVolumeClaim
name: nginx-pvc # 名字
resources:
requests:
storage: 200Mi # 需要的大小
storageClassName: nfs # 與pv中的保持一緻
# 建立PVC
kubectl apply -f pvc.yml
# 此時k8s就會選擇最合适大小的pv來與PVC綁定,如上文中PVC的大小 200M 那麼就會選擇 pv02-1gi 這個PV來綁定
kubectl get pvc
7.3.2.1.3 建立pod綁定PVC
如下yaml, pod-pvc.yml
app: nginx-deploy-pvc
name: nginx-deploy-pvc
app: nginx-deploy-pvc
app: nginx-deploy-pvc
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
persistentVolumeClaim:
claimName: nginx-pvc # 挂載PVC
# 建立使用PVC挂載的pod
kubectl apply -f pod-pvc.yml
7.3.2.2 動态配置設定
動态配置設定就是動态的增加PV并将其配置設定給pod使用
7.4 ConfigMap
配置集: 專為配置檔案挂載使用的資源類型
類似Docker中的-v 參數,但是将挂載的配置檔案抽象成了一種資源類型
底層儲存資料使用的是k8s的鍵值資料庫: ETCD
# 建立redis的配置檔案
echo appendonyl yes > redis.conf
# 建立配置集
kubectl create cm redis-conf --from-file=redis.conf
建立pod,cm.yml
name: redis
- name: redis
image: redis
command:
- redis-server
- "/redis-master/redis.conf" #指的是redis容器内部的位置
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /data
name: data
- mountPath: /redis-master
name: config # 對應下面volumes中的cm配置
volumes:
- name: data
emptyDir: {}
- name: config # 配置項
configMap:
name: redis-conf # cm的名稱
items:
- key: redis.conf # 檔案名
path: redis.conf # 挂載到redis中的檔案
7.5 Secret
類似于ConfigMap,但是是針對密鑰,令牌等東西存儲的
舉例: 建立pod拉取鏡像時可能需要私有鏡像倉庫的密鑰,此時通過Secret就可以做到一次配置,多次使用的效果
##指令格式
kubectl create secret docker-registry [secret名] \
--docker-server=<你的鏡像倉庫伺服器> \
--docker-username=<你的使用者名> \
--docker-password=<你的密碼> \
--docker-email=<你的郵箱位址>
name: private-nginx
- name: private-nginx
image: zy/mynginx:v1.0
imagePullSecrets:
- name: zy-docker # 建立的secret名稱
8 總結
通過上面的學習,簡單的了解了k8s中的大部分資源類型及使用方式,可以通過指令行的方式來操作k8s底層的各種東西
熟悉了k8s的網絡模型,知道k8s叢集中服務流量的分發規則.
學無止境!