分享的內容包括
- k8s demo部署示例
- k8s基本架構和原理
- k8s資源對象
- k8s網絡模型
- 總結
k8s就像圖中的貨船,管理各類集裝箱(容器)前端
一. k8s demo部署示例
說明
1. 宿主機上如何運行
- mvn編譯代碼打成jar包
- 執行
java -jar k8s-demo.jar &
- 瀏覽器中輸入 http://10.1.69.101:8080/hello 地址訪問服務
2. Docker容器上如何運行
- mvn編譯代碼打成jar包
- 將jar包打成docker鏡像
- 執行
docker run --name k8s-demo -d -p 8080:8080 k8s-demo:0.0.1-SNAPSHOT
- 瀏覽器中輸入 http://10.1.69.101:8080/hello 地址訪問服務
3. 在k8s中如何運行
這一步大體感覺一下yaml的樣子,不須要關心腳本的細節,後面介紹資源時會細說。只須要有個大致的印象,部署一個k8s服務的基本流程。java
- mvn編譯代碼打成jar包
- 將jar包打成docker鏡像
- 構建一個運行服務的yaml文件
- 執行kubectl apply -f k8s-demo.yaml
- 瀏覽器中輸入 www.k8s-demo.com/hello 地址訪問服務
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: k8s-demo
namespace: spring-test
spec:
replicas: 3
template:
metadata:
labels:
app: k8s-demo
spec:
containers:
- name: k8s-demo
image: k8s-demo:0.0.1-SNAPSHOT
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: k8s-demo
namespace: spring-test
spec:
type: NodePort
selector:
app: k8s-demo
ports:
- protocol: TCP
port: 8888
targetPort: 8080
nodePort: 30003
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: k8s-demo
namespace: spring-test
spec:
rules:
- host: www.k8s-demo.com
http:
paths:
- path: /hello
backend:
serviceName: k8s-demo
servicePort: 8888
複製代碼
4. 總結三種部署方式
爲了減小部署複雜度,代碼並無使用redis,只是實例圖增長了redisnode
5. 流程愈來愈複雜,爲何不直接部署在宿主機?
5.1 容器比宿主機優點在哪?
- 可移植性:容器提供了運行應用程序的基本包裝,能夠在任何支持容器的雲上部署
- 高效率:啓動一個容器只需一個鏡像,且啓動時間很是短
- 隔離性:宿主機上每每安裝不少服務,且各自依賴不同。而一個容器只跑一個服務
- 版本控制:方便追溯不一樣版本差別,方便快速回滾,只需替換鏡像版本,無需宿主機上一套複雜的流程
- 低成本:小巧輕便,不須要像宿主機或虛擬機同樣佔用不少資源
5.2 k8s的出現又解決了容器的什麼問題?
- 自動編排調度:大量容器劇增後,如何管理、如何調度的問題
- 分佈式解決方案:節點可水平擴展,容器可方便擴縮容
- 自愈能力:故障自動發現,並進行自我修復
咱們說容器實現了單個應用程序的基本包裝實現可移植。上圖中,宿主機部署的方式若是加上一個nginx作反向代理,就和k8s中ingress的部署方式是同樣的。也就是k8s實現了整套分佈式應用的可移植linux
二. 基本架構和原理
1. Master節點的組件
apiServer
- 提供資源操做的惟一入口,提供api註冊、發現、認證、訪問控制等功能
etcd
controller-manager
- 負責維護機器狀態,好比:自動擴容、故障檢查、滾動更新
- 實現集羣自動化的關鍵組件
scheduler
- 負責資源調度
- 將未分配節點的pod調度到合適的節點上
2. Node節點的組件
kubelet
- 負責容器生命週期管理,好比:建立、刪除
- 同時負責Volume,網絡的管理
kube-proxy
Container Runtime
- 容器運行環境
- 默認是Docker,同時還支持其餘容器引擎
三. 資源對象
概述
- k8s中大部分概念,如Node,Pod,Service均可以看作一種資源對象
- 資源的描述:yaml文件或json文件
- 資源的操做:對象能夠經過kubectl(或者api)執行增、刪、改、查
- 資源的存儲:信息在etcd中持久化
k8s經過對比資源的「實際狀態」和etcd中的「指望狀態」,實現自動化控制nginx
1. Pod
- Pod是k8s中最重要最基本的資源
- pod是在容器以外又封裝的一層概念
- pod是容器調度的基本單元(不是docker容器)
- 每一個pod包含一個特殊的根容器:Pause容器,和一個或多個業務容器
- 每一個pod有惟一的ip,pod內的容器可經過localhost通信
爲何要新增pod這個概念?redis
- 一組容器做爲一個單元,很難判斷總體狀態,以及對總體進行管控。新增業務無關的pause容器,用於管控總體
- 簡化了關聯容器通訊和共享的問題
2. Deployment
- 實現Pod自動編排:建立、刪除、擴容、縮容
- 經過replicas控制pod數量,template控制要建立的pod的模板
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: k8s-demo
namespace: spring-test
spec:
replicas: 3
template:
metadata:
labels:
app: k8s-demo
spec:
containers:
- name: k8s-demo
image: k8s-demo:0.0.1-SNAPSHOT
ports:
- containerPort: 8080
複製代碼
3. Service
- pod異常時,可能會被調度到另外一臺機器,致使pod的ip改變,使用ip訪問服務不可靠
3.1概述
- k8s裏最核心的資源之一,相似微服務架構中的「微服務」
- 前端應用經過入口地址訪問服務,服務經過label對接到後端的pod,即便pod的ip變了
- kube-proxy負責把service請求轉發到後端,並作負載均衡
- service整個生命週期內,ClusterIp不會變,對外提供的服務地址也就不會變
apiVersion: v1
kind: Service
metadata:
name: k8s-demo
namespace: spring-test
spec:
type: NodePort
selector:
app: k8s-demo
ports:
- protocol: TCP
port: 8888
targetPort: 8080
nodePort: 30003
複製代碼
4. Ingress
service提供了ip:port的訪問方式,即工做在tcp/ip層,而http服務須要將不一樣的url對應到不一樣的後端服務,service是沒法實現這一功能的。spring
- Ingress提供http層的負載分發功能
- Ingress能夠實現不一樣的請求,分發到不一樣的後端服務
- Ingress定義後,須要結合Ingress Controller,才能造成完整的功能
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: k8s-demo
namespace: spring-test
spec:
rules:
- host: www.k8s-demo.com
http:
paths:
- path: /hello
backend:
serviceName: k8s-demo
servicePort: 8888
複製代碼
4.1 Ingress Controller定義
- 可使用公有云提供的Ingress Controller
- 也可使用google提供的Ingress Controller,以pod形式運行,功能以下:
- 監聽apiserver,獲取ingress的定義
- 基於ingress定義,生成nginx的配置文件的內容
- 執行nginx -s reload,從新加載配置
4.2 Ingress定義
- 建立類型爲Ingress的yaml文件
- 配置spec.rules,指定hostname中url和service的對應關係
四. k8s網絡模型
前面hello world程序中,對於如何訪問到服務,有必要了解一下k8s的網絡模型,在這以前先介紹docker的網絡模型docker
1. Docker網絡模型
docker網絡模型數據庫
- docker第一次啓動時,會建立虛擬網橋docker0
- 爲docker0分配一個子網
- docker建立每一個容器時,會建立veth設備對,一端關聯到網橋上,另外一端使用linux的網絡命名空間技術鏈接到容器內,並給容器內eth0設備分配一個ip地址
2. Docker網絡的侷限性
- Docker網絡模型沒有考慮到多主機互聯的網絡解決方案,崇尚簡單爲美
- 同一機器內的容器之間能夠直接通信,可是不一樣機器之間的容器沒法通信
- 爲了跨節點通信,必須在主機的地址上分配端口,經過端口路由或代理到容器
- 分配和管理容器特別困難,特別是水平擴展時
3. k8s網絡模型概述
3.1 k8s網絡模型的原則:
- 每一個pod都擁有惟一個獨立的ip地址,稱IP-Per-Pod模型
- 全部pod都在一個可連通的網絡環境中
- 不論是否在同一個node,均可以經過ip直接通信
- pod被看做一臺獨立的物理機或虛擬機
目前原生docker和kubernetes還不能打通多節點容器與容器的通信,要支持該模型,必須依靠第三方網絡插件實現,好比:flanneljson
3.2 設計這個原則的緣由:
- 用戶不須要額外考慮如何創建pod之間的鏈接
- 用戶不須要考慮將容器端口映射到主機端口的問題
- 能夠兼容過去跑在宿主機和KVM的應用
3.3 IP-Per-Pod與Docker端口映射的區別
- docker端口映射到宿主機會引入端口管理的複雜性
- docker最終被訪問的ip和端口,與提供的不一致,引發配置的複雜性
4. k8s網絡模型詳解
k8s網絡實現
4.1 容器與容器的通信
- 同一個容器的pod直接共享同一個linux協議棧
- 就像在同一臺機器上,可經過localhost訪問
- 可類比一個物理機上不一樣應用程序的狀況
4.2 pod與pod的通信
同一Node內的pod之間通信
- 同一Node內的pod都是經過veth鏈接在同一個docker0網橋上,地址段相同,因此能夠直接通信
不一樣Node的pod之間通信
- docker0網段與宿主機不在同一個網段,因此不一樣pod之間的pod不能直接通信
- 不一樣node之間通信只能經過宿主機物理網卡
- 前面說過k8s網絡模型須要不一樣的pod之間能通信,因此ip不能重複,這就要求k8s部署時要規劃好docker0的網段
- 同時,要記錄每一個pod的ip地址掛在哪一個具體的node上
- 爲了達到這個目的,有不少開源軟件加強了docker和k8s的網絡
4. 開源網絡組件Flannel
4.1 實現的功能
- 協助k8s給每一個Node上的docker容器分配互不衝突的ip地址
- 能在這些ip地址之間創建覆蓋網絡(Overlay Network),將數據傳遞到目標容器
4.2 底層原理
- Flannel建立名爲flannel0的網橋
- flannel0網橋一端鏈接docker0網橋,另外一端鏈接flanneld進程
- flanneld進程一端鏈接etcd,利用etcd管理分配的ip地址資源,同時監控pod地址,創建pod節點路由表
- flanneld進程一端鏈接docker0和物理網絡,配合路由表,完成數據包投遞,完成pod之間通信
4.3 缺點
- 引入多個網絡組件,帶來網絡時延和損耗
- 默認使用udp做爲底層傳輸協議,具備不可靠性
五. 總結
- 本文先經過一個demo,部署在不一樣的環境中,直觀感覺瞭如何使用k8s。這個過程咱們須要思考k8s誕生解決了什麼問題?核心的提供了一個平臺,主要負責容器的自動調度和編排
- 對k8s有直觀感覺後,介紹了下k8s的基本架構。各個組件是如何交互的,在使用k8s過程當中不斷回想架構圖,能加深對k8s的瞭解
- 掌握了基本架構後,想要將服務部署到k8s中,須要對經常使用的資源對象有必定了解,所以接着介紹了主要的資源對象。k8s中其餘的資源對象可類比學習
- 當你把一個服務部署到k8s以後,如何作驗證呢,如何暴露你的服務呢?須要對k8s的網絡模型有必定了解,才能真正掌握它暴露服務的方式。所以最後部分着重介紹了k8s的網絡模型
參考