DevOps:容器篇

1. docker

Docker 是一個應用容器引擎,說簡單點就是將你的應用里三層外三層打包成一個鏡像,然后用一條命令將鏡像跑起來,本質(zhì)上它就是一個進程而已,只不過使用了一些隔離技術(shù)(cgroups 、namespace、rootfs、setns)讓其“隱藏”起來,從而感覺上它是一個容器,而且是一個獨立的系統(tǒng)。docker和虛擬機有著本質(zhì)的區(qū)別,虛擬機會占用更多的物理資源,虛擬機比較笨重,重建或釋放都比較費時。例如有個1000平的大房子,如果隔成10個甚至20個小房間都沒問題,而且可以隨時拆掉再隔;但如果在里面蓋房子的話,可能蓋5間就不錯了。


image.png

用以下命令揭示“容器”的真實身份

# 查看 a776ea6f142d2819 容器的進程號
[root@node1 ~]# docker inspect --format '{{ .State.Pid }}'  a776ea6f142d
2819
# 發(fā)現(xiàn)容器在宿主機中進程
[root@node1 ~]# ps -aux |grep 2819
root     22819  0.0  0.0 109096  6604 ?        Sl   Apr28   3:40 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/a2b9a823d8451eaa32c92330599e7167dc69b46930746b536ec018ca91e30914 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup

2. kubernetes

Kubernetes是Google開源的一個容器編排引擎,隨著docker的流行,當運行數(shù)百、數(shù)千個容器時,人們就不得不考慮一個問題,如何讓容器更高效的運行、以及如何在分布式環(huán)境下運行容器等。這是k8s就橫空出世了,它簡化了大規(guī)模部署的容器管理問題,而在k8s流行之前,docker公司就有三劍客的另外兩個產(chǎn)品:docker-compose、swarm。swarm是docker公司主推的容器編排工具,也是和k8s一決高下的產(chǎn)品,但最終用戶用腳投票,k8s以完勝收場,這里不得不提的一個大牛就是Tower(高塔),作為k8s的布道師功不可沒。

一、架構(gòu)

image.png

(1) kubectl

集群的客戶端命令行工具,請求apiserver的rest接口,查看和維護集群,kubectl需要一個配置文件: kubeconfig,此文件包含用戶、集群上下文、命名空間、認證機制信息等,kubectl可以同時管理多個集群,在請求apiserver需要認證信息。kubectl可以同時管理多個集群

(2) kube-apiserver

API Server提供了資源對象的唯一操作入口,其他所有組件都必須通過它提供的API來操作資源數(shù)據(jù),只有API Server與存儲通信,其他模塊通過API Server訪問集群狀態(tài)。以RESTFul接口方式提供給外部客戶和內(nèi)部組件進行同一調(diào)用。

(3) kube-controller-manager

實現(xiàn)集群故障檢測和恢復的自動化工作,負責執(zhí)行各種控制器,主要有:

  • endpoint-controller:定期刷新service和pod(關(guān)聯(lián)信息由endpoint對象維護)的關(guān)聯(lián)關(guān)系,保證service到pod的映射總是最新的。

  • replication-controller:定期檢查replicationController(新版叫ReplicaSet)中配置的pod數(shù)量和實際運行數(shù)量是否一致,如果不一致會自動啟動或停止pod。

(4) kube-scheduler

Scheduler收集和分析當前Kubernetes集群中所有Work節(jié)點的資源(內(nèi)存、CPU)負載情況,然后分發(fā)Pod到集群中可用的節(jié)點上,并實時監(jiān)測集群中未分發(fā)和已分發(fā)的所有運行的Pod,將已分發(fā)的pod信息寫回到API Server。為了避免頻繁查詢,Scheduler會緩存一份最新的信息在本地。

(5) etcd

和Zookeeper類似,負責存儲各個組件的共享數(shù)據(jù),保證集群高可用。

(6) kube-proxy

負責接收并轉(zhuǎn)發(fā)請求。Kube-proxy的核心功能是將到達Service的訪問請求轉(zhuǎn)發(fā)到后臺的某個具體的Pod。無論是通過ClusterIP+Port的方式還是NodeIP+NodePort的方式訪問Service,最終都會被節(jié)點的Iptables規(guī)則(新版本是通過LVS轉(zhuǎn)發(fā))重定向到Kube-proxy監(jiān)聽服務代理端口,該代理端口實際上就是SocketServer在本地隨機打開的一個端口,SocketServer是Kube-proxy為每一個服務都會創(chuàng)建的“服務代理對象”的一部分。當Kube-proxy監(jiān)聽到Service的訪問請求后,它會找到最適合的Endpoints,然后將請求轉(zhuǎn)發(fā)過去。具體的路由選擇依據(jù)Round Robin算法及Service的Session會話保持這兩個特性。

(7) kubelet

運行在每個work節(jié)點上,作為agent,負責分配該Node上的Pods任務、啟動Pod、管理容器、周期性獲取容器狀態(tài)等,反饋給kube-apiserver。注意:kubelet 與 kube-apiserver 之間的通信是雙向的, kubelet 既需要訪問 kube-apiserver 獲取分配到自己節(jié)點上的 pod 信息, kube-apiserver 也需要主動訪問 kubelet 拉取日志, 狀態(tài), 監(jiān)控數(shù)據(jù)等信息, 所以對兩個組件來說, 認證是雙向的, kube-apiserver 需要持有 kubelet 的客戶端證書, 以完成 kubelet 對自己身份的校驗; kubelet 也需要持有 kube-apiserver 的客戶端證書, 完成 kube-apiserver 對自己身份的認證。
通過kubeadm安裝時,Kubelet是唯一一個運行在宿主機上的服務,因為它負責啟動容器,如果它也運行在容器中,那就成了它在容器中啟動其他容器啦,這樣會有很多不方便。

(8) kube-DNS

一個可選的DNS服務,用于為每個Service對象創(chuàng)建DNS記錄,這樣所有的Pod就可以通過DNS訪問服務了。

(9) CRI

CRI是k8s對容器操作的統(tǒng)一抽象,在1.20版本之前,k8s直接調(diào)用docker的API,所以搞了一個 dockershim的適配器來完成,之前比較熱的話題k8s要廢棄docker,其實是廢棄這個東西。目前k8s最新版對容器操作直接對接OCI(容器統(tǒng)一的開發(fā)標準)來完成,這樣的好處不言而喻,不管什么容器廠家,只要實現(xiàn)了OCI標準,就能和k8s無縫對接,詳細請看我的文章《docker的隕落》

二、安裝

使用kubeadm安裝k8s非常簡單,但經(jīng)常失敗,大致失敗的原因有幾點:

  • 鏡像下載不下來,使用阿里云鏡像,但版本比較老
  • 虛擬機,云主機等多網(wǎng)卡環(huán)境,需指定advertiseAddress,calico插件需要指定通信的網(wǎng)卡
  • pod網(wǎng)段和service網(wǎng)段和系統(tǒng)網(wǎng)段沖突
  • 浮動IP問題
  • OpenStack環(huán)境下容器跨節(jié)點無法通行問題,可嘗試關(guān)閉port-security來解決
  1. 編寫kubeadm配置文件: kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: InitConfiguration
# kubeadm 使用 eth0 的默認網(wǎng)絡接口(通常是內(nèi)網(wǎng)IP,在virtualbox一般是10.0.2.15)做為 Master節(jié)點的advertise address
# 如果是通過虛擬機安裝k8s,那么必須設置advertiseAddress地址,否則導致其他節(jié)點無法正常和master通信
localAPIEndpoint:
  # 不能綁定浮動IP
  advertiseAddress: 10.0.2.24
  bindPort: 6443
  
---
# 開啟Kube-proxy代理規(guī)則為ipvs,默認是Iptables
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"

---
apiVersion: "kubeadm.k8s.io/v1beta2"
kind: ClusterConfiguration
kubernetesVersion: v1.17.4
controlPlaneEndpoint: "apiserver:6443"
apiServer:
  extraArgs:
    service-node-port-range: 1000-40000
  certSANs:
  - 10.0.2.24
  - 127.0.0.1
networking:
  # podSubnet相當于--pod-network-cidr 參數(shù)
  podSubnet: 192.244.0.0/16
  # serviceSubnet相當于--service-network-cidr 參數(shù)
  serviceSubnet: 10.96.0.0/16
  1. 執(zhí)行kubeadm初始化操作
#  加上此參數(shù):--upload-certs ,其他節(jié)點加入時可以自動獲取證書
$ kubeadm init --config=kubeadm-config.yaml --upload-certs
  1. 安裝客戶端,執(zhí)行節(jié)點加入操作等
  2. 安裝網(wǎng)絡插件,推薦安裝 calico 插件。

3. 應用部署

k8s內(nèi)置了多種資源類型,如pod是k8s中最小的單元, ReplicaSet管理pod的多個副本,Deployment 是無狀態(tài)應用。

下面是部署一個nginx到k8s集群,并設置有pod有3個副本

apiVersion: apps/v1
kind: Deployment

metadata:
  name: nginx-deployment
  labels:
    app: nginx

spec:
  replicas: 3
apiVersion: apps/v1
kind: Deployment

metadata:
  name: nginx-deployment
  labels:
    app: nginx

spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: registry.cn-hangzhou.aliyuncs.com/moobox/nginx
        ports:
        - containerPort: 80---
#service
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:

  - port: 80
    protocol: TCP
    targetPort: 80
      selector:
    app: nginx
      type: ClusterIP
$ kubectl apply -f nginx.yaml
$ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-6c84b7494d-gj5qk   1/1     Running   0          4m11s
nginx-deployment-6c84b7494d-j8fhz   1/1     Running   0          4m11s
nginx-deployment-6c84b7494d-xbvdf   1/1     Running   0          4m11s

4. 高級

一、監(jiān)控

使用prometheus + Grafana監(jiān)控k8s集群,支持operator的話,可下載kube-prometheus v0.5.0 版(最新版有一個鏡像拉取不了)進行安裝。安裝完如果沒有監(jiān)控數(shù)據(jù),可能是:

問題1: 時間不同步,時區(qū)不對,設置為本地時區(qū)和當前時間,查看
prometheus主頁發(fā)現(xiàn)有警告,可通過timedatectl和date 命令修改

問題2:Grafana 的prometheus數(shù)據(jù)源,默認配置的是k8s內(nèi)部域名地址,所以外部無法訪問,數(shù)據(jù)源需要修改為外部的地址: http://192.168.x.x:39090/

二、藍綠部署

k8s默認就支持滾動升級,藍綠部署也是支持的,加入有個服務之前的版本是V1,新部署了一個版本是V2,那我們就可以通過兩個service來實現(xiàn)一個簡單的藍綠部署

#service
apiVersion: v1
kind: Service
metadata:
  name: web-bluegreen-v1
  namespace: dev
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  # 通過選擇不同版本的webapp,來切換流量  
  selector:
    app: webapp
    version: v1.0 #version: v2.0
  type: ClusterIP
#service
apiVersion: v1
kind: Service
metadata:
  name: web-bluegreen-v2
  namespace: dev
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  # 通過選擇不同版本的webapp,來切換流量  
  selector:
    app: webapp
    version:  v2.0
  type: ClusterIP

k8s默認是不支持灰度發(fā)布的,想要實現(xiàn)灰度發(fā)布,可使用其他組件,如istio

三、自動擴容

HPA(Horizontal Pod Autoscaler)是k8s的一個資源對象,利用prometheus獲取該資源對象的監(jiān)控指標,可實現(xiàn)Pod自動伸縮。但有幾點必須要注意:

  • pod一定要設置資源限制request、limit等,才能開啟HPA
  • HPA控制器的時間窗口默認是15秒,即每隔15s拉取一次監(jiān)控指標,可通過–horizontal-pod-autoscaler-sync-period參數(shù)設定
    kubernetes集群需要配置好metrics server
  • 目前是v1版本,從k8s v1.18 支持 v2beta2版本,可支持基于內(nèi)存的伸縮指標,可自定義伸縮指標

基于內(nèi)存/CPU的自動伸縮
下面我們對一個xxx應用進行自動伸縮,當CPU使用超過60%時,會自動增加pod,但不會超過6個

$ kubectl autoscale deployment xxx --cpu-percent=60 --min=2 --max=6

QPS的自動伸縮
下面創(chuàng)建一個HPA來實現(xiàn) 一個QPS的 自動伸縮:

apiVersion: autoscaling/v2beta2 
kind: HorizontalPodAutoscaler
metadata: 
  name: blog-web
spec: 
  scaleTargetRef: 
    apiVersion: apps/v1 
    kind: Deployment 
    name: blog-web
  minReplicas: 2
  maxReplicas: 8 
  metrics:
  - type: Pods
    pods:
      metric:
        name: http_requests_received
      target:
        type: AverageValue
        averageValue: 10
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內(nèi)容