K8S | 容器和Pod組件
一、場景
作為研發(fā)人員,通常自己電腦的系統(tǒng)環(huán)境都是非常復(fù)雜,在個人的習(xí)慣上,是按照下圖的模塊管理電腦的系統(tǒng)環(huán)境;
對于「基礎(chǔ)設(shè)施」、「主機操作系統(tǒng)」、「系統(tǒng)軟件」來說,通常只做配置修改;
對于自行安裝的軟件環(huán)境來說,個人通常這樣分類:「應(yīng)用軟件」、「研發(fā)軟件」、「持續(xù)集成」、「虛擬機環(huán)境」;
- 應(yīng)用軟件:主要指常用的辦公軟件,比如文檔編寫,畫圖設(shè)計,通信產(chǎn)品等;
- 研發(fā)軟件:比如基礎(chǔ)開發(fā)環(huán)境,各種中間件環(huán)境,數(shù)據(jù)存儲查詢等;
- 持續(xù)集成:主流的就是Jenkins、Docker、Kubernetes等組件,整體比較復(fù)雜,不好管理;
- 虛擬機環(huán)境:研發(fā)必備的Linux操作系統(tǒng),用來部署一些標(biāo)準(zhǔn)的組件集群;
不論是這些軟件環(huán)境還是虛擬機系統(tǒng)的搭建,基本都是通過下載軟件安裝包,然后在本地部署和定期更新以及運行,基于這個場景再去理解容器和Pod組件,會輕松許多;
二、容器
1、容器鏡像
參考上面系統(tǒng)環(huán)境的管理,軟件包和安裝部署的原理;
Docker容器鏡像是一個輕量級的、獨立的、可執(zhí)行的軟件包,它包含了運行應(yīng)用程序所需的一切:代碼、運行時、系統(tǒng)工具、系統(tǒng)庫和設(shè)置,帶有創(chuàng)建Docker容器的說明;
可以通過Dockerfile腳本自定義鏡像,也可以使用云端倉庫中其他人公開發(fā)布的,生產(chǎn)環(huán)境通常采用私有倉庫管理鏡像;
容器鏡像所承載的是封裝了應(yīng)用程序及其所有軟件依賴的二進制數(shù)據(jù),容器鏡像是可執(zhí)行的軟件包,可以單獨運行;通常會創(chuàng)建應(yīng)用的容器鏡像并將其推送到某倉庫,然后在Pod中引用它;
2、容器
容器將應(yīng)用程序從底層的主機設(shè)施中解耦,這使得在不同的云或OS環(huán)境中部署更加容易;
容器的本質(zhì)就是一個視圖隔離、可限制資源、獨立文件系統(tǒng)的進程集合;
以常見的Linux研發(fā)環(huán)境來分析,可以限制容器的資源分配,比如內(nèi)存大小、CPU使用,隔離進程之間的通信,設(shè)置獨立的文件系統(tǒng)等;
Kubernetes集群中的每個節(jié)點都會運行容器,這些容器構(gòu)成分配給該節(jié)點的Pod,單個Pod中的容器會在共同調(diào)度下,于同一位置運行在相同的節(jié)點上;
從整體上可以把K8S理解為「操作系統(tǒng)」,鏡像理解為「軟件安裝包」,容器理解為「應(yīng)用進程」;
3、實踐案例
制作鏡像,首先將代碼工程auto-client和auto-serve打包,然后構(gòu)建鏡像文件,放在本地環(huán)境中;
- 制作【auto-client】鏡像
構(gòu)建命令
docker build -t auto-client:latest .
Dockerfile腳本
# 基礎(chǔ)鏡像
FROM openjdk:8
# 維護者
MAINTAINER cicadasmile
# 持久化目錄
VOLUME /data/docker/logs
# 添加應(yīng)用服務(wù)JAR包
ADD auto-client.jar application.jar
# 配置參數(shù)
ENTRYPOINT ["java","-Dspring.profiles.active=dev","-Djava.security.egd=file:/dev/./urandom","-jar","/application.jar"]
- 制作【auto-serve】鏡像
構(gòu)建命令
docker build -t auto-serve:latest .
Dockerfile腳本
# 基礎(chǔ)鏡像
FROM openjdk:8
# 維護者
MAINTAINER cicadasmile
# 持久化目錄
VOLUME /data/docker/logs
# 添加應(yīng)用服務(wù)JAR包
ADD auto-serve.jar application.jar
# 配置參數(shù)
ENTRYPOINT ["java","-Dspring.profiles.active=dev","-Djava.security.egd=file:/dev/./urandom","-jar","/application.jar"]
三、Pod組件
1、基本概念
Pod是可以在K8S中創(chuàng)建和管理的、最小的可部署的計算單元;
Pod是一組(一個或多個)容器,這些容器共享存儲、網(wǎng)絡(luò)、以及怎樣運行這些容器的聲明,Pod中的內(nèi)容總是并置的并且一同調(diào)度,在共享的上下文中運行;
2、Pod管理
【Pod創(chuàng)建】
通常不會直接創(chuàng)建Pod,而是使用諸如Deployment或Job這類工作負(fù)載資源來創(chuàng)建Pod;是相對臨時性的、用后即拋的一次性實體;
【單容器Pod】
每個Pod都意在運行給定應(yīng)用程序的單個實例,可以使用多個Pod對應(yīng)用程序橫向擴展,即一個實例一個Pod對應(yīng),Pod看作單個容器的包裝器由K8S直接管理,是常見的部署方式;
【多容器Pod】
分布式系統(tǒng)中可能存在由多個緊密耦合且需要共享資源的共處容器組成的應(yīng)用程序,比較典型的是「生產(chǎn)消費」場景,Pod將這些容器和存儲資源打包為一個可管理的實體;
Pod中的容器被自動安排到集群中的同一物理機或虛擬機上,并可以一起進行調(diào)度,容器之間可以共享網(wǎng)絡(luò)和存儲資源和依賴、彼此通信、協(xié)調(diào)何時以及何種方式終止自身;
容器之間原本是被隔離開的,而Pod在設(shè)計上可以突破這種隔離,進而實現(xiàn)資源共享;
- 存儲共享
在Pod層面設(shè)置共享的Volume,該Pod中所有容器都可以訪問該共享Volume,這也是Pod組件的存儲方式,Volume還允許Pod中持久數(shù)據(jù)保留下來,即使其中的容器需要重新啟動;
- 網(wǎng)絡(luò)共享
同一個Pod內(nèi),所有容器共享一個IP地址和端口空間,并且可以通過localhost發(fā)現(xiàn)對方;
3、實踐案例
3.1 Pod腳本
在此前的案例中,都是單容器Pod,這里演示多容器Pod,將【auto-client】和【auto-serve】放在同一個「auto-pod」中運行;
并且這里為兩個容器分配CPU和內(nèi)存資源,requests是要為容器指定資源需求,limits是要為容器指定資源限制;
apiVersion: v1
kind: Pod
metadata:
name: auto-pod
spec:
containers:
- name: auto-client
image: auto-client
imagePullPolicy: Never
ports:
- containerPort: 8079
resources:
requests:
cpu: "250m"
memory: "64Mi"
limits:
cpu: "500m"
memory: "128Mi"
- name: auto-serve
image: auto-serve
imagePullPolicy: Never
ports:
- containerPort: 8082
resources:
requests:
cpu: "250m"
memory: "64Mi"
limits:
cpu: "500m"
memory: "128Mi"
3.2 Pod命令
- 創(chuàng)建Pod
kubectl create -f pod.yaml
- 查看指定Pod
kubectl get pod/auto-pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
auto-pod 2/2 Running 0 9m2s 10.1.0.123 docker-desktop <none> <none>
- 查看指定Pod描述
kubectl describe pod/auto-pod
# 此處只展示部分信息
Name: auto-pod
Namespace: default
Node: docker-desktop/192.168.65.11
Status: Running
IP: 10.1.0.123
Containers:
auto-client:
Container ID: docker://Container-ID
Image: auto-client
Image ID: docker://sha256:Image-ID
Port: 8079/TCP
Limits:
cpu: 500m
memory: 128Mi
Requests:
cpu: 250m
memory: 64Mi
auto-serve:
Container ID: docker://Container-ID
Image: auto-serve
Image ID: docker://sha256:Image-ID
Port: 8082/TCP
Limits:
cpu: 500m
memory: 128Mi
Requests:
cpu: 250m
memory: 64Mi
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 38s default-scheduler Successfully assigned default/auto-pod to docker-desktop
Normal Pulled 37s kubelet Container image "auto-client" already present on machine
Normal Created 37s kubelet Created container auto-client
Normal Started 37s kubelet Started container auto-client
Normal Pulled 37s kubelet Container image "auto-serve" already present on machine
Normal Created 37s kubelet Created container auto-serve
Normal Started 37s kubelet Started container auto-serve
- 刪除Pod
kubectl delete -f pod.yaml
3.3 服務(wù)日志
在「auto-client」服務(wù)中,提供一個簡單的定時任務(wù),每10秒訪問一次「auto-serve」的接口,打印請求的響應(yīng)結(jié)果;
@Component
public class HttpJob {
private static final Logger LOG = LoggerFactory.getLogger(HttpJob.class.getName()) ;
private static final String SERVER_URL = "http://localhost:8082/serve";
/**
* 每10秒執(zhí)行一次
*/
@Scheduled(fixedDelay = 10000)
public void systemDate (){
try{
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(3000);
factory.setConnectTimeout(6000);
RestTemplate restTemplate = new RestTemplate(factory);
Map<String,String> paramMap = new HashMap<>() ;
String result = restTemplate.getForObject(SERVER_URL,String.class,paramMap);
LOG.info("server-resp::::"+result);
} catch (Exception e){
e.printStackTrace();
}
}
}
在「auto-serve」服務(wù)中,提供一個簡單的Get請求接口;
@RestController
public class ServeWeb {
private static final Logger logger = LoggerFactory.getLogger(ServeWeb.class) ;
@Value("${server.port:}")
private Integer servePort ;
@GetMapping("/serve")
public String serve (){
logger.info("serve:{}",servePort);
return "serve:"+servePort ;
}
}
查看兩個容器的運行日志,發(fā)現(xiàn)「auto-client」和「auto-serve」可以正常通信,以此來驗證同一個Pod內(nèi)網(wǎng)絡(luò)共享;
4、狀態(tài)與重啟
4.1 重啟策略
可以在Pod中通過restartPolicy屬性設(shè)置重啟策略,常用的取值是Always以降低應(yīng)用的中斷時間,適用于Pod中的所有容器;
- Always:默認(rèn)值,容器失效時,kubelet自動重啟該容器。
- OnFailure:容器停止運行且退出碼不為0時,kubelet自動重啟該容器。
- Never:不論容器是什么狀態(tài),kubelet都不重啟該容器。
4.2 生命周期
- Pending:Pod被Kubernetes系統(tǒng)接受,但有一個或者多個容器未創(chuàng)建,此階段包括等待Pod被調(diào)度的時間和通過網(wǎng)絡(luò)下載鏡像的時間。
- Running:Pod已經(jīng)綁定到了某個節(jié)點,Pod中所有的容器都已被創(chuàng)建,至少有一個容器在運行,或者正處于啟動或重啟狀態(tài)。
- Succeeded:Pod中的所有容器都已成功終止,并且不會再重啟。
- Failed:Pod中的所有容器都已終止,并且至少有一個容器是因為失敗被終止。
- Unknown:因為某些原因無法取得Pod的狀態(tài),通常是因為與Pod所在主機通信失敗。
Pod遵循預(yù)定義的生命周期,起始于Pending階段,如果至少其中有一個主要容器正常啟動,則進入Running階段,之后取決于Pod中是否有容器以失敗狀態(tài)結(jié)束而進入Succeeded或者Failed階段。