一.導言
隨著容器技術的發展,軟體界對容器管理的需求越來越迫切,于是出現了一些kubernetes(即k8s),docker swarm 等容器管理軟體,同時k8s等服務編排軟體也讓微服務變得可行,快速擴容縮容,自動處理網路配置等特性也讓k8s如火如荼,
k8s能做什么?
- 服務發現和負載均衡,使用dns或者ip對外暴露容器服務,并提供負載均衡
- 存盤管理,多種存盤選擇
- 擬態擴容縮容,根據需求擴容,縮容,并且k8s會盡力達到desired state
- 自動裝箱,比如配置每個容器能使用的CPU和RAM資源,k8s將容器分配到合適的節點以最大化利用系統資源
- 自動處理故障,當容器失效時,能快速處理,并且不會對客戶端有影響
- 配置和秘鑰管理
二.k8s架構及相關概念

control plane:控制臺
kube-apiserver: k8s的核心api服務,一般需要做橫向擴展
etcd: 提供一致性和高可用的的鍵值存盤,k8s用來存盤集群資料,etcd是一款用go語言撰寫的分布式kv存盤,基于raft演算法,能提供更穩定的高負載穩定讀寫能力,
kube-scheduler: 為未分配節點的pod尋找合適的節點
kube-controller-manager: 包括以下controller
- ??node controller: 監視節點下線
- ??job-controller: 監視Job 運行狀況
- ??EndpointSlice controller: 即端點串列控制器,為Service 和 pod 提供連接
cloud-controller-manager: 云服務控制管理
node:節點,對應物理機或者虛擬機
kubelet: 運行在節點中的agent,確保容器運行在pod中
kube-proxy: 運行在節點中的網路代理,為Servcie提供支持

pod: k8s 抽象出來的的管理單元,包括一個或者多個容器,共享存盤,網路,埠等資源
volume: 存盤單元抽象
container:容器,比如docker

Deployment:部署,描述部署的容器,復制等資訊,一個典型的Deployment如下
apiVersion: apps/v1 (版本)
kind: Deployment (物件型別)
metadata: (元資料)
name: nginx-deployment (name, UIDs)
spec: (目標狀態)
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels: (labels and selector)
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Service:基于pod創建對外或者對內網路服務
三.構建無狀態服務
無狀態服務:服務不依賴自身的狀態,實體的狀態資料可以維護在記憶體中,
構建步驟如下:
???0.筆者這里使用minikube進行測驗,先啟動minikube???
minikube start
minikube dashboard # 啟動后臺管理界面

1.執行部署
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: load-balancer-example
name: hello-world
spec:
replicas: 5
selector:
matchLabels:
app.kubernetes.io/name: load-balancer-example
template:
metadata:
labels:
app.kubernetes.io/name: load-balancer-example
spec:
containers:
- image: gcr.io/google-samples/node-hello:1.0
name: hello-world
ports:
- containerPort: 8080
kubectl apply -f https://k8s.io/examples/service/load-balancer-example.yaml
2.查看部署資訊
kubectl get deployments hello-world
kubectl describe deployments hello-world
NAME READY UP-TO-DATE AVAILABLE AGE
hello-world 5/5 5 5 12m
3.查看副本集
這里我們創建了五個副本
kubectl get replicasets
kubectl describe replicasets
NAME DESIRED CURRENT READY AGE
hello-world-644f58f5f4 5 5 5 12m
4.創建Service暴露部署
kubectl expose deployment hello-world --type=LoadBalancer --name=my-service # LoadBalancer表示使用負載均衡的方式
5.查看Service
kubectl get services my-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service LoadBalancer 10.102.184.247 <pending> 8080:31755/TCP 3s
6.查看Service詳細資訊
kubectl describe services my-service
Name: my-service
Namespace: default
Labels: app.kubernetes.io/name=load-balancer-example
Annotations: <none>
Selector: app.kubernetes.io/name=load-balancer-example
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.102.184.247
IPs: 10.102.184.247
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31755/TCP
Endpoints: 10.244.0.87:8080,10.244.0.88:8080,10.244.0.89:8080 + 2 more... # 端點
Session Affinity: None
External Traffic Policy: Cluster
Events: <none
7.查看pod對應的端點
kubectl get pods --output=wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-world-644f58f5f4-2slc4 1/1 Running 0 8m46s 10.244.0.91 minikube <none> <none>
hello-world-644f58f5f4-jjf6w 1/1 Running 0 8m46s 10.244.0.88 minikube <none> <none>
hello-world-644f58f5f4-mzd5x 1/1 Running 0 8m46s 10.244.0.90 minikube <none> <none>
hello-world-644f58f5f4-t6cmj 1/1 Running 0 8m46s 10.244.0.89 minikube <none> <none>
hello-world-644f58f5f4-xlvtr 1/1 Running 0 8m46s 10.244.0.87 minikube <none> <none>
8.訪問服務
使用 curl http://<external-ip>:<port> 進行訪問,
<external-ip> 這里指代LoadBalancer Ingress地址,許多廠商開發了各種網關和k8s集成,
<port> 指代Service暴露的埠,
如果是minikube,直接啟動即可
? k8s minikube service my-service
|-----------|------------|-------------|---------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|------------|-------------|---------------------------|
| default | my-service | 8080 | http://192.168.49.2:31755 |
|-----------|------------|-------------|---------------------------|
?? Starting tunnel for service my-service.
|-----------|------------|-------------|------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|------------|-------------|------------------------|
| default | my-service | | http://127.0.0.1:53820 |
|-----------|------------|-------------|------------------------|
?? 正通過默認瀏覽器打開服務 default/my-service...
? Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
三.構建有狀態服務
有狀態服務 · 服務本身依賴或者存在區域的狀態資料,這些資料需要自身持久化或者可以通過其他節點恢復,
??1.添加自定義組態檔,存盤mysql密碼
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: mysql-pass
literals:
- password=YOUR_PASSWORD
EOF
??2.撰寫部署mysql 和 WordPress檔案
??mysql部署檔案 application/wordpress/mysql-deployment.yaml:
apiVersion: v1
kind: Service # 部署服務
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
ports:
- port: 3306
selector:
app: wordpress
tier: mysql
clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim # 指定持久化存盤
metadata:
name: mysql-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment # mysql部署
metadata:
name: wordpress-mysql
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass # 使用之前定義的秘鑰
key: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql # 將該路徑的存盤映射到mysql-pv-claim
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
WordPress 部署檔案:application/wordpress/wordpress-deployment.yaml
apiVersion: v1
kind: Service # 暴露服務
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
selector:
app: wordpress
tier: frontend
type: LoadBalancer
---
apiVersion: v1
kind: PersistentVolumeClaim # 指定持久化存盤
metadata:
name: wp-pv-claim
labels:
app: wordpress
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: frontend
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: frontend
spec:
containers:
- image: wordpress:4.8-apache
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: wordpress-mysql
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html # 存盤路徑映射
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: wp-pv-claim
??將以上檔案寫入到kustomization.yaml中
cat <<EOF >>./kustomization.yaml
resources:
- mysql-deployment.yaml
- wordpress-deployment.yaml
EOF
??3.執行部署
kubectl apply -k ./ #確保上述檔案在當前目錄下
??查看秘鑰:
? k8s kubectl get secrets
NAME TYPE DATA AGE
mysql-pass-kkcc2b926b Opaque 1 3d22h
??查看PersistentVolume:
? k8s kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-pv-claim Bound pvc-456c2492-32bd-4d15-9753-c3ad1034c38f 20Gi RWO standard 3d22h
wp-pv-claim Bound pvc-78d63fcd-9c75-4320-97d6-4498d2915707 20Gi RWO standard 3d22h
??查看pod:
? k8s kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7fdfc976b9-4tx6d 1/1 Running 0 16s
wordpress-mysql-6987d65455-f44dz 1/1 Running 0 16s
??查看Service:
? k8s kubectl get services wordpress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress LoadBalancer 10.101.95.45 <pending> 80:31798/TCP 3d22h
??運行服務,訪問 http://127.0.0.1:52503/ 即可看到服務地址
? k8s minikube service wordpress --url
http://127.0.0.1:52503
? Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
四.網路模型
k8s給集群里面的每個pod分配集群內 IP地址,這個ip僅僅限制在集群內部使用,
- pod之間可以互相訪問,不依賴NAT(Network Address Translation)
- 節點上的agent(kubelet)可以和其他節點上的pod互相訪問
"IP-per-pod" model:同一個pod里面的容器共享網路命名空間,即共享ip地址,mac地址等等,這意味著pod里面的容器可以使用localhost互相訪問對方的埠,同時要求容器內的埠不能互相沖突,
- pod里面的容器使用loopback 互相訪問
- pod之間通過cluster-wide IP 互相訪問
- 可以使用Service暴露服務,方便從集群外部訪問,許多廠商開發了各類網關,以支持http 應用,網站,和APIs
五.最佳實踐
- 所有組態檔,比如Deployment, Service 應該進行版本控制,推送到git倉庫
- 先創建Service,然后再創建Deployment,這樣pod就能獲得Service的相關資訊
- 使用DNS server插件
- 不要為pod指定地址埠
- 使用語意化的標簽來進行管理應用或者部署,比如{ app.kubernetes.io/name: MyApp, tier: frontend, phase: test, deployment: v3 }
六.CRI 之 docker engine
??1.容器發展史

??2.docker 架構和底層技術

??docker 使用go語言撰寫,使用namespaces 來隔離workspace (container),當我們創建一個container,docker創建一系列的namespace來進行隔離,
??docker 使用cgroup來進行資源控制,
??3.docker 中的一些關鍵概念
- ??每個container只包含一個行程
- ??可以使用docker compose,組合多個container進行管理
- ??docker提供兩種持久化方式,volumes(使用卷的方式), bind mounts(掛載)
- ??image是分層的,并且可以快取
- ??使用Multi-stage builds,只保留最后一階段的輸出
??4.docker最佳實踐
??image:
-
- 選擇合適的base image
- 使用Multi-stage builds,可以讓image變得更小
- 在共享組件的基礎上構建image
- 對image打標簽
- 在正式環境使用volumes存盤,在開發環境使用bind mounts存盤
- 使用CI/CD開發
??dockerfile:
-
- 創建無狀態的container
- 使用stdin 創建 Dockerfile
- 使用.dockerignore排除檔案
- 使用Multi-stage builds
- 不要安裝不必要的包
- 解耦應用,每個container只運行一個行程
- 減少layer的數量??
七.總結
本文介紹了k8s的核心架構,和重要相關概念,并且演示了兩個典型用例,同時介紹了docker的相關知識,
八.參考
https://docs.docker.com/get-started/
https://kubernetes.io/docs/home/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/551566.html
標籤:其他
上一篇:dqwwn1-服務器弱點
下一篇:返回列表
