K8s,Kubernetes 的縮寫,起源於希臘語意爲舵手、領航員。是一種容器編排工具,於14.7被Docker收購,同類產品有docker swarm:
k8s master 節點:
master節點:k8s集羣的管理節點,提供集羣資源數據訪問入口,負責運行Api Server進程、Scheduler服務進程、Controller Manager服務進程、etcd存儲服務,負責關聯工作節點 Node。
k8s node 節點:
node節點:k8s集羣中運行Pod的服務節點,是k8s集羣最小操作單元,用於承載被分配Pod的運行(Pod宿主機); 關聯Master管理節點,擁有名稱、IP、系統資源信息; 負責運行:docker eninge服務、守護進程kunelet、負載均衡器kube-proxy;
每個Node節點都運行一組關鍵進程: Docker Engine:負責本機容器的創建和管理工作; kubelet:負責對 Pod對應的容器的創建、啓停等任務;(Node節點可以在運行時動態增加到K8s集羣中) kube-proxy:實現K8s Service的通信與負載均衡機制的重要組件;
K8s【推薦的、默認的】Node管理方式:kubelet會向master註冊自己,kubelet進程會定時向Master彙報自身情報(如操作系統、Docker版本、CPU和內存,以及有哪些Pod在運行等等),這樣Master可以獲知每個Node節點的資源使用情況,並實現高效均衡的資源調度策略。
Pod:是k8s最小的調度單位,包含一/多個container,內部共享一個namespace。
什麼是控制器?
K8s 中內建了很多 Controller 控制器,這些相當於一個狀態機,用來控制 Pod 的具體狀態和行爲。
ReplicationController 和 ReplicaSet Deployment(RC、RS)
Deployment
DaemonSet
StateFulSet
Job/CronJob
Horizontal Pod Autoscaling
ReplicationController 和 ReplicaSet:
ReplicationController(RC)用來確保容器應用的副本數始終保持在用戶定義的副本數,即如果有容器異常退出,會自動創建新的 Pod 來替代;而如果異常多出來的容器也會自動回收;在新版本的 Kubernetes 中建議使用 ReplicaSet 來取代 ReplicationController 。ReplicaSet 跟 ReplicationController 沒有本質的不同,只是名字不一樣,並且 ReplicaSet 支持集合式的 selector;
RS/RC 與 Deployment 的關聯
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: php-redis
image: nginx:1.7.9
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
RS 與 Deployment 的關聯
Deployment:
Deployment,是常見的K8s對象類型,提供了對 Pod 和 ReplicaSet 的聲明式定義 (declarative) 方法和管理方式,每個Deployment對應集羣的一次部署,常用來創建 ReplicaSet 和 Pod,解決了 ReplicaSet 更新的諸多問題,用來替代以前的ReplicationController來方便的管理應用。(部署一個新的微服務往往不會直接在集羣中使用 ReplicaSet,因爲ReplicaSet功能不夠強大,不支持一些常見的更新、擴容、縮容運維操作,引入 Deployment 就是爲了支持這些複雜操作。)
在 K8s 集羣中創建 Deployment 對象時,會創建 Deployment 資源、ReplicaSet、三個Pod對象,組成以下的拓撲結構:
拓撲結構中的子節點都是穩定的,任意節點刪除都會被 K8s 控制器重啓。
每個 Deployment 都會和它的依賴組成以下的拓撲結構,在這個拓撲結構中的子節點都是『穩定』的,任意節點的刪除都會被 Kubernetes 的控制器重啓。
DeploymentController:負責管理 K8s 集羣中的所有 Deployment 對象,實現 Deployment 對象的各種操作:同步、擴容、重新創建、滾動更新、回滾、暫定恢復、刪除。
Deployment:典型的應用場景包括: ·定義 Deployment 來創建 Pod 和 ReplicaSet; ·滾動升級和回滾應用 ·擴容和縮容; ·暫停和繼續 Deployment;
1.部署一個簡單的 Nginx 應用
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record
## --record 參數可以記錄命令,我們可以很方便的查看每次revision的變化
2.擴容
kubectl scale deployment nginx-deployment --replicas 10
3.爲 Deployment 設置自動擴展
## (若集羣支持 horizontal pod autoscaling)
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
4.更新鏡像
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
5.回滾
kubectl rollout undo deployment/nginx-deployment
集羣service管理包括:
- 網絡代理模式
- 服務代理
- 服務發現
- 發佈服務
概述
Service 是對一組提供相同功能的 Pods 的抽象,併爲它們提供一個統一的入口。
藉助 Service,應用可以方便的實現服務發現與負載均衡,並實現應用的零宕機升級。
Service 通過標籤來選取服務後端,一般配合 Replication Controller 或者 Deployment 來保證後端容器的正常運行。這些匹配標籤的 Pod IP 和端口列表組成 endpoints,由 kube-proxy 負責將服務 IP 負載均衡到這些 endpoints 上。
Service 有四種類型:
- ClusterIP:默認類型,自動分配一個僅 cluster 內部可以訪問的虛擬 IP
- NodePort:在 ClusterIP 基礎上爲 Service 在每臺機器上綁定一個端口,這樣就可以通過 NodeIP:NodePort 來訪問該服務。如果 kube-proxy 設置了 –nodeport-addresses=10.240.0.0/16(v1.10 支持),那麼僅該 NodePort 僅對設置在範圍內的 IP 有效。
- LoadBalancer:在 NodePort 的基礎上,藉助 cloud provider 創建一個外部的負載均衡器,並將請求轉發到 :NodePort
- ExternalName:將服務通過 DNS CNAME 記錄方式轉發到指定的域名(通過 spec.externlName 設定)。需要 kube-dns 版本在 1.7 以上。
另外,也可以將已有的服務以 Service 的形式加入到 Kubernetes 集羣中來,只需要在創建 Service 的時候不指定 Label selector,而是在 Service 創建好後手動爲其添加 endpoint。
K8s 的 Service
K8s 中的 Pod 是有生命週期的對象,隨時都有可能由於集羣的狀態變化而被銷燬和創建,此時要面臨的問題:當一些 Pod 需要爲其它 Pod 提供服務時,如何提供同一功能服務的一組 Pod 建立一個抽象並追蹤這組服務中節點的健康狀態。 這個抽象在 K8s 集羣中就是 Service,每個K8s的 Service 都是一組Pod的邏輯集合和訪問方式的抽象,可以把 Service 加上的一組 Pod 稱爲一個微服務。
K8s Service 定義了這樣一個抽象:一個Pod的邏輯分組,一種夠可以訪問它們的策略 - - 通常稱爲微服務。 這一組Pod能夠被Service訪問到,通常是通過Label Selector。
K8s 中 Service 實現原理: 1.如何處理服務的創建;2.如何轉發來自節點內部和外部的流量;
創建服務:
在 K8s 中創建一個新的 Service 對象需要兩大模塊同時協作:控制器 與 kube-proxy。 控制器,需要在每次客戶端創建新的 Service 對象時生成其他用於暴露一組 Pod 的 K8s 對象,即 Endpoint 對象; kube-proxy,運行在 K8s 集羣中的每一個節點上,會根據 Service 和 Endpoint 的變動改變節點上 iptables 或 ipvs 中保存的規則。
ServiceController 在 Service 對象變動時發生了什麼事情:
網絡代理模式
擁有三種代理模式:userspace、iptables和ipvs。
現在默認使用iptables,在1.8版本之後增加了ipvs功能。
早期代理的方式
client先請求serviceip,經由iptables轉發到kube-proxy上之後再轉發到pod上去。這種方式效率比較低。
當前iptables代理方式
client請求serviceip後會直接轉發到pod上。這種模式性能會高很多。kube-proxy就會負責將pod地址生成在node節點iptables規則中。
ipvs代理方式
這種方式是通過內核模塊ipvs實現轉發,這種效率更高。
服務代理
創建yaml配置文件
創建一個service.yaml
文件:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
在selector字段中指定了爲哪一個標籤的app進行負載均衡。ports字段指定了暴露的端口,每一個- name指定一組端口,targetPort爲目標容器的端口。
創建service
kubectl create -f service.yaml
查看service
然後通過命令
kubectl get svc
查看創建的service
通過命令kubectl get endpoints my-service
查看創建的service當後端代理的pod的ip
並沒有給它分配pod所以代理的ip爲空。
配置service代理pod
首先查看了一下當前有哪些pod:
現在想讓剛創建的service代理nginx-pod
修改service.yaml
文件中app:MyApp
爲app:nginx
,這樣就可以匹配到標籤爲app=nginx的pod了。
然後重新生效這個service:
kubectl replace -f service.yaml --force
pod已經連接上了。
通過clusterip訪問pod
首先查看下service的clusterip:
然後在節點上可以通過這個ip和端口的方式訪問pod上的應用:
service服務發現
服務發現支持Service環境變量和DNS兩種模式
環境變量
當一個pod運行到node,kubelet會爲每個容器添加一組環境變量,Pod容器中程序就可以使用這些環境變量發現Service。
環境變量名格式如下:
{SVCNAME}_SERVICE_HOST
{SVCNAME}_SERVICE_PORT
其中服務名和端口名轉爲大寫,連字符轉換爲下劃線。查看方法是進入pod中輸入
env
查看環境變量,在程序中調用這個變量就可以訪問這個組件。
限制:
1)Pod和Service的創建順序是有要求的,Service必須在Pod創建之前被創建,否則環境變量不會設置到Pod中。
2)Pod只能獲取同Namespace中的Service環境變量。
DNS
DNS服務監視Kubernetes API,爲每一個Service創建DNS記錄用於域名解析。這樣Pod中就可以通過DNS域名獲取Service的訪問地址。
工作原理
kube-dns用於記錄集羣svc的域名解析相關記錄,dnsmasq主要用於dns緩存。
yaml文件中爲kube-dns指定了一個固定的ip,所以需要注意修改node節點kubelet配置的kube-dns是否爲這個ip(我之前配置的不是,所以要修改)
集羣應用發佈
服務類型
ClusterIP:
分配一個內部集羣IP地址,只能在集羣內部訪問(同Namespace內的Pod),默認ServiceType。
NodePort:
分配一個內部集羣IP地址,並在每個節點上啓用一個端口來暴露服務,可以在集羣外部訪問。
訪問地址:<NodeIP>:<NodePort>
LoadBalancer:
分配一個內部集羣IP地址,並在每個節點上啓用一個端口來暴露服務。
除此之外,Kubernetes會請求底層雲平臺上的負載均衡器,將每個Node([NodeIP]:[NodePort])作爲後端添加進去。