一、 docker簡介
環境配置
軟件開發最大的麻煩事之一,就是環境配置。用戶計算機的環境都不相同,你怎么知道自家的軟件,能在那些機器跑起來?
用戶必須保證兩件事:操作系統的設置,各種庫和組件的安裝。只有它們都正確,軟件才能運行。舉例來說,安裝一個 Python 應用,計算機必須有 Python 引擎,還必須有各種依賴,可能還要配置環境變量。
如果某些老舊的模塊與當前環境不兼容,那就麻煩了。開發者常常會說:"它在我的機器可以跑了"(It works on my machine),言下之意就是,其他機器很可能跑不了
虛擬機(virtual machine)
- 就是帶環境安裝的一種解決方案。它可以在一種操作系統里面運行另一種操作系統,比如在 Windows 系統里面運行 Linux 系統。應用程序對此毫無感知,因為虛擬機看上去跟真實系統一模一樣,而對於底層系統來說,虛擬機就是一個普通文件,不需要了就刪掉,對其他部分毫無影響。雖然用戶可以通過虛擬機還原軟件的原始環境。但是,這個方案有幾個缺點。
- (1)資源占用多
虛擬機會獨占一部分內存和硬盤空間。它運行的時候,其他程序就不能使用這些資源了。哪怕虛擬機里面的應用程序,真正使用的內存只有 1MB,虛擬機依然需要幾百 MB 的內存才能運行。 - (2)冗余步驟多
虛擬機是完整的操作系統,一些系統級別的操作步驟,往往無法跳過,比如用戶登錄 - (3)啟動慢
啟動操作系統需要多久,啟動虛擬機就需要多久。可能要等幾分鍾,應用程序才能真正運行
Linux 容器
由於虛擬機存在這些缺點,Linux 發展出了另一種虛擬化技術:Linux 容器(Linux Containers,縮寫為 LXC)。
- Linux 容器不是模擬一個完整的操作系統,而是對進程進行隔離。或者說,在正常進程的外面套了一個保護層。對於容器里面的進程來說,它接觸到的各種資源都是虛擬的,從而實現與底層系統的隔離。由於容器是進程級別的,相比虛擬機有很多優勢。
- (1)啟動快
容器里面的應用,直接就是底層系統的一個進程,而不是虛擬機內部的進程。所以,啟動容器相當於啟動本機的一個進程,而不是啟動一個操作系統,速度就快很多。 - (2)資源占用少
容器只占用需要的資源,不占用那些沒有用到的資源;虛擬機由於是完整的操作系統,不可避免要占用所有資源。另外,多個容器可以共享資源,虛擬機都是獨享資源。 - (3)體積小
容器只要包含用到的組件即可,而虛擬機是整個操作系統的打包,所以容器文件比虛擬機文件要小很多。
Docker
- docker屬於 Linux 容器的一種封裝,使用go語言開發,基於Linux內核的cgroups,namespace,Union FS等技術,對應用進程進行封裝隔離,並且獨立於宿主機與其他進程。
Docker 將應用程序與該程序的依賴,打包在一個文件里面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器里運行,就好像在真實的物理機上運行一樣。有了 Docker,就不用擔心環境問題。
總體來說,Docker 的接口相當簡單,用戶可以方便地創建和使用容器,把自己的應用放入容器。容器還可以進行版本管理、復制、分享、修改,就像管理普通的代碼一樣
二、docker帶來的好處(解決了什么問題)
- (1)職責的邏輯分離
使用docker,開發人員只需要關心容器中運行的應用程序,而運維人員只需要關心如何管理容器。Docker設計的目的就是加強開發人員寫代碼的開發環境與應用程序要部署的生產環境的一致性,從而降低那種“開發時一切正常,肯定是運維的問題”的風險。 - (2)快速高效的開發生命周期
Docker 的目標之一就是縮短代碼從開發,測試到部署,上線運行的周期,讓你的應用程序具備可移植性,易於構建,並易於協作。 - (3)響應式部署和擴展
Docker 是基於容器的平台,允許高度可移植的工作負載。Docker 容器可以在開發人員的本機上,數據中心的物理或虛擬機上,雲服務上或混合環境中運行。
Docker 的可移植性和輕量級的特性,還可以使您輕松地完成動態管理的工作負擔,並根據業務需求指示,實時擴展或拆除應用程序和服務。 - (4)在同一硬件上運行更多工作負載
Docker 輕巧快速。它為基於虛擬機管理程序的虛擬機提供了可行、經濟、高效的替代方案,因此您可以利用更多的計算能力來實現業務目標。Docker 非常適合於高密度環境以及中小型部署,而您可以用更少的資源做更多的事情。
Docker 的主要用途,目前有三大類。
- (1)提供一次性的環境。比如,本地測試他人的軟件、持續集成的時候提供單元測試和構建的環境。
- (2)提供彈性的雲服務。因為 Docker 容器可以隨開隨關,很適合動態擴容和縮容。
- (3)組建微服務架構。通過多個容器,一台機器可以跑多個服務,因此在本機就可以模擬出微服務架構
鏡像 & 容器 & 倉庫
鏡像和容器的關系就像類和類的實例,一個鏡像可以同時跑多個容器,單個容器實例又可以創建新的鏡像。然后docker倉庫就像maven儲存jar一樣,提供保存鏡像功能
三、Kubernetes簡介
- docker提供容器化技術,然后它並不具備編排能力,如果想在多台機子需要運行則每台機子都需要操作一遍,不方便。docker的缺點
- 單機使用,無集群
- 容器數量上升,管理成本成指數增加
- 沒有容災和自愈機制
- 沒有編排模板,無法大規模容器調度(上線下線)
- 沒有統一的配置中心
- 沒有圖形管理功能
- 因此我需要容器編排工具
- docker swarm(涼了)
- mesosphere + marathon (少人用)
- kubenetes (k8s)
- k8s 的優勢
- 自動化容器的部署 和 擴縮容
- 相同服務容器有組的概念,可以提供服務發現和負載均衡
- 可自我修復:當某一個node節點關機或掛掉后,node節點上的服務會自動轉移到另一個node節點上
- 滾動更新: 更新服務不中斷,一次更新一個pod,而不是同時刪除整個服務
- 集中化配置管理和秘鑰管理
- 任務批處理
- 擴展性好: 支持模塊化、插件化、可掛載、可組合
- k8s缺點
- 學習成本高
四 k8s需要安裝的模塊和組件
- master節點
- 集群擁有一個Kubernetes Master。Kubernetes Master提供集群的獨特視角,並且擁有一系列組件,比如Kubernetes API Server。API Server提供可以用來和集群交互的REST端點。master節點包括用來創建和復制Pod的Deployment
- Node節點
- 節點是物理或者虛擬機器,作為Kubernetes worker,通常需要安裝docker,kubelet,kube Proxy
k8s組件
- etcd (組件)
- 用於持久化存儲集群中所有的資源對象,如Node、Service、Pod、RC、Namespace等
- API Server (組件)
- 提供了資源對象的唯一操作入口,其他所有組件都必須通過它提供的API來操作資源數據
- Controller Manager
- 集群內部的管理控制中心,其主要目的是實現Kubernetes集群的故障檢測和恢復的自動化工作,比如根據RC的定義完成Pod的復制或移除,以確保Pod實例數符合RC副本的定義;根據Service與Pod的管理關系
- Scheduler
- 集群中的調度器,負責Pod在集群節點中的調度分配
- Kubelet
- 負責本Node節點上的Pod的創建、修改、監控、刪除等全生命周期管理
- kube Proxy
- 實現了Service的代理與軟件模式的負載均衡器
k8s集群的三種安裝方式
- minikube (個人學習使用)
- 二進制文件下載安裝(適合生產,需要熟練人員)
- kubeadm 安裝(適合生產)
五、Kubernetes基本概念
- Pod
- Pod是最小部署單元,Pod有一個或多個容器組成,Pod中容器共享存儲和網絡,在同一台Docker主機上運行
- pod包含的容易建議只運行一個服務進程
- 生產環境中很少單獨啟動一個pod直接使用,而是常用Depolyment、DaemonSet、StatefulSet等方式調度管理Pod
- Deployment、Replication Controller 和 Replicat Set、
- Replication Controller和 Replicat Set 是兩種部署Pod的方式。可以確保任意時間都有指定數量的Pod“副本”在運行。如果為某個Pod創建了Replication Controller並且指定3個副本,它會創建3個Pod,並且持續監控它們
- 生產會可以使用更高級的Deployment進行pod的管理和部署
- Deployment示例,字段解析
apiVersion: apps/v1 # 指定api版本,此值必須在kubectl api-versions中
kind: Deployment # 指定創建資源的角色/類型
metadata: # 資源的元數據/屬性
name: demo # 資源的名字,在同一個namespace中必須唯一
namespace: default # 部署在哪個namespace中
labels: # 設定資源的標簽
app: demo
version: stable
spec: # 資源規范字段
replicas: 1 # 聲明副本數目
revisionHistoryLimit: 3 # 保留歷史版本
selector: # 選擇器
matchLabels: # 匹配標簽
app: demo
version: stable
strategy: # 策略
rollingUpdate: # 滾動更新
maxSurge: 30% # 最大額外可以存在的副本數,可以為百分比,也可以為整數
maxUnavailable: 30% # 示在更新過程中能夠進入不可用狀態的 Pod 的最大值,可以為百分比,也可以為整數
type: RollingUpdate # 滾動更新策略
template: # 模版
metadata: # 資源的元數據/屬性
annotations: # 自定義注解列表
sidecar.istio.io/inject: "false" # 自定義注解名字
labels: # 設定資源的標簽
app: demo
version: stable
spec: # 資源規范字段
containers:
- name: demo # 容器的名字
image: demo:v1 # 容器使用的鏡像地址
imagePullPolicy: IfNotPresent # 每次Pod啟動拉取鏡像策略,三個選擇 Always、Never、IfNotPresent
# Always,每次都檢查;Never,每次都不檢查(不管本地是否有);IfNotPresent,如果本地有就不檢查,如果沒有就拉取
resources: # 資源管理
limits: # 最大使用
cpu: 300m # CPU,1核心 = 1000m
memory: 500Mi # 內存,1G = 1000Mi
requests: # 容器運行時,最低資源需求,也就是說最少需要多少資源容器才能正常運行
cpu: 100m
memory: 100Mi
livenessProbe: # pod 內部健康檢查的設置
httpGet: # 通過httpget檢查健康,返回200-399之間,則認為容器正常
path: /healthCheck # URI地址
port: 8080 # 端口
scheme: HTTP # 協議
# host: 127.0.0.1 # 主機地址
initialDelaySeconds: 30 # 表明第一次檢測在容器啟動后多長時間后開始
timeoutSeconds: 5 # 檢測的超時時間
periodSeconds: 30 # 檢查間隔時間
successThreshold: 1 # 成功門檻
failureThreshold: 5 # 失敗門檻,連接失敗5次,pod殺掉,重啟一個新的pod
readinessProbe: # Pod 准備服務健康檢查設置
httpGet:
path: /healthCheck
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 5
#也可以用這種方法
#exec: 執行命令的方法進行監測,如果其退出碼不為0,則認為容器正常
# command:
# - cat
# - /tmp/health
#也可以用這種方法
#tcpSocket: # 通過tcpSocket檢查健康
# port: number
ports:
- name: http # 名稱
containerPort: 8080 # 容器開發對外的端口
protocol: TCP # 協議
imagePullSecrets: # 鏡像倉庫拉取密鑰
- name: harbor-certification
affinity: # 親和性調試
nodeAffinity: # 節點親和力
requiredDuringSchedulingIgnoredDuringExecution: # pod 必須部署到滿足條件的節點上
nodeSelectorTerms: # 節點滿足任何一個條件就可以
- matchExpressions: # 有多個選項,則只有同時滿足這些邏輯選項的節點才能運行 pod
- key: beta.kubernetes.io/arch
operator: In
values:
- amd64
- Label
- 標簽用於區分對象,(比如Pod,Service)鍵/值對存在;每個對象可以 有多個標簽,通過標簽關聯對象 。然后可通過Pod里的Selector屬性選擇
- StatefulSet
- 有狀態集,常用於部署有狀態且需要順序啟動的應用程序。可用於部署es集群,mongoDB集群、redis集群或者zookeeper
- DaemonSet
- 守護進程集,和守護進程類似,它會在符合條件的節點部署一個pod。當有新節點加入集群時,會為它新加一個pod,當移除時,則回收pod。適合部署日志收集deaemon
- ConfigMap
- 用於管理程序的配置文件
- Secret
- 用於保存敏感信息,如密碼,令牌,SSH秘鑰
- Storage (持久化)
- 容器內的磁盤文件都是短暫的,如果容器崩潰重啟,其文件會丟失。因此k8s提供了Volums(數據卷),可以將數據掛載到主機上或者其他文件系統上(Glustter\NFS等)
- Volums資源的管理,可以使用PersistentVolume和PersistentVolume和Clain管理
- Service
- 因為Pod可能在不斷的創建和死亡的,其的地址是不斷變化的。那它們之間是怎么訪問的?答案:service主要用於Pod之間的通信。對於Pod來說,Service是提前定義好的且不變的資源
- Service資源的名詞解析
apiVersion: v1 # 指定api版本,此值必須在kubectl api-versions中
kind: Service # 指定創建資源的角色/類型
metadata: # 資源的元數據/屬性
name: demo # 資源的名字,在同一個namespace中必須唯一
namespace: default # 部署在哪個namespace中
labels: # 設定資源的標簽
app: demo
spec: # 資源規范字段
type: ClusterIP # ClusterIP 類型
ports:
- port: 8080 # service 端口
targetPort: http # 容器暴露的端口
protocol: TCP # 協議
name: http # 端口名稱
selector: # 選擇器
app: demo
- Ingress
- Ingess 為k8s集群的服務提供了入口,可以提供負載均衡,SSL
- Ingree 用與 集群外部到集群內部的Service的http 和 https路由
- RBAC(Role-Base Access Control,基於角色訪問控制)
- 提供了Role,ClusterRole,RoleBinding,ClusterRoleBinding四種資源。role和ClusterRole區別是role是作用於命名空間的,ClusterRole是作用與集群的
- CronJob
- cronJob可以用於周期行的執行任務,這些自動化任務和運行在linux和unix系統上的cronJob一樣。crobJob對定期和重復任務非常有用,如執行備份任務,周期性調度程序接口
六、目標
Jenkins+Docker+K8S+GitLab+Harbor搭建持續集成交付環境
整套環境的搭建包含:Docker環境的搭建、docker-compose環境的搭建、K8S集群的搭建、GitLab代碼倉庫的搭建、Jenkins自動化部署環境的搭建、Harbor私有倉庫的搭
docker整理來自阮一峰博文,如有侵權,聯系我刪除
阮一峰docker博文鏈接:http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html