多容器Pod
訪問Pod
查看Pod日誌
在前一節我們提到Pod是一個容器集合,本節將會創建多個容器的Pod,讓大家更加深入了解Pod。
Pod創建成功以後,可以向Pod發送請求,訪問容器中的進程,本節會提供一種簡單的方式訪問容器,便於大家測試。
查看Pod的日誌對我們調試程序很有用,這是我們往後會經常會用到的。
最後,同一Pod內容器之間如何聯通,以及區別是什麼,弄懂這些可以加深我們對Pod的理解。
好了,廢話少說,我們開始吧。
本節實驗使用單節點K8S集群即可。
測試鏡像需要兩個,一個使用httpd鏡像,另一個使用上一節使用的程序做鏡像,步驟如下:
在根目錄下創建test1文件夾,在該文件夾下,創建Dockerfile文件以及app.js文件。
Dockerfile內容如下:
FROM node:7ADD app.js /app.jsENTRYPOINT ["node", "app.js"]
上面用到的app.js文件內容如下:
const http = require('http');const os = require('os');console.log("server1 starting...");var handler = function(request, response) { console.log("server1 Received request from " + request.connection.remoteAddress); response.writeHead(200); response.end("server1 You've hit " + os.hostname() + "\n");};var www = http.createServer(handler);www.listen(8080);
使用如下命令構建容器鏡像:
docker build -t first_image .
操作截圖如下:
鏡像構建成功後,推送到自己在docker上的倉庫,操作步驟如下:
先打標籤,命令如下:
docker tag first_image:latest huqianakls/first_image:latestdocker login -u huqianakls 包括兩個容器 "containers": [ { "image": "huqianakls/first_image:latest", "imagePullPolicy": "Always", "name": "firstcontainer", "ports": [ { "containerPort": 8080, "protocol": "TCP" } ], "resources": {}, "terminationMessagePath": "/dev/termination-log", "terminationMessagePolicy": "File", "volumeMounts": [ { "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", "name": "default-token-7td7w", "readOnly": true } ] }, { "image": "httpd:latest", "imagePullPolicy": "Always", "name": "secondcontainer", "ports": [ { "containerPort": 80, "protocol": "TCP" } ], "resources": {}, "terminationMessagePath": "/dev/termination-log", "terminationMessagePolicy": "File", "volumeMounts": [ { "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", "name": "default-token-7td7w", "readOnly": true } ] } ], ......省略...... }, "status": { .......省略...... 容器是否準備好 "restartCount": 0, "state": { "running": { "startedAt": "2019-09-20T07:48:35Z" } } }, { "containerID": "docker://20a0145721a8aa05b2fdf90ad2a52e839f4603f14b75b4573067346aa4f83bd1", "image": "httpd:2.4", "imageID": "docker-pullable://httpd@sha256:39d7d9a3ab93c0ad68ee7ea237722ed1b0016ff6974d80581022a53ec1e58797", "lastState": {}, "name": "secondcontainer", "ready": true, Pod的狀態 "podIP": "192.168.219.76", "qosClass": "BestEffort", "startTime": "2019-09-20T07:48:30Z" }}
上面的結果內容我刪減了一部分,重要的屬性我寫了注釋。
目前使用一種簡單的方式來訪問Pod,使用埠轉發方式,命令如下:
kubectl port-forward Pod名稱 主機埠:容器埠
對於multicontainerpod,我們配置埠轉發如下:
kubectl port-forward multicontainerpod 8081:8080kubectl port-forward multicontainerpod 8082:80
由於有兩個埠,因此需要配置兩個埠轉發。
注意,如果出現如下錯誤:
錯誤信息為:unable to do port forwarding: socat not found。解決方法是安裝socat軟體,運行如下命令安裝:
yum install -y socat
上述兩個命令會導致終端被佔,此時需要另起終端訪問,訪問結果如下:
從結果可以看出,訪問成功。
訪問httpd,結果如下:
訪問成功。
查看日誌可以使用docker的原生命令:
docker logs 容器ID
該命令只能查詢容器的日誌,不能查詢Pod的整體日誌。如果需要查詢Pod的日誌,使用如下命令:
Kubectl logs Pod名稱 -c 容器名稱
查詢multicontainerpod日誌,不指定容器名稱,執行截圖如下:
執行失敗,從錯誤結果可以看出,如果一個Pod包含多個容器需要指定具體某個容器名稱。關於單容器Pod查詢日誌大家可以自行測試一下。
添加容器名稱,查詢結果如下:
查詢成功。
問題:同一Pod內容器之間是否可以互相訪問呢?如果可以,方式是什麼?
下面通過實驗回答該問題:
構建新的鏡像,dockerfile使用實驗環境構建部分中的內容,app.js改為下面內容:
const http = require('http');const os = require('os');console.log("server2 starting...");var handler = function(request, response) { console.log("server2 Received request from " + request.connection.remoteAddress); response.writeHead(200); response.end("server2 You've hit " + os.hostname() + "\n");};var www = http.createServer(handler);www.listen(8081);
將"server1"改為"server2",監聽埠改為8081。
使用docker build構建鏡像,名字為second_image:latest,並推送到docker倉庫。
創建Pod,配置如下:
apiVersion: v1kind: Podmetadata: name: test1spec: containers: - image: huqianakls/first_image:latest name: con1 ports: - containerPort: 8080 protocol: TCP - image: huqianakls/second_image:latest name: con2 ports: - containerPort: 8081 protocol: TCP
使用kubectl create -f 命令創建Pod。
使用docker exec -it 命令分別進入con1和con2兩個容器,執行hostname命令,查看容器主機名,運行過程如下:
從結果可以看出,兩個容器的主機名是一樣的。
接著查詢兩個容器的網絡配置,命令為ip r,運行過程如下:
可以看出,兩個容器的網絡配置是一樣的。
既然網路配置一樣,兩個容器應該可以使用 curl 127.0.0.1埠 互相訪問,測試如下:
測試成功。
下面我們使用ps aux命令分別查看兩個容器的進程信息:
從結果可以看出,兩個容器的進程信息不完全一致,說明他們的進程命名空間是不一樣的。不過現在新版本的docker和K8S是可以共享進程命名空間的,只是需要配置,默認情況下不共享。
最後,我們來測試一下兩個容器的文件系統是否一樣,在一個容器中創建文件,然後去另一個容器中查看該文件是否存在:
可見,兩個容器不共享文件系統。文件系統由容器鏡像決定,因此,同一Pod的中的容器不共享文件系統。
從上面的測試可以知道:
1、同一Pod內的容器共享主機名;
2、同一Pod內的容器共享網絡;
3、默認情況下,同一Pod內容器不共享進程命名空間;
4、同一Pod內的容器不共享文件系統;
1、創建包含兩個容器的Pod;
2、訪問Pod中的容器,並查看容器日誌;
3、測試同一Pod兩個容器的連通性和隔離性;