K8S動手教程2.2:Pod多容器,訪問,日誌

2020-09-10 韋陀學院

內容摘要

多容器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

目前使用一種簡單的方式來訪問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內容器聯通與隔離

問題:同一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兩個容器的連通性和隔離性;

相關焦點

  • K8S動手教程2.1:第1個Pod
    構建完成後,將鏡像push到自己在hub.docker.com中的容器倉庫,步驟如下:1、給新構建的鏡像打tagdocker tag first_pod huqianakls/first_pod:latest注意:huqianakls 是dockers上的帳號或者id號,使用/隔開,/後面就是鏡像名和tag;2、登錄自己的帳號
  • K8S動手教程2.5:Pod健康檢查
    httpGet表示使用http的方式檢查容器是否健康,path是訪問路徑。從配置可以看出,健康檢查會訪問app.js文件中接口,該接口在訪問3次以後,會返回500錯誤,此時容器會處於不正常狀態。運行該Pod,觀察健康檢查如何發生作用。
  • 每天5分鐘|輕鬆掌握開發工作中必會的k8s-pod介紹和安裝nginx
    (2)學校做統計的時候會很方便,比如這次的疫情下統計健康情況,班級1 和班級2都很健康,班級3不正常。數據很容易觀察。(3)同一個班級裡面的學生共享一份教材即可,節省了資源。01—pod的介紹k8s最重要的功能之一就是資源的管理和調度,對於pod的理解和我們上面提到的班級的例子類似。
  • 認識和理解k8s中的pod
    序言在大部分的k8s教程中,都是先講k8s的基本理論,對於剛剛接觸k8s的同學來說,可能一臉懵逼,望而生畏,所以我帶領大家一步步動手部署,在部署的過程中一步步教大家理解其中的概念,讓更多的技術人員邁入k8s的大門。
  • 一個小需求,自動重啟k8s集群中日誌不刷新的POD
    ,筆者就經常遇到這種情況,pod狀態是running,但是程序卻沒有響應。發生這種情況的原因有很多種,有可能是因為k8s健康檢查的原因,比如使用ps檢查進程;或者是程序內部死循環,但是不退出;再或者網絡閃斷,程序無法重連等等。無論什麼原因,都會有解決辦法,但是優化需要時間,在未完全解決之前,問題不能不解決,於是想到了一個臨時方案,因為筆者公司項目日誌是直接列印在stdout的,發生了程序無響應的情況,比較簡單的一個辦法是判斷日誌輸出的時間。
  • 使用client-go獲取pod日誌
    我們在使用kubectl查看一個pod的日誌時:我們要先找到pod namekubectl -n task get pod然後查看日誌,需要輸入一堆參數kubectl -n tasks logs kube-proxy-worker-hqwn4 --tail 1 -f
  • filebeat收集K8S日誌,寫入自動創建的索引
    與傳統的日誌收集不同:pod所在節點不固定,每個pod中運行filebeat,配置繁瑣且浪費資源;pod的日誌目錄一般以emptydir方式掛載在宿主機,目錄不固定,filebeat無法自動匹配;pod持續增多,filebeat需要做到自動檢測並收集;因此最好的收集方式為node節點上的一個filebeat
  • 輕量級日誌系統Loki原理簡介和使用
    alert設置metric達到某個特定的基數觸發了告警僅僅這些日誌是不能夠解決問題的 還需要看下應用的日誌k8s的基本單位是podpod把日誌輸出到stdout和stderr當某個pod的內存變得很大觸發了我們的alert這個時候管理員去頁面查詢確認是哪個pod有問題然後要確認pod內存變大的原因
  • K8s使用metric-server讓pod自動擴縮容
    /{namespace}/pods/{pod} 特定 pod 的指標,指標名稱為PodMetrics未來將能夠支持指標聚合,如 max 最大值,min 最小值,95th 峰值,以及自定義時間窗口,如 1h,1d,1w 等。
  • K8S動手教程2.3:Pod標籤和選擇器
    根據標籤查詢Pod為了測試,創建1個新Pod,配置內容為:apiVersion: v1kind: Podmetadata: name: apppod2 labels: app: myapp2rel: v2.0spec: containers: - image: huqianakls/app1:latest name: appcon2 ports: - containerPort: 8080 protocol: TCP下面我來測試下查詢Pod:1、查詢標籤app值為myapp2的Pod命令為:kubectl get pod
  • K8S動手教程2.4:Pod註解和命名空間
    不同namespace中可以創建同名的Pod,下面我們在namespace2下創建apppod6,將namespace改為namespace2。刪除Pod1、按照名稱刪除命令為:kubectl delete pod Pod名稱1 Pod名稱2......
  • Kubernetes ELK 日誌收集
    一般來說,這種agent用一個容器來運行,可以訪問該節點上所有應用程式容器的日誌文件所在目錄由於這種agent必須在每個節點上運行,所以需要使用DaemonSet控制器運行該應用程式。但是sidecar容器中運行日誌採集代理程序會導致大量資源消耗,因為每個Pod都需要啟動2個容器,業務容器和採集代理程序,另外無法使用kubectl logs命令來訪問這些日誌,因為他們不受kubelet控制下面是Kubernetes官方的一個fluentd的配置文件實例,使用Configmap保存配置文件,通過Pod中啟動
  • K8S權限控制,限制用戶在特定namespace上的訪問權限
    K8Skubernetes應用越來越廣泛,我們kubernetes集群中也會根據業務來劃分不同的命名空間,隨之而來的就是安全權限問題,我們不可能把集群管理員帳號分配給每一個人,有時候可能需要限制某用戶對某些特定命名空間的權限,比如開發和測試人員也可能需要登錄集群,了解應用的運行情況,查看pod
  • 我司基於K8s高可用集群架構
    在這個過程中需要有三個步驟:測試用例、打包鏡像、更新pod。第一次部署服務在k8s集群環境的時候可能需要:創建namespace、創建imagepullsecret、創建pv(storageclass)、創建deployment(pod controller)、創建svc、創建ingress、等。
  • k8s三部曲第一章第3節 k8s架構基本原理
    borg系統2)架構* 一個master節點 * api server k8s網關,所有的指令請求都必須經過api server * scheduler 調度器,使用調度算法,把請求資源調度某一個node節點 * controller 控制器,維護k8s資源對象 * etcd 存儲資源對象* node節點
  • 從kubectl top看K8S監控原理
    這裡可以對比下kubect get pod時的日誌:的監控數據是核心指標(HPA調度),應該和 pod 本身擁有同等地位,即 metric應該作為一種資源存在,如metrics.k8s.io 的形式,稱之為 Metric Api於是官方從
  • k8s三部曲第二章第1節 pod核心原理
    1.pod核心原理概念:k8s的作用k8s是用來管理容器,但不直接操作容器,最小操作單元是pod(間接管理容器)特點:1).一個master有一群node節點2).master節點不存儲容器,只是負責調度、網關、控制器、資源對象存儲
  • K8S整體架構解析,簡單明了
    master節點主要負責集群的控制,對pod進行調度,已經令牌管理等等功能。node節點主要是負責幹活,啟動容器、管理容器。master節點和node節點一般不要部署在一臺機器上。上面這個架構圖,舉例是一個master節點和2個node節點。但實際生產上,從高可用考慮,是需要部署多個master節點的。
  • 擁抱雲原生,如何將開源項目用k8s部署?
    涉及到幾個核心內容: otter基本架構 dockerfile編寫 deployment編寫 啟動腳本改造 K8s中固定ip/port訪問2.otter的基本架構那麼,對於k8s部署來說,可以採用同一份鏡像,然後在不同環境(k8s的不同namespace)中將otter.properties作為ConfigMap寫入,最後通過volume的形式掛載到pod的指定路徑上。這裡對幾個名詞做簡單介紹,詳細內容可以參考k8s官方文檔。