日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从部署 httpd 入手,理清 k8s 配置中的 containerPort、port、nodePort、targetPort

發布時間:2023/12/4 编程问答 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从部署 httpd 入手,理清 k8s 配置中的 containerPort、port、nodePort、targetPort 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

注:文中各種內網、公網 IP 僅為示例,不保證所有 IP 都可以訪問,且你的環境中 IP 可能不同。

背景

在上一篇文章?自己搭建一個k8s環境?中,我們一頓操作猛如虎,搭建出了由 1 個 master 和 1 個 worker 節點組成的 k8s 集群,大概是這樣的效果:

為了驗證我們搭建的環境是否好使,本篇文章就借搭建 httpd 來復習復習 k8s 的部署,順便理清 k8s 配置中的 containerPort、port、nodePort、targetPort。

如果你沒有聽說過 httpd,那么只需要知道它是一款功能類似于?nginx、IIS?的 Web 服務器,它的全名是 Apache HTTP Server。當部署好后訪問它默認的首頁,會收獲?It Works?這樣一行令人愉快的提示語。

nginx?https://nginx.org/en/
IIS?https://www.iis.net/
Apache HTTP Server?https://httpd.apache.org/

先把最終效果放上,圖中展示了下面會用到的各種 k8s 資源以及訪問效果,閱讀后面的內容時可以對照著圖看看:

部署 httpd

為了部署 httpd,我們需要用到以下知識:

  • Namespace:通過 Namespace 可以對集群內的資源進行分組,例如我希望所有和部署 httpd 有關的資源都在同一個分組中,那么就可以通過設置 namespace 實現(當然,Namespace 還影響著諸如 DNS 等內容,可以在官方文檔中查看)

  • Deployment:我們知道,Pod 是可以在 Kubernetes 中創建和管理的、最小的可部署的計算單元,但通常我們不需要直接創建 Pod,而是通過 Deployment 之類的?工作負載?資源來管理它。所以我們通過 Deployment 來部署 httpd

  • Service:當部署妥當后,需要有一種方式來訪問部署好的程序,Service 就是將 Pod 里的程序公開為網絡服務的抽象方法

Namespace https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
Deployment https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
Pod https://kubernetes.io/zh/docs/concepts/workloads/pods/
工作負載 https://kubernetes.io/zh/docs/concepts/workloads/
Service https://kubernetes.io/zh/docs/concepts/services-networking/service/

了解了相關知識后,馬上開干,我們通過?kubectl?來管理集群,所以需要登錄到 master 節點上來使用?kubectl。

kubectl https://kubernetes.io/zh/docs/reference/kubectl/overview/

下面會通過?yaml?文件的方式創建相關資源,

YAML is a human-friendly data serialization language for all programming languages.
YAML 是一種人類友好的數據序列化語言,適用于所有編程語言。

簡而言之就是通過一種易于書寫和閱讀的格式,來描述數據(和大家熟悉的 JSON 以及 XML 做的事情一樣)。

創建 Namespace

首先創建一個?httpd-namespace.yaml?文件:

apiVersion: v1 kind: Namespace metadata:name: httpd
  • 通過?kind?指定要創建的資源為?Namespace

  • 通過?metadata.name?來指定 Namespace 的名稱

然后執行

kubectl create -f ./httpd-namespace.yaml

表示通過文件創建資源。

然后查看我們創建的 namespace:

kubectl get namespace httpd

得到結果:

NAME STATUS AGE httpd Active 11s

一些資源有自己的縮寫,例如?namespace?可以縮寫為?ns:

kubectl get ns httpd

這樣能少打幾個字母,提高效率。
通過?kubectl api-resources?可以查看相關列表。

創建 Deployment

接下來創建?httpd-deployment.yaml?文件:

apiVersion: apps/v1 kind: Deployment metadata:namespace: httpdname: httpd spec:selector:matchLabels:app: httpdtemplate:metadata:labels:app: httpdspec:containers:- name: httpdimage: httpd:alpineports:- containerPort: 80
  • 通過?kind?指定要創建的資源為?Deployment

  • metadata

    • 通過?namespace?設置該 Deployment 屬于?httpd?Namespace 下

    • 通過?name?將該 Deployment 的名稱設為?httpd(有的朋友喜歡加上前綴或后綴表示是 Deployment,例如?httpd-deployment。都是可以的,只是我個人更喜歡資源類型加名稱已經可以唯一標識一個資源了,就不再添加前后綴了)

  • spec

    • selector?表示 Deployment 如何找到要管理的 Pod。這里使用的?matchLabels?表示,匹配帶有?app?這個 label,且值為?httpd?的 Pod

    • template?中的

    • metadata.labels?會為 Pod 增加?app: httpd?label,這個 label 必須和前面?selector?定義的匹配

    • spec.containers?表示創建一個名為 httpd 的 container,使用?httpd:alpine?鏡像,并開放容器的 80 端口

然后創建 Deployment:

kubectl create -f ./httpd-deployment.yaml

查看創建好的 Deployment:

kubectl get deploy -n httpd
  • deploy?是?deployments?的縮寫

  • 因為我們的 Deployment 在?httpd?Namespace 下,所以還需要?-n?設置 Namespace

可以看到創建好的 Deployment:

NAME READY UP-TO-DATE AVAILABLE AGE httpd 1/1 1 1 17s

由于 Deployment 會為我們管理 Pod,這時 Pod 已經創建好了,查看 Pod:

kubectl get pods -n httpd

可以看到創建好的 Pod:

NAME READY STATUS RESTARTS AGE httpd-76f7455774-mdk4t 1/1 Running 0 33s

由 Deployment 生成的 Pod 的名稱為?httpd?和隨機字符串組成,所以你看到的 Pod 名稱可能和我不同。

觀察 Pod 的網絡

讓我們來看看這個 Pod 的 IP 地址,通過?-o?可以設置輸出的格式:

kubectl get pod -n httpd -o wide

得到的返回如下:

NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-76f7455774-mdk4t 1/1 Running 0 1m15s 10.10.229.95 bun-worker-01 <none> <none>

可以看到 httpd Pod 運行于?bun-worker-01?節點,并且有一個 IP 地址。由于我們開放的端口為?80?,試試訪問一下:

wget -qO - 10.10.229.95

wow,可以訪問,并得到了響應:

<html><body><h1>It works!</h1></body></html>

說明 httpd 工作良好。

再來看看這個 IP 地址?10.10.229.95,和之前通過?kubeadm init?設置的?pod-network-cidr=10.10.0.0/16?正好一致,使用的是我們為 Pod 劃分的網段。

現在,我們的 Worker 節點里大概是這個模樣:

這是不是意味著只要在 master 或 worker 節點上裝一個 nginx 來反向代理這個 IP 地址,就能把 Pod 里的內容發布出去了呢?是,也不是 🤭

我們的這個 Pod 是通過 Deployment 管理的,可以試試刪掉這個 Pod,然后 Deployment 應該自動會重新創建一個新的 Pod:

kubectl delete pod httpd-76f7455774-mdk4t -n httpd kubectl get pods -n httpd -o wide

果然,又創建出一個新的 Pod:

NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-76f7455774-mrx79 1/1 Running 0 6s 10.10.229.96 bun-worker-01 <none> <none>

不過 IP 地址變了😂
當然,也有奇技淫巧可以固定住 Pod 的 IP,但我們并不需要,因為有專業人士負責把 Pod 內的資源公開出去,那就是 Service。

創建 Service

創建?httpd-service.yaml?文件:

apiVersion: v1 kind: Service metadata:namespace: httpdname: httpd spec:selector:app: httpdtype: NodePortports:- protocol: TCPport: 8081targetPort: 80nodePort: 30000
  • 通過?kind?指定要創建的資源為?Service

  • spec

    • selector?用于查找 Service 要服務的 Pod

    • type?這里指定了?NodePort,表示通過 Node 節點的端口暴露服務

    • ports?下面設置了使用的協議為?TCP?以及一系列的端口,后面會介紹(這里特地為各種端口設置了不同的值,方便下面進行試驗)

在生產環境中,一般直接使用的是云廠商提供的負載均衡服務(即?type?設為?LoadBalancer)。但我們的宗旨是低成本(qiong)自建 k8s,所以選用?NodePort?方式非常合適。

創建 Service:

kubectl create -f ./httpd-service.yaml

查看創建好的 Service:

kubectl get svc -n httpd

返回的內容:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpd NodePort 10.1.96.193 <none> 8081:30000/TCP 6s

Cluster IP 和 port

首先來看?CLUSTER-IP,這也是通過?kubeadm init?設置的?service-cidr=10.1.0.0/16?決定的,通過 Cluster IP 可以在集群內部進行通信。

我們進入 httpd 的 Pod 里試驗一下:

kubectl exec -it httpd-76f7455774-mrx79 -n httpd /bin/sh

exec?可以對 Pod 內的容器執行命令,例如這里執行的是?/bin/sh?命令,讓我們可以直接與容器內部進行交互。注意將?exec?后方的 Pod 名稱換成你自己的。

注意:現在,終端的內容來自 httpd Pod 內部。

在 Service 中,我們指定的?port?為?8081,那么通過?ClusterIP:port?就可以訪問到通過 Service 公開的內容:

wget -qO - 10.1.96.193:8081

確實可以,相當于我(httpd Pod)繞了一圈訪問了我自己:

<html><body><h1>It works!</h1></body></html>

k8s 中還有另一種訪問 Service 的方式,那就是通過?<Service 名稱>.<Namespace 名稱>.svc.cluster.local?域名,來試一試:

wget -qO - httpd.httpd.svc.cluster.local:8081

鵝妹子嚶,也可以訪問!
它背后的原理則是創建 Service 時,k8s 會創建對應的?DNS 記錄?,用?nslookup?命令看看?httpd.httpd.svc.cluster.local?解析后的 IP 是哪里:

nslookup httpd.httpd.svc.cluster.local

結果:

Server: 10.1.0.10 Address: 10.1.0.10:53Name: httpd.httpd.svc.cluster.local Address: 10.1.96.193

域名解析后又指向了 Cluster IP。

DNS 記錄 https://kubernetes.io/zh/docs/concepts/services-networking/dns-pod-service/

輸入?exit?退出和 Pod 的交互,回到 master。

Node IP 和 nodePort

nodePort?顧名思義就是從節點上開放的端口,它確實在物理上占用了這個節點(主機)的一個端口,可以通過?NodeIP:nodePort?訪問。在這里 httpd Pod 運行在?bun-worker-01?節點上,節點的 IP 是?172.17.0.2,那么這樣也可以訪問到 httpd:

wget -qO - 172.17.0.2:30000

默認情況下,nodePort?可用的范圍為?30000-32767,當不設置?nodePort?時會在這個范圍內隨機分配一個。

Pod IP 和 targetPort

在 Service 的配置中,如果不設置?targetPort,那么它默認會被設為和?port?一樣的值。不過我們為 Pod 開放的端口為?80,所以在 Service 中配置的?targetPort?需要和 Deployment 中的?containerPort?對應上。

這樣通過?NodeIP:nodePort?以及?ClusterIP:port?來的流量才能通過?PodIP:targetPort?進入到容器中。

通過公網 IP 訪問 httpd

最后,我們可以通過公網訪問 Pod 里的 httpd!因為?NodePort?類型的 Service 是真的在節點上開放了一個端口,即?nodePort,那么我們只需要用節點的公網 IP +?nodePort?就能訪問到 httpd 了!

記得先在云主機的防火墻中開放?30000?端口:

接下打開瀏覽器,見證奇跡。我的?bun-worker-01?節點公網 IP 為?101.35.132.54:

但是不管靜態設置或動態分配節點的 Port 總歸是有些麻煩,而且目前這樣如果想通過域名解析來訪問 httpd,意味著域名后還需要接上?30000?端口才行,且不易實現負載均衡訪問,不是主流的方案。

下一篇我們將使用?ingress-nginx,直接公開節點的?80?和?443?端口,像是安裝了 nginx 一樣,通過簡單的配置,就能使用域名直接訪問 Pod 里的資源。

ingress-nginx https://kubernetes.github.io/ingress-nginx/

總結

以上是生活随笔為你收集整理的从部署 httpd 入手,理清 k8s 配置中的 containerPort、port、nodePort、targetPort的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。