⑴ Spring提供了()和()兩種依賴注入方式訪問容器配置的Bean實例。
【答案】:Set注入、陵猛構造注入
解析:依賴注入是指對象之間關系的控制權由應用代碼中轉粗消到外部容器,而且依賴性還較強,所以Spring框架主要提供了Set注入和構造注入兩種依賴注入岩汪知的方式。
⑵ 常見的五種容器管理方法
大家在開發應用軟體的時候以及架構伺服器的時候應該聽過關於容器管理的一些方法吧。今天我們就給大家整合了一些比較好用的容器首仿管理方式,一起來了解一下吧。
1.AWS彈性容器服務
AmazonECS支持Docker容器及其專有的Fargate技術。ECS是一個高度可擴展的平台,允許用戶安裝和運行自己的容器編排軟體、管理和擴展虛擬機集群,或在這些虛擬機上安排容器。
這包括長期運行的應用程序、微服務、批處理作業和機器學習應用程序。AWS容器產品與許多其他AWS服務集成,包括彈性負載平衡、AmazonVPC、AWSIAM、,AmazonECR、AWSBatch、AmazonCloudWatch、AWSCloudFormation、AWSCodeStar和AWSCloudTrail。AWS還為Kubernetes(EKS)提供彈性容器服務。
亞馬遜網路服務是雲計算基礎設施市場份額的行業領導者。它在公共雲中擁有41.5%的應用程序工作負載。這使其成為組織的焦點,其宴芹指中包括任何考慮容器的公司。
2.AzureKubernetes服務(AKS)
AzureKubernetesService(AKS)提供了一個功能強大的託管工具,用於使用和編排容器,以及動態擴展基礎設施和應用程序。AKS使用Azure門戶和AzureCLI或Azure資源管理器和Terraform等基礎設施代碼工具來配置集群。
AKS提供了幾個關鍵功能:控制平面遙測、日誌聚合和容器運行狀況可見性,作為Azure門戶的一部分。它還具有自動升級、修補和自我修復功能。
憑借基於應用程序工作負載的近30%的市場份額,微軟Azure也是晌配企業雲計劃的核心。更重要的是,它的市場份額正在增長。該服務旨在通過引入高度自動化的流程來簡化DevOps,這與流程管理相輔相成。
3.DiamantiD10
Diamanti的D10裸機容器平台提供統一的解決方案,java課程建議可以大規模託管和運行容器化應用程序。它插入現有的VLAN和DNS基礎設施。
⑶ docker daemon中的userland-proxy選項
docker啟動時可以在配置文件中指定啟動項,如下:
新建/etc/default/docker文件,指定docker守護進程的啟動配置:
從docker daemon的角度,添加了userland-proxy的起停開關
首先介紹userland-proxy一直以來的作用。眾所周知,在Docker的橋接bridge網路模式下,Docker容器是通過宿主機上的NAT模式,搜碼碼建立與宿主機之外世界的通信。然而在宿主機上,一般情況下,進程可以通過三種方式訪問容器,分別為:<eth0IP>:<hostPort>, <containerIP>:<containerPort>,以及<0.0.0.0>:<hostPort>。實際上,最後一種方式的成功訪問完全得益於userland-proxy,即Docker Daemon在啟動一個Docker容器時,每次為容器在宿主機上映射一個埠,都會啟動一個docker-proxy進程,實現宿主機上0.0.0.0地址上對容器的訪問代理。
當時引入userland-proxy時,也許是因為設計者意識到了0.0.0.0地世哪址對容器訪問上的功能缺陷。然而,在docker-proxy加入Docker之後相當長的一段時間內。Docker愛好者普遍感受到,很多場景下,docker-proxy並非必需,甚至會帶來一些其他的弊端。
影響較大的場景主要有兩種。
第一,單個容器需要和宿主機有多個埠模敬的映射。此場景下,若容器需要映射1000個埠甚至更多,那麼宿主機上就會創建1000個甚至更多的docker-proxy進程。據不完全測試,每一個docker-proxy佔用的內存是4-10MB不等。如此一來,直接消耗至少4-10GB內存,以及至少1000個進程,無論是從系統內存,還是從系統CPU資源來分析,這都會是很大的負擔。
第二,眾多容器同時存在於宿主機的情況,單個容器映射埠極少。這種場景下,關於宿主機資源的消耗並沒有如第一種場景下那樣暴力,而且一種較為慢性的方式侵噬資源。
如今,Docker Daemon引入- -userland-proxy這個flag,將以上場景的控制權完全交給了用戶,由用戶決定是否開啟,也為用戶的場景的proxy代理提供了靈活性
原文地址: http://www.dataguru.cn/thread-544489-1-1.html
⑷ 容器雲部署後有哪些應用途徑
第一,當容器雲部署之後較為常見的就是微服務的應用,這種情況下容器是允許開發人員選擇合適的服務工具或者技術棧的。在該部署作業中應該注意的就是要想辦法隔離服務以外的潛在沖突,而且還應該重視的就是地獄式矩陣依賴。
第二,其實在進行容器雲部署之後傳統應用也是很常見的,這方面要重視成本的控制。而且大多數情況下都是通過大規模的螞蔽單體應用來增加容易隔離的安全性和移植特點,這些都是在部署的時缺鬧候應該考慮的事情。
第三,還有就是要注意容器雲部署之後的持續集成和部署,這方面只要是管道自動化和應用部署以及交付速度等,當重視這些方面之後才能確保完成部署工作且通過專業的測試,而且作為專業的IT團隊還應該可以持續集成新的代碼才行。
這里需要專業的伏物罩開發團隊,可以了解一下時速雲的案例,他們服務過500+的中大型客戶,通過雲原生技術幫助企業實現數字化轉型,不僅涵蓋容器雲 PaaS、DevOps、微服務、ServiceMesh、API 網關等核心雲原生產品,還可以為企業提供數據開發、數據治理、數據資產、數據服務等數據能力。
⑸ Pod的特性
Pod是k8s系統中可以創建和管理的最小單元,是資源對象模型中由用戶創建或部署的最小資源對象模型,也是在k8s上運行容器化應用的資源對象,其他的資源對象都是用來支撐或者擴展Pod對象功能的,比如控制器對象是用來管控Pod對象的,Service或者Ingress資源對象是用來暴露Pod引用對象的,PersistentVolume資源對象是用來為Pod提供存儲等等,k8s不會直接處理容器,而是Pod,Pod是由一個或者多個container組成的。
每個Pod都是運行應用的單個實例,如果需要水平擴展應用(例如,運行多個實例),則應該使用多個Pods,每個實例一個Pod。在Kubernetes中,這樣通常稱為Replication。Replication的Pod通常由Controller創建和管理。
Pod可以被理解成一群可以共享網路、存儲和計算資源的容器化服務的集合。再打個形象的比喻,在同一個Pod里的幾個Docker服務/程序,好像被部署在同一台機器上,可以通過localhost互相訪問,並且可以共用Pod里的存儲資源(這里是指Docker可以掛載Pod內的數據卷,數據卷的概念,後文會詳細講述,暫時理解為「需要手動mount的磁碟」)。筆者總結Pod如下圖,可以看到:同一個Pod之間的Container可以通過localhost互相訪問,並且可以掛載Pod內所有的數據卷;但是不同的Pod之間的Container不能用localhost訪問,也不能掛載其他Pod的數據卷。
1.1、為什麼需要pod
我們先談談為什麼k8s會使用pod這個最小單元,而不是使用docker的容器,k8s既然使用了pod,當然有它的理由。
1、更利於擴展
k8s不僅僅支持Docker容器,也支持rkt甚至用戶自定義容器,為什麼會有這么多不同的容器呢,因為容器並不是真正的虛擬機,docker的一些概念和誤區總結,此外,Kubernetes不依賴於底層某一種具體的規則去實現容器技術,而是通過CRI這個抽象層操作容器,這樣就會需要pod這樣一個東西,pod內部再管理多個業務上緊密相關的用戶業務容器,就會更有利用業務擴展pod而不是擴展容器。
2、更容易定義一組容器的狀態
如果我們沒有使用pod,而是直接使用一組容器去跑一個業務呢,那麼當其中一個或者若干個容器出現問題呢,我們如何去定義這一組容器的狀態呢,通過pod這個概念,這個問題就可以很好的解決,一組業務容器跑在一個k8s的pod中,這個pod中會有一個pause容器,這個容器與其他的業務容器都沒有關系,以這個pause容器的狀態來代表這個pod的狀態.
3、利於容器間文件共享,以及通信。
pod里的多個業務容器共享pause容器的ip和存儲卷Volume,pod中的其他容器共享pause容器的ip地址和存儲,這樣就做到了文件共享和互信。
1.2 Pod 特性:
1 資源共享:IP和Volume
一個Pod里的多個容器可以共享存儲和網路IP,可以看作一個邏輯的主機。共享的如 namespace,cgroups或者其他的隔離資源。
多個容器共享同一個network namespace,由此在一個Pod里的多個容器共享Pod的IP和埠namespace,所以一個Pod內的多個容器之間可以通過localhost來進行通信,所需要注意的是不同容器要注意不要有埠沖突即可。不同的Pod有不同的IP,不同Pod內的多個容器之前通信,不可以使用IPC(如果沒有特殊指定的話)通信,通常情況下使用Pod的IP進行通信。
k8s要求底層網路支持集群內任意兩個pod直接的TCP/IP直接通信,這通常才有虛擬二層網路技術來實現,例如Flannel,Openswitch等。
一個Pod里的多個容器可以共享存儲卷,這個存儲卷會被定義為Pod的一部分,並且可以掛載到該Pod里的所有容器的文件系統上。
2 生命周期短暫
Pod屬於生命周期比較短暫的組件,比如,當Pod所在節點發生故障,那麼該節點上的Pod會被調度到其他節點,但需要注意的是,被重新調度的Pod是一個全新的Pod,跟之前的Pod沒有半毛錢關系。
3 平坦的網路
K8s集群中的所有Pod都在同一個共享網路地址空間中,也就是說每個Pod都可以通過其他Pod的IP地址來實現訪問。
1.3 Pod使用和管理
1、核心原則是:將多個應用分散到多個Pod中 原因:基於資源的合理應用;擴縮容,不同應用應該有不同的擴縮容策略等。
結論:單Pod單容器應用,除非特殊原因。
你很少會直接在kubernetes中創建單個Pod。因為Pod的生命周期是短暫的,用後即焚的實體。當Pod被創建後(不論是由你直接創建還是被其他Controller),都會被Kubernetes調度到集群的Node上。直到Pod的進程終止、被刪掉、因為缺少資源而被驅逐、或者Node故障之前這個Pod都會一直保持在那個Node上。
Pod不會自愈。如果Pod運行的Node故障,或者是調度器本身故障,這個Pod就會被刪除。同樣的,如果Pod所在Node缺少資源或者Pod處於維護狀態,Pod也會被驅逐。Kubernetes使用更高級的稱為Controller的抽象層,來管理Pod實例。雖然可以直接使用Pod,但是在Kubernetes中通常是使用Controller來管理Pod的。
1.4、Pod和Controller
Controller可以創建和管理多個Pod,提供副本管理、滾動升級和集群級別的自愈能力。例如,如果一個Node故障,Controller就能自動將該節點上的Pod調度到其他健康的Node上。
包含一個或者多個Pod的Controller示例:
Deployment
StatefulSet
DaemonSet
通常,Controller會用你提供的Pod Template來創建相應的Pod。
在用戶定義范圍內,如果pod增多,則ReplicationController會終止額外的pod,如果減少,RC會創建新的pod,始終保持在定義范圍。例如,RC會在Pod維護(例如內核升級)後在節點上重新創建新Pod。
對Pod的定義可以通過Yaml或Json格式的配置文件來完成。關於Yaml或Json中都能寫哪些參數,參考官網 http://kubernetes.io/docs/user-guide/pods/multi-container/
Pod的yaml整體文件內容及功能註解如下:
我們來看一個段實際的例子
在使用docker時,我們可以使用docker run命令創建並啟動一個容器,而在Kubernetes系統中對長時間運行的容器要求是:其主程序需要一直在前台運行。如果我們創建的docker鏡像的啟動命令是後台執行程序,例如Linux腳本:
nohup ./startup.sh &
則kubelet創建包含這個容器的pod後運行完該命令,即認為Pod執行結束,之後根據RC中定義的pod的replicas副本數量生產一個新的pod,而一旦創建出新的pod,將在執行完命令後陷入無限循環的過程中,這就是Kubernetes需要我們創建的docker鏡像以一個前台命令作為啟動命令的原因。
對於無法改造為前台執行的應用,也可以使用開源工具supervisor輔助進行前台運行的功能。
Pod可以由一個或多個容器組合而成
場景1:單個應用多個容器
spring boot web:
kubectl create -f springboot-deployment.yml
kubectl get pods -o wide
加入 –o wide參數 查看額外信息:包括node和ip
pod處於pending的原因:通過 kubectl describe pods springbootweb 進一步查找問題。
可以看到pod的鏡像信息寫錯了:
先刪除pod,然後再創建: kubectl delete pod springbootweb
由於創建的埠號是9081,可以直接訪問:curl 10.0.86.2:9081
# curl 10.0.86.2:9081
Hello world
場景2:Pod不同應用多個容器組合而成
例如:兩個容器應用的前端frontend和redis為緊耦合的關系,應該組合成一個整體對外提供服務,則應該將這兩個打包為一個pod.
配置文件frontend-localredis-pod.yaml如下:
屬於一個Pod的多個容器應用之間相互訪問只需要通過localhost就可以通信,這一組容器被綁定在一個環境中。
使用kubectl create創建該Pod後,get Pod信息可以看到如下圖:
#kubectl get gods
可以看到READY信息為2/2,表示Pod中的兩個容器都成功運行了.
2.3 集群外部訪問Pod
上面的例子,在k8s集群的安裝有kube-proxy的node節點上,可以直接通過curl 10.0.86.2:9081 訪問集群的pod。但在集群外的客戶端系統無法通過Pod的IP地址或者Service的虛擬IP地址和虛擬埠號訪問到它們。為了讓外部客戶端可以訪問這些服務,可以將Pod或Service的埠號映射到宿主機,以使得客戶端應用能夠通過物理機訪問容器應用。
1、將容器應用的埠號映射到物理機
(2)通過設置Pod級別的hostNetwork-true,該Pod中所有容器的埠號都將被直接映射到物理機上。設置hostNetwork-true時需要注意,在容器的ports定義部分如果不指定hostPort,則默認hostPort等於containerPort,如果指定了hostPort,則hostPort必須等於containerPort的值。
靜態pod是由kubelet進行管理的僅存在於特定Node的Pod上,他們不能通過API Server進行管理,無法與ReplicationController、Deployment或者DaemonSet進行關聯,並且kubelet無法對他們進行健康檢查。靜態Pod總是由kubelet進行創建,並且總是在kubelet所在的Node上運行。
創建靜態Pod有兩種方式:配置文件或者HTTP方式
1)配置文件方式
首先,需要設置kubelet的啟動參數"--config",指定kubelet需要監控的配置文件所在的目錄,kubelet會定期掃描該目錄,並根據目錄中的 .yaml或 .json文件進行創建操作
假設配置目錄為/etc/kubelet.d/配置啟動參數:--config=/etc/kubelet.d/,然後重啟kubelet服務後,再宿主機受用docker ps或者在Kubernetes Master上都可以看到指定的容器在列表中
由於靜態pod無法通過API Server直接管理,所以在master節點嘗試刪除該pod,會將其變為pending狀態,也不會被刪除
#kubetctl delete pod static-web-node1
要刪除該pod的操作只能在其所在的Node上操作,將其定義的.yaml文件從/etc/kubelet.d/目錄下刪除
#rm -f /etc/kubelet.d/static-web.yaml
#docker ps
Volume類型包括:emtyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、gitRepo、secret、nfs、scsi、glusterfs、persistentVolumeClaim、rbd、flexVolume、cinder、cephfs、flocker、downwardAPI、fc、azureFile、configMap、vsphereVolume等等,可以定義多個Volume,每個Volume的name保持唯一。在同一個pod中的多個容器能夠共享pod級別的存儲卷Volume。Volume可以定義為各種類型,多個容器各自進行掛載操作,講一個Volume掛載為容器內需要的目錄。
如下圖:
如上圖中的Pod中包含兩個容器:tomcat和busybox,在pod級別設置Volume 「app-logs」,用於tomcat想其中寫日誌文件,busybox讀日誌文件。
配置文件如下:
busybox容器可以通過kubectl logs查看輸出內容
#kubectl logs volume-pod -c busybox
tomcat容器生成的日誌文件可以登錄容器查看
#kubectl exec -ti volume-pod -c tomcat -- ls /usr/local/tomcat/logs
應用部署的一個最佳實踐是將應用所需的配置信息於程序進行分離,這樣可以使得應用程序被更好的復用,通過不用配置文件也能實現更靈活的功能。將應用打包為容器鏡像後,可以通過環境變數或外掛文件的方式在創建容器時進行配置注入。ConfigMap是Kubernetes v1.2版本開始提供的一種統一集群配置管理方案。
6.1 ConfigMap:容器應用的配置管理
容器使用ConfigMap的典型用法如下:
ConfigMap以一個或多個key:value的形式保存在Kubernetes系統中共應用使用,既可以用於表示一個變數的值,也可以表示一個完整的配置文件內容。
通過yuaml配置文件或者直接使用kubelet create configmap 命令的方式來創建ConfigMap
6.2 ConfigMap的創建
舉個小例子cm-appvars.yaml來描述將幾個應用所需的變數定義為ConfigMap的用法:
# vim cm-appvars.yaml
執行kubectl create命令創建該ConfigMap
#kubectl create -f cm-appvars.yaml
查看建立好的ConfigMap:
#kubectl get configmap
kubectl describe configmap cm-appvars
kubectl get configmap cm-appvars -o yaml
另:創建一個cm-appconfigfile.yaml描述將兩個配置文件server.xml和logging.properties定義為configmap的用法,設置key為配置文件的別名,value則是配置文件的文本內容:
在pod "cm-test-app"定義中,將configmap "cm-appconfigfile"中的內容以文件形式mount到容器內部configfiles目錄中。
Pod配置文件cm-test-app.yaml內容如下:
創建該Pod:
#kubectl create -f cm-test-app.yaml
Pod "cm-test-app"created
登錄容器查看configfiles目錄下的server.xml和logging.properties文件,他們的內容就是configmap 「cm-appconfigfile」中定義的兩個key的內容
#kubectl exec -ti cm-test-app -- bash
root@cm-rest-app:/# cat /configfiles/server.xml
root@cm-rest-app:/# cat /configfiles/ logging.properties
6.3使用ConfigMap的條件限制
使用configmap的限制條件如下:
Pod在整個生命周期過程中被定義為各種狀態,熟悉Pod的各種狀態有助於理解如何設置Pod的調度策略、重啟策略
Pod的狀態包含以下幾種,如圖:
Pod的重啟策略(RestartPolicy)應用於Pod內所有的容器,並且僅在Pod所處的Node上由kubelet進行判斷和重啟操作。當某哥容器異常退出或者健康檢查石柏師,kubelet將根據RestartPolicy的設置進行相應的操作
Pod的重啟策略包括Always、OnFailure及Nerver,默認值為Always。
kubelet重啟失效容器的時間間隔以sync-frequency乘以2n來計算,例如1、2、4、8倍等,最長延時5分鍾,並且成功重啟後的10分鍾後重置該事件。
Pod的重啟策略和控制方式息息相關,當前可用於管理Pod的控制器寶庫ReplicationController、Job、DaemonSet及直接通過kubelet管理(靜態Pod),每種控制器對Pod的重啟策略要求如下:
RC和DaemonSet:必須設置為Always,需要保證該容器持續運行
Job:OnFailure或Nerver,確保容器執行完成後不再重啟
kubelet:在Pod失效時重啟他,不論RestartPolicy設置什麼值,並且也不會對Pod進行健康檢查
對Pod的健康檢查可以通過兩類探針來檢查:LivenessProbe和ReadinessProbe
LivenessProbe探針:用於判斷容器是否存活(running狀態),如果LivenessProbe探針探測到容器不健康,則kubelet殺掉該容器,並根據容器的重啟策略做響應處理
ReadinessProbe探針:用於判斷容器是否啟動完成(ready狀態),可以接受請求。如果ReadinessProbe探針探測失敗,則Pod的狀態被修改。Endpoint Controller將從service的Endpoint中刪除包含該容器所在的Pod的Endpoint。
kubelet定製執行LivenessProbe探針來診斷容器的健康狀況。LivenessProbe有三種事項方式。
1)ExecAction:在容器內部執行一個命令,如果該命令的返回值為0,則表示容器健康。例:
(2)TCPSocketAction:通過容器ip地址和埠號執行TCP檢查,如果能夠建立tcp連接表明容器健康。例:
3)HTTPGetAction:通過容器Ip地址、埠號及路徑調用http get方法,如果響應的狀態嗎大於200且小於400,則認為容器健康。例:
對於每種探針方式,都需要設置initialDelaySeconds和timeoutSeconds兩個參數,它們含義如下:
initialDelaySeconds:啟動容器後首次監控檢查的等待時間,單位秒
timeouSeconds:健康檢查發送請求後等待響應的超時時間,單位秒。當發生超時就被認為容器無法提供服務無,該容器將被重啟
九.玩轉Pod調度
在Kubernetes系統中,Pod在大部分場景下都只是容器的載體而已,通常需要通過RC、Deployment、DaemonSet、Job等對象來完成Pod的調度和自動控制功能。
9.1 RC、Deployment:全自動調度
RC的主要功能之一就是自動部署容器應用的多份副本,以及持續監控副本的數量,在集群內始終維護用戶指定的副本數量。
在調度策略上,除了使用系統內置的調度演算法選擇合適的Node進行調度,也可以在Pod的定義中使用NodeName、NodeSelector或NodeAffinity來指定滿足條件的Node進行調度。
1)NodeName
Pod.spec.nodeName用於強制約束將Pod調度到指定的Node節點上,這里說是「調度」,但其實指定了nodeName的Pod會直接跳過Scheler的調度邏輯,直接寫入PodList列表,該匹配規則是強制匹配。
2)NodeSelector:定向調度
Kubernetes Master上的scheler服務(kube-Scheler進程)負責實現Pod的調度,整個過程通過一系列復雜的演算法,最終為每個Pod計算出一個最佳的目標節點,通常我們無法知道Pod最終會被調度到哪個節點上。實際情況中,我們需要將Pod調度到我們指定的節點上,可以通過Node的標簽和pod的nodeSelector屬性相匹配來達到目的。
Pod.spec.nodeSelector是通過kubernetes的label-selector機制進行節點選擇,由scheler調度策略MatchNodeSelector進行label匹配,調度pod到目標節點,該匹配規則是強制約束。
啟用節點選擇器的步驟為:
kubectl label nodes <node-name> <label-key>=<label-value>
例: #kubectllabel nodes k8s-node-1 zonenorth
運行kubectl create -f命令創建Pod,scheler就會將該Pod調度到擁有zone=north標簽的Node上。 如果多個Node擁有該標簽,則會根據調度演算法在該組Node上選一個可用的進行Pod調度。
需要注意的是:如果集群中沒有擁有該標簽的Node,則這個Pod也無法被成功調度。
3)NodeAffinity:親和性調度
該調度策略是將來替換NodeSelector的新一代調度策略。由於NodeSelector通過Node的Label進行精確匹配,所有NodeAffinity增加了In、NotIn、Exists、DoesNotexist、Gt、Lt等操作符來選擇Node。調度側露更加靈活。
9.2 DaemonSet:特定場景調度
DaemonSet用於管理集群中每個Node上僅運行一份Pod的副本實例,如圖:
這種用法適合一些有下列需求的應用:
在實際生產環境中,我們經常遇到某個服務需要擴容的場景,也有可能因為資源精確需要縮減資源而需要減少服務實例數量,此時我們可以Kubernetes中RC提供scale機制來完成這些工作。
以redis-slave RC為例,已定義的最初副本數量為2,通過kubectl scale命令可以將Pod副本數量
#kubectl scale rc redis-slave --replicas=3
ReplicationController"redis-slave" scaled
#kubectl get pods
除了可以手工通過kubectl scale命令完成Pod的擴容和縮容操作以外,新版本新增加了Horizontal Podautoscaler(HPA)的控制器,用於實現基於CPU使用路進行啟動Pod擴容縮容的功能。該控制器基於Mastger的kube-controller-manager服務啟動參數 --horizontal-pod-autoscler-sync-period定義的時長(默認30秒),周期性監控目標Pod的Cpu使用率並在滿足條件時對ReplicationController或Deployment中的Pod副本數量進行調整,以符合用戶定義的平均Pod Cpu使用率,Pod Cpu使用率來源於heapster組件,所以需預先安裝好heapster。
當集群中的某個服務需要升級時,我們需要停止目前與該服務相關的所有Pod,然後重新拉取鏡像並啟動。如果集群規模較大,因服務全部停止後升級的方式將導致長時間的服務不可用。由此,Kubernetes提供了rolling-update(滾動升級)功能來解決該問題。
滾動升級通過執行kubectl rolling-update命令一鍵完成,該命令創建一個新的RC,然後自動控制舊版本的Pod數量逐漸減少到0,同時新的RC中的Pod副本數量從0逐步增加到目標值,最終實現Pod的升級。需要注意的是,系統要求新的RC需要與舊的RC在相同的Namespace內,即不能把別人的資產轉到到自家名下。
例:將redis-master從1.0版本升級到2.0:
需要注意的點:
運行kubectl rolling-update來完成Pod的滾動升級:
#kubectl rolling-update redis-master -f redis-master-controller-v2.yaml
另一種方法就是不使用配置文件,直接用kubectl rolling-update加上--image參數指定新版鏡像名來完成Pod的滾動升級
#kubectl rolling-update redis-master --image=redis-master:2.0
與使用配置文件的方式不同的是,執行的結果是舊的RC被刪除,新的RC仍然使用就的RC的名字。
如果在更新過程總發現配置有誤,則用戶可以中斷更新操作,並通過執行kubectl rolling-update-rollback完成Pod版本的回滾。
⑹ 超值一篇分享,Docker:從入門到實戰過程全記錄
作者 | 天元浪子
來源 | CSDN博客
想要真正理解Docker,就不得不從虛擬化技術的發展歷程說起。普遍認為虛擬化技術經歷了物理機時代、虛擬機時代,目前已經進入到了容器化時代。可以說,Docker是虛擬化技術不斷發展的必然結果。
那麼,什麼是容器呢?容器和虛擬機有什麼不同?Docker和容器又是什麼關系呢?搞明白這幾個問題,Docker的概念就清晰了。
1.1 虛擬機和容器
藉助於VMWare等軟體,可以在一台計算機上創建多個虛擬機,每個虛擬機都擁有獨立的操作系統,可以各自獨立的運行程序。這種分身術雖然隔離度高(操作系統級),使用方便(類似物理機),但佔用存儲資源多(GB級)、啟動速度慢(分鍾級)的缺點也是顯而易見的。
相較於虛擬機,容器(Container)是一種輕量型的虛擬化技術,它虛擬的是最簡運行環境(類似於沙盒)而非操作系統,啟動速度快(秒級)、佔用存儲資源少(KB級或MB級),容器間隔離度為進程級。在一台計算機上可以運行上千個容器,這是容器技術對虛擬機的碾壓式優勢。
1.2 容器、鏡像和Docker
Docker是一個開源的應用容器引擎,可以創建容器以及基於容器運行的程序。Docker可以讓開發者打包他們的應用和依賴包到一個輕量級、可移植的容器中,然後發布到任何流行的Linux機器上,也可以實現虛擬化。
聽起來很簡單,但是在Docker和容器之間,還隱藏著一個鏡像的概念,令初學者頗感困惑。本質上,Docker鏡像是一個特殊的文件系統,它提供容器運行時所需的程序、庫、資源、配置等文件。Docker鏡像類似於一個py文件,它需要Docker的運行時(類似於Python解釋器)運行。鏡像被運行時,即創建了一個鏡像的實例,一個實例就是一個容器。
1.3 Docker 和 k8s
作為容器引擎,Docker為容器化的應用程序提供了開放的標准,使得開發者可以用管理應用程序的方式來管理基礎架構,實現快速交付、測試和部署代碼。隨著容器的大量使用,又產生了如何協調、調度和管理容器的問題,Docker的容器編排應運而生。
k8s是Google開源的一個容器編排引擎,它支持自動化部署、大規模可伸縮、應用容器化管理,是一個開源的,用於管理雲平台中多個主機上的容器化的應用,k8s的目標是讓部署容器化的應用簡單並且高效,k8s提供了應用部署、規劃、更新、維護的一種機制。
Docker和k8sr都是以containerd(容器化標准)作為運行時,因此使用Docker創建的鏡像完全可以在k8s中無障礙的使用。
2.1 在ubuntu中安裝
在linux系統中安裝Docker非常簡單,官方為我們提供了一鍵安裝腳本。這個方法也適用於Debian或CentOS等發行版。
安裝過程如果出現超時,不要灰心,多試幾次,總會成功的。安裝完成後,Docker只能被root用戶使用,可以使用下面的命令取消許可權限制:
然後,重啟docker服務:
最後,關閉當前的命令行,重新打開新的命令行就可以了。
順便提一下,如果在CentOS下安裝,可能會出現一堆類似於下面的錯誤:
這是由於docker和Podman沖突造成的,需要先卸載Podman:
2.2 在Win10中安裝
Docker的運行,依賴linux的環境,官方提供了Docker Desktop for Windows,但是它需要安裝Hyper-V,Hyper-V是微軟開發的虛擬機,類似於 VMWare 或 VirtualBox,僅適用於 Windows 10。這個虛擬機一旦啟用,QEMU、VirtualBox 或 VMWare Workstation 15 及以下版本將無法使用!如果你必須在電腦上使用其他虛擬機(例如開發 Android 應用必須使用的模擬器),請不要使用 Hyper-V!
我的電腦是win10家庭版,不能直接安裝hyper-v,需要將下面的命令保存到cmd文件中:
然後在cmd文件上點擊右鍵,選擇使用管理員運行。執行完畢後會重啟,在重啟的過程中進行安裝。
2.3 Hello world
docker服務啟動的情況下,運行下面的命令:
此命令的含義是:
第一次運行時,因為本地沒有ubuntu:20.04鏡像,docker會自動從鏡像伺服器下載。下載過程可能需要多試幾次,只要成功一次,以後執行就不再需要下載了。
docker官方還提供了一個hello-world鏡像,可以直接運行:
此命令省略了鏡像版本和運行參數,docker使用latest作為版本,即最新版本。
從hello world的例子中,也可以體驗到,docker實例的運行是非常快的。
docker官方的鏡像庫比較慢,在進行鏡像操作之前,需要將鏡像源設置為國內的站點。
新建文件/etc/docker/daemon.json,輸入如下內容:
然後重啟docker的服務:
3.1 列出本地所有鏡像
執行命令 docker images 可以查看
當前我本地只有剛才安裝的兩個鏡像。
3.2 從鏡像庫中查找鏡像
執行命令 docker search 鏡像名稱可以從docker鏡像庫中查找鏡像。
最好選擇官方(OFFICIAL)的鏡像,這樣的鏡像最穩定一些。
3.3 下載新的鏡像
執行命令docker pull 鏡像名稱:版本號即可下載新的鏡像。
鏡像下載後,就可以使用鏡像來創建容器了。
4.1 啟動容器
執行命令docker run即可啟動容器,也就是創建某個鏡像的實例。docker run命令非常復雜,可以先執行一個docker run --help來查看幫助:
比如我們要執行python的shell,需要添加-it參數,即:docker run -it python:3.8
4.2 將宿主機的文件掛載到容器
docker容器與宿主機是隔離的,要想讓容器內的程序能訪問宿主機上的文件,需要通過-v參數將宿主機的文件掛載到容器中。
比如我們在宿主機上有一個hello.py,可以列印hello,想要在python容器中執行,就需要進行掛載。-v後還需要接兩個參數,分別是宿主機的目錄和容器內的目錄,兩者使用:分隔,路徑必須都是絕對路徑。
我的hello.py保存在主目錄的/docker_test目錄中,將這個目錄掛載到容器的/docker_test目錄,然後在容器內執行python /docker_test/hello.py:
4.3 容器的埠映射
我們修改一下hello.py,創建一個socket服務端,並監聽5000埠,當有客戶端連接時,列印客戶端的地址,先客戶端發送hello,然後關閉連接:
在容器內執行:
接下來,嘗試用telnet命令連接,結果卻是失敗的。原因是,127.0.0.1是宿主機的ip地址,5000是容器的埠,這與我們的習慣稍微有些不同。事實上,docker的容器是非常輕量的,它並沒有自己的網路,要想訪問容器的埠,需要進行埠映射,將容器的某埠映射到宿主機的埠,客戶端連接時,只要與宿主機的埠進行連接就可以了。
需要注意的是,上面的代碼創建的伺服器,無論如何也不可能被客戶端連接,因為代碼中綁定了127.0.0.1的ip,在容器中運行時,需要綁定所有ip,即0.0.0.0。
然後,再使用-p參數,-p還需要三個參數,即宿主機的ip地址、宿主機的埠、容器的埠,三者之間使用:分隔。一般的,可以將宿主機的ip地址省略,只寫宿主機的埠:容器的埠即可。
這樣,就將容器的5000埠映射到了宿主機的5001埠,使用:
即可與容器中的伺服器進行連接。
4.4 容器管理
上面的服務運行之後,可以使用docker ps命令,查看運行中的容器:
顯示的內容有下面幾列:
要想結束容器,可以使用docker kill 容器ID命令。
一般而言,當我們的程序開發完成後,會連同程序文件與運行環境一起製作成一個新的鏡像。
要製作鏡像,需要編寫Dockerfile。DockeFile由多個命令組成,常用的命令有:
注意,Docker鏡像中有一個層的概念,每執行一個RUN命令,就會創建一個層,層過多會導致鏡像文件體積增大。盡量在RUN命令中使用&&連接多條shell命令,減少RUN命令的個數,可以有效減小鏡像文件的體積。
5.1 自製顯示文本文件內容鏡像
編寫cat.py,接收一個文件名,由python讀取文件並顯示文件的內容:
這個例子比較簡單,縮寫Dockerfile如下:
這個Dockerfile的含義是:
需要說明的是,ENTRYPOINT有兩種寫法:
這里採用第二種寫法,是因為我們要在外部給容器傳遞參數。執行命令編譯Docker鏡像:
這個命令中,-t的含義是目標,即生成的鏡像名為hello,版本號為1.0,別忘了最後那個.,這叫到上下文路徑,是指 docker 在構建鏡像,有時候想要使用到本機的文件(比如復制),docker build 命令得知這個路徑後,會將路徑下的所有內容打包。
這樣,我們的第一個鏡像就製作完成了,使用下面的命令執行它:
即可看到~/docker_test/cat/files/test.txt的內容。
5.2 自製web伺服器鏡像
我們使用tornado開發一個網站,而python的官方鏡像是沒有tornado庫的,這就需要在製作鏡像時進行安裝。
測試的ws.py如下:
編寫Dockerfile文件如下:
在此我們驗證一下CMD與ENTRYPOINT的區別。在Dockerfile所在有目錄下執行如下命令:
執行完成後,再使用docker images使用就可以看到生成的鏡像了,然後使用下面的命令運行:
在瀏覽器中輸入宿主機的ip和8000埠,就可以看到頁面了。
在這個例子中,我使用的運行命令是CMD,如果在docker run中指定的其他的命令,此命令就不會被執行,如:
此時,容器中被執行的是python命令,而不是我們的服務。在更多情況下,我們希望在docker run命令中為我們的服務傳參,而不是覆蓋執行命令,那麼,我們應該使用ENTRYPOINT而不是CMD:
上面這種寫法,是不支持傳遞參數的,ENTRYPOINT和CMD還支持另一種寫法:
使用這種寫法,docker run命令中的參數才可以傳遞給hello.py:
這個命令中,--port=9000被作為參數傳遞到hello.py中,因此容器內的埠就成了9000。
在生產環境中運行時,不會使用-it選項,而是使用-d選項,讓容器在後台運行:
這種方式下,即使當前的控制台被關閉,該容器也不會停止。
5.3 自製apscheler服務鏡像
接下來,製作一個使用apscheler編寫的服務鏡像,代碼如下:
Dockerfile也是信手拈來:
生成鏡像:
應該可以運行了,文件復制需要兩個目錄,在運行時,可以使用兩次-v來掛載不同的目錄:
前面用到的官方python鏡像大小足足882MB,在這個基礎上,再安裝用到的第三方庫,添加項目需要的圖片等資源,大小很容易就超過1個G,這么大的鏡像,網路傳給客戶非常的不方便,因此,減小鏡像的體積是非常必要的工作。
docker hub上有個一python:3.8-alpine鏡像,大小隻有44.5MB。之所以小,是因為alpine是一個採用了busybox架構的操作系統,一般用於嵌入式應用。我嘗試使用這個鏡像,發現安裝一般的庫還好,但如果想安裝numpy等就會困難重重,甚至網上都找不到解決方案。
還是很回到基本的路線上來,主流的操作系統鏡像,ubuntu的大小為72.9MB,centos的大小為209MB——這也算是我更喜歡使用ubuntu的一個重要原因吧!使用ubuntu作為基礎鏡像,安裝python後的大小為139MB,再安裝pip後的大小一下子上升到了407MB,要是再安裝點其他東西,很容易就趕上或超過python官方鏡像的大小了。
看來,尋常路線是很難壓縮鏡像文件體積了。幸好,還有一條曲線救國的路可走,這就是多階段構建法。
多階段構建的思想其實很簡單,先構建一個大而全的鏡像,然後只把鏡像中有用的部分拿出來,放在一個新的鏡像里。在我們的場景下,pip只在構建鏡像的過程中需要,而對運行我們的程序卻一點用處也沒有。我們只需要安裝pip,再用pip安裝第三方庫,然後將第三方庫從這個鏡像中復制到一個只有python,沒有pip的鏡像中,這樣,pip佔用的268MB空間就可以被節省出來了。
1、在ubuntu鏡像的基礎上安裝python:
然後運行:
這樣,就生成了python:3.8-ubuntu鏡像。
2、在python:3.8-ubuntu的基礎上安裝pip:
然後運行:
這樣,就生成了python:3.8-ubuntu-pip鏡像。
3、多階段構建目標鏡像:
這個dockerfile需要解釋一下了,因為它有兩個FROM命令。
第一個是以python:3.8-ubuntu-pip鏡像為基礎,安裝numpy,當然,在實際應用中,把所有用到的第三方庫出寫在這里。
第二個FROM是以FROM python:3.8-ubuntu鏡像為基礎,將第三方庫統統復制過來,COPY命令後的–from=0的意思是從第0階段進行復制。實際應用中再從上下文中復製程序代碼,添加需要的ENTRYPOINT等。
最後,再運行:
這然,用於我們項目的鏡像就做好了。比使用官方python鏡像構建的版本,小了大約750MB。
到此,我們的鏡像已經製作好了,可是,鏡像文件在哪,如何在生產環境下運行呢?
剛才使用docker images命令時,已經看到了生成的鏡像:
我們可以使用docker save命令將鏡像保存到指定的文件中,保存的文件是一個.tar格式的壓縮文件:
將hello.tar復制到生產環境的機器上,然後執行導入命令:
就可以使用了。
⑺ 外部三層交換機其他網段內網如何訪問docker
1、在Docker容器中運行的應用程序需要綁定到宿主機上的一個埠,以便其他計算機可以通過該埠訪問該應用程序棚脊。可以使用dockerrun命令的-p選項來指定要綁定的埠。
2、確保Docker容器和其他計算機都連接到同一個外部三層交換機,並且都在同一個子網中。這樣,其他計算機才能夠通過交換機訪問到Docker容器。
3、配置交換機的路物敬由表,將其他網段內網的流量路由到與Docker容器所在子網相連的埠上。可以使用命令行或者圖形化工具來完成這一步驟。
4、如果使用的是Linux操作系統,需鏈螞滲要打開Docker容器的防火牆埠。
⑻ 簡述Kubernetes外部如何訪問集群內的服務
對於Kubernetes,集群外的客戶端默認情況,無法通過Pod的IP地址或者Service的虛擬IP地址:虛擬埠號進行訪問。通常可以通過以下方式進行訪問Kubernetes集群內的服務:
映射Pod到物理機:將Pod埠號映射到宿主機,即在Pod中採用hostPort方式,以使客戶端應用能夠通過物理機訪問容器應用。
映射Service到物理機:將Service埠號映射到宿主機,即在Service中採用nodePort方式,以使客戶端應用能夠通過物理機訪問容器應用。
映射Sercie到LoadBalancer:通過設置LoadBalancer映射到雲服務商提供的LoadBalancer地址。這種用法僅用於在公有雲服務提供商的雲平台上設置Service的場景。我推薦你去看看時速雲,他們是一家全棧雲原生技術服務提供商,提供雲原生應用及數據平台產品,其中涵蓋容器雲PaaS、DevOps、微服務治理、服務網格、API網關等。大家可以去體驗一下。 如果我的回答能夠對您有幫助的話,求給大大的贊。
⑼ macvlan技術實現了什麼主機的容器訪問
其它容器、網路中的其它設備。
1、其它容器。在多台宿主機器構成的容器集群中,使用macvlan技術可以將各容器創建為不同的虛擬子網,實現容器之間的跨宿頌皮嘩主機訪問。
2、網路中的其它設備。使野行用macvlan技術可以將容器接入至物理交換機或路由器中,獲得與網路中其它設備握冊(其它宿主機器、其它伺服器、PC機、手機等)進行通信的能力。
⑽ 如何訪問docker里的redis
創建一個redis docker容器
首先,我們先為redis創建一個Dockerfile
FROM ubuntu:12.10
RUN apt-get update
RUN apt-get -y install redis-server
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server"]
現在你需要通過Dockerfile創建一個鏡像,將替換成你自己的名字。
sudo docker build -t /redis .
運行服務
使用我們剛才創建的redis鏡像
使用 -d 運行這個服務分離模式,讓容器在後台運行。
重要的是我們沒有開放容器埠,相反,我們將使用一個容器來連接redis容器資料庫
sudo docker run -name redis -d /redis
創建你的web應用容器
現在我們可以創建我們的應用程序容器,我們使用-link參數來創建一個連接redis容器,我們使用別名db,這將會在redis容器和redis實例容器中創建一個安全的通信隧道
sudo docker run -link redis:db -i -t ubuntu:12.10 /bin/bash
進入我們剛才創建的容器,我們需要安裝redis的redis-cli的二進制包來測試連接
apt-get update
apt-get -y install redis-server
service redis-server stop
現在我們可以測試連接,首先我么要先查看下web應用程序容器的環境變數,我們可以用我們的ip和埠來連接redis容器
env
. . .
DB_NAME=/violet_wolf/db
DB_PORT_6379_TCP_PORT=6379
DB_PORT=tcp://172.17.0.33:6379
DB_PORT_6379_TCP=tcp://172.17.0.33:6379
DB_PORT_6379_TCP_ADDR=172.17.0.33
DB_PORT_6379_TCP_PROTO=tcp
我們可以看到我們有一個DB為前綴的環境變數列表,DB來自指定別名連接我們的現在的容器,讓我們使用DB_PORT_6379_TCP_ADDR變數連接到Redis容器。
redis-cli -h $DB_PORT_6379_TCP_ADDR
redis 172.17.0.33:6379>
redis 172.17.0.33:6379> set docker awesome
OK
redis 172.17.0.33:6379> get docker
"awesome"
redis 172.17.0.33:6379> exit
我們可以很容易的使用這個或者其他環境變數在我們的web應用程序容器上連接到redis容器