K8S知识点记录
文章目錄
- 一.K8s組件
- 整體調(diào)用
- 各個組件調(diào)用關(guān)系
- 二.K8s常用知識點
- 1.Namespace
- 創(chuàng)建namespace
- 查看namespace
- 在namespace中創(chuàng)建資源
- 查看namespace pods
- 2.Pod
- 創(chuàng)建nginx pod,port-forward 實現(xiàn)本地訪問
- 創(chuàng)建一個redis pod,掛載conf文件
- 3.Service
- service是什么?
- Service的類型
- 2.1 ClusterIp
- 2.2 NodePort類型
- 2.3 LoadBalancer
- service的三種端口
- kubectl expose
- 集群內(nèi)訪問 Service
- 4.Ingress
- Ingress Controoler
- 高可靠部署架構(gòu)
- 有哪些部署方案 ?
- 方案一:Deployment + LB
- 方案二:Daemonset + HostNetwork + LB
- 方案三:Deployment + LB 直通 Pod
- 5.Deployment
- Deployment 通過 ReplicaSet 來管理 Pod
- 查看副本詳細信息:
- rollout history
- StatefulSet 無狀態(tài)服務(wù)
- 6 kube-dns發(fā)現(xiàn)服務(wù)
- 7.k8s Endpoints
- 8.externalTrafficPolicy
- 9.Kube-proxy
- iptables
- ipvs
- 10. hpa
- 三.配置存儲 configmap secret
- pod env
- secret
- 2.secret使用
- 配置熱更新之reloader
- 四.安全認證
- secret 創(chuàng)建tls
- 創(chuàng)建https的負載均衡
- k8s
- PersistentVolume、PersistentVolumeClaim和StorageClass的概念關(guān)系
- pv pvc
- StorageClass
- k8s監(jiān)控
- 探針
- scale 彈性伸縮命令
- 彈性伸縮 監(jiān)控
- Internet到k8s的流量
- k8s 的一些命令
- 9-4 ReplicationController 與 deployment 關(guān)系
- port-forward
- K8S反向代理ip
- LoadBalancer
- nodeport(節(jié)點端口)的外部流量策略
- k8s 好用的工具🔧
- kubens命名空間切換工具
- k9s
- k8s 發(fā)布模式
- 藍綠發(fā)布:兩套環(huán)境交替升級,舊版本保留一定時間便于回滾。
- 灰度發(fā)布:根據(jù)比例將老版本升級,例如80%用戶訪問是老版本,20%用戶訪問是新版本。
- 滾動發(fā)布:按批次停止老版本實例,啟動新版本實例。
一.K8s組件
整體調(diào)用
各個組件調(diào)用關(guān)系
二.K8s常用知識點
1.Namespace
Namespace用于對k8s中資源對象的分組。namespace之間沒有嵌套或?qū)蛹夑P(guān)系。一個資源對象只能屬于一個namespace。不同組之間的對象是隔離的,互相不可見。
常見的pods, services, replication controllers和deployments等都是屬于某一個namespace的(默認是default),而node, persistentVolumes等則不屬于任何namespace。
Namespace 適合用于隔離不同用戶創(chuàng)建的資源。
注意:namespace無法保證網(wǎng)絡(luò)的隔離性,比如說service可以跨namespace訪問。
默認來說Kubernetes具有如下3個namespace:
- default: k8s默認的namespace,如果操作如果不指明namespace,默認會操作名為default的namespace。
- kube-system: k8s系統(tǒng)自己運行所需的資源對象所在的namespace。
- kube-public: k8s自動創(chuàng)建的namespace,對所有用戶可見。適合放置集群范圍都可見的服務(wù)。
創(chuàng)建namespace
#test.yaml:kind: Namespace apiVersion: v1 metadata:name: test labels:name: test ╰─? kubectl apply -f test.yaml --validate=false 1 ? namespace/test created查看namespace
kubectl get namespace在namespace中創(chuàng)建資源
Pod YAML文件
apiVersion: v1 kind: Pod metadata:name: mypodnamespace: testlabels:name: mypod spec:containers:- name: mypodimage: nginx ╰─? kubectl apply -f nginx-pod.yaml 1 ? pod/mypod created查看namespace pods
╰─? kubectl get pods --namespace=test NAME READY STATUS RESTARTS AGE mypod 1/1 Running 0 5m4s```2.Pod
k8s 創(chuàng)建的pod會被分配到不同的 Node 上
一般是使用deployment 來創(chuàng)建 與管理 pod
創(chuàng)建nginx pod,port-forward 實現(xiàn)本地訪問
-
創(chuàng)建nginx pod
k create -f nginx-pod.yamlnginx-pod.yaml
apiVersion: v1 kind: Pod metadata:name: nginxlabels:name: nginx spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80 -
查看pod狀態(tài)
-
進入pod容器中查看nginx
k exec -it nginx /bin/bash -
本地端口映射
k port-forward nginx 8080:80
創(chuàng)建一個redis pod,掛載conf文件
redis.conf
3.Service
service是什么?
在說明Service是什么之前先了解下Service的使用場景:
當(dāng)客戶端想要訪問K8S集群中的pod時,需要知道pod的ip以及端口,那K8S中如何在不知道pod的地址信息的情況下進行pod服務(wù)的快速連接?
若某一node上的pod發(fā)生故障,K8S最大的特點就是能夠給感知和重啟該pod,但是pod重啟后ip會發(fā)生變化,那么客戶端如何感知并保持對pod的訪問?
如果多個pod組合在一起形成pod組,如何在被訪問時達到負載均衡的效果?
針對上面三種需求,K8S提出了Service的概念,意在解決上述三個問題和場景,下面?zhèn)z看看Service的定義:
Kubernetes Service是為了管理具有相同功能的一組Pod而定義的一種對象,Service具體的作用和場景如下:
-
通過Pod的Label Selector訪問Pod組。
-
Service的IP保持不變(Headless Servcie除外,下面會單獨講),保證了訪問接口的穩(wěn)定性,屏蔽了Pod的IP地址變化帶來的影響,進而實現(xiàn)解耦合。雖然這樣,還是建議使用ServiceName進行訪問。
-
Service通過kube-proxy借助iptables/ipvs提供負載均衡的能力,實現(xiàn)反向代理,將請求轉(zhuǎn)發(fā)到合適的Pod上。
Service可以看作是一組提供相同服務(wù)的Pod對外的訪問接口。借助Service,應(yīng)用可以方便地實現(xiàn)服務(wù)發(fā)現(xiàn)和負載均衡。
Service的類型
在Serive定義時,我們需要指定spec.type字段,這個字段擁有四個選項:
- ClusterIP。默認值。給這個Service分配一個Cluster IP,它是Kubernetes系統(tǒng)自動分配的虛擬IP,因此只能在集群內(nèi)部訪問。
- NodePort。將Service通過指定的Node上的端口暴露給外部。通過此方法,訪問任意一個NodeIP:nodePort都將路由到ClusterIP,從而成功獲得該服務(wù)。
- LoadBalancer。在 NodePort 的基礎(chǔ)上,借助 cloud provider 創(chuàng)建一個外部的負載均衡器,并將請求轉(zhuǎn)發(fā)到 :NodePort。此模式只能在云服務(wù)器(AWS等)上使用。
- ExternalName。將服務(wù)通過 DNS CNAME 記錄方式轉(zhuǎn)發(fā)到指定的域名(通過 spec.externlName 設(shè)定)。需要 kube-dns 版本在 1.7 以上。
2.1 ClusterIp
ClusterIP主要在每個node節(jié)點使用iptables,將發(fā)向ClusterIP對應(yīng)端口的數(shù)據(jù),轉(zhuǎn)發(fā)到kube-proxy中。然后kube-proxy自己內(nèi)部實現(xiàn)有負載均衡的方法,并可以查詢到這個service下對應(yīng)pod的地址和端口,進而把數(shù)據(jù)轉(zhuǎn)發(fā)給對應(yīng)的pod的地址和端口。
2.2 NodePort類型
在定義Service時指定spec.type=NodePort,并指定spec.ports.nodePort的值,Kubernetes就會在集群中的每一個Node上打開你定義的這個端口,這樣,就能夠從外部通過任意一個NodeIP:nodePort訪問到這個Service了。
NodePort的原理在于在 Node上開了一個端口,將向該端口的流量導(dǎo)入到 kube-proxy,然后由 kube-proxy進一步到給對應(yīng)的 pod。
這種類型的service工作流程為:
Client----->NodeIP:NodePort----->ClusterIP:ServicePort----->PodIP:ContainerPort
https://www.jianshu.com/p/72e0d3033ab8
下面是一個簡單的例子:
apiVersion: v1 kind: Service metadata:name: nginx-servicelabels:run: nginx spec:selector:app: nginxports:- port: 80nodePort: 30001targetPort: 5003type: NodePort假如有3個app: nginx Pod運行在3個不同的Node中,那么此時客戶端訪問任意一個Node的30001端口都能訪問到這個nginx服務(wù)。
NodeIP: 30001=> ClusterIP:80 => PodIP:5003
2.3 LoadBalancer
LoadBalancer和NodePort其實是同一種方式。區(qū)別在于LoadBalancer比NodePort多了一步,就是可以調(diào)用Cloud provider去創(chuàng)建LB來向節(jié)點導(dǎo)流。
使用云提供商的負載均衡器向外部暴露服務(wù)。 外部負載均衡器可以將流量路由到自動創(chuàng)建的 NodePort 服務(wù)和 ClusterIP 服務(wù)上。
service的三種端口
port
service暴露在cluster ip上的端口,:port 是提供給集群內(nèi)部客戶訪問service的入口。
nodePort
nodePort是k8s提供給集群外部客戶訪問service入口的一種方式,:nodePort 是提供給集群外部客戶訪問service的入口。
targetPort
targetPort是pod上的端口,從port和nodePort上到來的數(shù)據(jù)最終經(jīng)過kube-proxy流入到后端pod的targetPort上進入容器。
port、nodePort總結(jié)
總的來說,port和nodePort都是service的端口,前者暴露給集群內(nèi)客戶訪問服務(wù),后者暴露給集群外客戶訪問服務(wù)。從這兩個端口到來的數(shù)據(jù)都需要經(jīng)過反向代理kube-proxy流入后端pod的targetPod,從而到達pod上的容器內(nèi)。
kubectl expose
將資源暴露為新的Kubernetes Service。
指定deployment、service、replica set、replication controller或pod ,并使用該資源的選擇器作為指定端口上新服務(wù)的選擇器。deployment 或 replica set只有當(dāng)其選擇器可轉(zhuǎn)換為service支持的選擇器時,即當(dāng)選擇器僅包含matchLabels組件時才會作為暴露新的Service。
為RC的nginx創(chuàng)建service,并通過Service的80端口轉(zhuǎn)發(fā)至容器的8000端口上。
kubectl expose rc nginx --port=80 --target-port=8000集群內(nèi)訪問 Service
在集群里面,其他 pod 要怎么訪問到我們所創(chuàng)建的這個 service 呢?有三種方式:
首先我們可以通過 service 的虛擬 IP 去訪問,比如說剛創(chuàng)建的 my-service 這個服務(wù),通過 kubectl get svc 或者 kubectl discribe service 都可以看到它的虛擬 IP 地址是 172.29.3.27,端口是 80,然后就可以通過這個虛擬 IP 及端口在 pod 里面直接訪問到這個 service 的地址。
第二種方式直接訪問服務(wù)名,依靠 DNS 解析,就是同一個 namespace 里 pod 可以直接通過 service 的名字去訪問到剛才所聲明的這個 service。不同的 namespace 里面,我們可以通過 service 名字加“.”,然后加 service 所在的哪個 namespace 去訪問這個 service,例如我們直接用 curl 去訪問,就是 my-service:80 就可以訪問到這個 service。
第三種是通過環(huán)境變量訪問,在同一個 namespace 里的 pod 啟動時,K8s 會把 service 的一些 IP 地址、端口,以及一些簡單的配置,通過環(huán)境變量的方式放到 K8s 的 pod 里面。在 K8s pod 的容器啟動之后,通過讀取系統(tǒng)的環(huán)境變量比讀取到 namespace 里面其他 service 配置的一個地址,或者是它的端口號等等。比如在集群的某一個 pod 里面,可以直接通過 curl $ 取到一個環(huán)境變量的值,比如取到 MY_SERVICE_SERVICE_HOST 就是它的一個 IP 地址,MY_SERVICE 就是剛才我們聲明的 MY_SERVICE,SERVICE_PORT 就是它的端口號,這樣也可以請求到集群里面的 MY_SERVICE 這個 service。
4.Ingress
Ingress 包含兩大組件:Ingress Controller 和 Ingress。
Ingress 簡單的理解就是你原來需要改 Nginx 配置,然后配置各種域名對應(yīng)哪個 Service,現(xiàn)在把這個動作抽象出來,變成一個 Ingress 對象,你可以用 yaml 創(chuàng)建,每次不要去改 Nginx 了,直接改 yaml 然后創(chuàng)建/更新就行了;
Ingress Controoler
Ingress Controoler 通過與 Kubernetes API 交互,動態(tài)的去感知集群中 Ingress 規(guī)則變化,并按照規(guī)則模板生成一段 Nginx 配置,再寫到 Nginx Pod 里,最后 reload 一下,工作流程如下圖:
當(dāng)然在實際應(yīng)用中,最新版本 Kubernetes 已經(jīng)將 Nginx 與 Ingress Controller 合并為一個組件,所以 Nginx 無需單獨部署,只需要部署 Ingress Controller 即可
(注意:寫入 nginx.conf 的不是service的地址,而是service backend 的 pod 的地址,避免在 service 在增加一層負載均衡轉(zhuǎn)發(fā))
https://www.jianshu.com/p/3574ecda6417
部署ingress及使用
高可靠部署架構(gòu)
在Kubernetes集群中,Ingress作為集群流量接入層,Ingress的高可靠性顯得尤為重要
當(dāng)您成功創(chuàng)建一個ACK集群后,默認情況下,集群內(nèi)部已經(jīng)部署了一套擁有2個Pod副本的Nginx Ingress Controller服務(wù),其前端掛載在一個公網(wǎng)SLB實例上。
https://help.aliyun.com/document_detail/151524.html
高可靠性首先要解決的就是單點故障問題,一般常用的是采用多副本部署的方式,我們在Kubernetes集群中部署高可靠Ingress接入層同樣采用多節(jié)點部署架構(gòu),同時由于Ingress作為集群流量接入口,建議采用獨占Ingress節(jié)點的方式,以避免業(yè)務(wù)應(yīng)用與Ingress服務(wù)發(fā)生資源爭搶。
如上述部署架構(gòu)圖,由多個獨占Ingress實例組成統(tǒng)一接入層承載集群入口流量,同時可依據(jù)后端業(yè)務(wù)流量水平擴縮容Ingress節(jié)點。當(dāng)然如果您前期的集群規(guī)模并不大,也可以采用將Ingress服務(wù)與業(yè)務(wù)應(yīng)用混部的方式,但建議進行資源限制和隔離。
我們可以通過修改deployment(nginx-ingress-controller)的副本數(shù)來實現(xiàn)高可用,但是由于ingress承載著整個集群流量的接入,所以生產(chǎn)環(huán)境中,建議把ingress通過DaemonSet的方式部署集群中,而且該節(jié)點打上污點不允許業(yè)務(wù)pod進行調(diào)度,以避免業(yè)務(wù)應(yīng)用與Ingress服務(wù)發(fā)生資源爭搶。然后通過SLB把ingress節(jié)點主機添為后端服務(wù)器,進行流量轉(zhuǎn)發(fā)。
Ingress高可用
有哪些部署方案 ?
Nginx Ingress on TKE 部署最佳實踐
方案一:Deployment + LB
在 TKE 上部署 Nginx Ingress 最簡單的方式就是將 Nginx Ingress Controller 以 Deployment 的方式部署,并且為其創(chuàng)建 LoadBalancer 類型的 Service(可以是自動創(chuàng)建 CLB 也可以是綁定已有 CLB),這樣就可以讓 CLB 接收外部流量,然后轉(zhuǎn)發(fā)到 Nginx Ingress 內(nèi)部:
前 TKE 上 LoadBalancer 類型的 Service 默認實現(xiàn)是基于 NodePort,CLB 會綁定各節(jié)點的 NodePort 作為后端 rs,將流量轉(zhuǎn)發(fā)到節(jié)點的 NodePort,然后節(jié)點上再通過 Iptables 或 IPVS 將請求路由到 Service 對應(yīng)的后端 Pod,這里的 Pod 就是 Nginx Ingress Controller 的 Pod。后續(xù)如果有節(jié)點的增刪,CLB 也會自動更新節(jié)點 NodePort 的綁定。
方案二:Daemonset + HostNetwork + LB
方案一雖然簡單,但是流量會經(jīng)過一層 NodePort,會多一層轉(zhuǎn)發(fā)。這種方式有一些缺點:
轉(zhuǎn)發(fā)路徑較長,流量到了 NodePort 還會再經(jīng)過 Kubernetes 內(nèi)部負載均衡,通過 Iptables 或 IPVS 轉(zhuǎn)發(fā)到 Nginx,會增加一點網(wǎng)絡(luò)耗時。
經(jīng)過 NodePort 必然發(fā)生 SNAT,如果流量過于集中容易導(dǎo)致源端口耗盡或者 conntrack 插入沖突導(dǎo)致丟包,引發(fā)部分流量異常。
每個節(jié)點的 NodePort 也充當(dāng)一個負載均衡器,CLB 如果綁定大量節(jié)點的 NodePort,負載均衡的狀態(tài)就分散在每個節(jié)點上,容易導(dǎo)致全局負載不均。
CLB 會對 NodePort 進行健康探測,探測包最終會被轉(zhuǎn)發(fā)到 Nginx Ingress 的 Pod,如果 CLB 綁定的節(jié)點多,Nginx Ingress 的 Pod 少,會導(dǎo)致探測包對 Nginx Ingress 造成較大的壓力。
我們可以讓 Nginx Ingress 使用 hostNetwork,CLB 直接綁節(jié)點 IP + 端口(80,443), 這樣就不用走 NodePort;由于使用 hostNetwork,Nginx Ingress 的 pod 就不能被調(diào)度到同一節(jié)點避免端口監(jiān)聽沖突。通常做法是提前規(guī)劃好,選取部分節(jié)點作為邊緣節(jié)點,專門用于部署 Nginx Ingress,為這些節(jié)點打上 label,然后 Nginx Ingress 以 DaemonSet 方式部署在這些節(jié)點上。下面是架構(gòu)圖:
方案三:Deployment + LB 直通 Pod
方案二雖然相比方案一有一些優(yōu)勢,但同時也引入了手動維護 CLB 和 Nginx Ingress 節(jié)點的運維成本,需要提前規(guī)劃好 Nginx Ingress 的節(jié)點,增刪 Nginx Ingress 節(jié)點時需要手動在 CLB 控制臺綁定和解綁節(jié)點,也無法支持自動擴縮容。如果你的網(wǎng)絡(luò)模式是 VPC-CNI,那么所有的 Pod 都使用的彈性網(wǎng)卡,彈性網(wǎng)卡的 Pod 是支持 CLB 直接綁 Pod 的,可以繞過 NodePort,并且不用手動管理 CLB,支持自動擴縮容:
5.Deployment
在 k8s 中編排應(yīng)用可以更好地做彈性擴容,負載均衡。既然要均衡,一個 Pod 肯定不能均衡,自然要部署多個 Pod
docker-compose 可以簡單地通過 docker-compose scale 來擴容,現(xiàn)在用k8s擴容
在k8s中管理 Pod 的稱作 Controller,我們可以使用 Deployment 這種 Controller 來為 Pod 進行擴容,當(dāng)然它還可以滾動升級,回滾,金絲雀等等關(guān)于部署的事情
Deployment同樣為Kubernetes的一個核心內(nèi)容,主要職責(zé)同樣是為了保證pod的數(shù)量和健康,90%的功能與Replication Controller完全一樣,可以看做新一代的Replication Controller。但是,它又具備了Replication Controller之外的新特性:
Replication Controller全部功能:Deployment繼承了上面描述的Replication Controller全部功能。
-
事件和狀態(tài)查看:可以查看Deployment的升級詳細進度和狀態(tài)。
-
回滾:當(dāng)升級pod鏡像或者相關(guān)參數(shù)的時候發(fā)現(xiàn)問題,可以使用回滾操作回滾到上一個穩(wěn)定的版本或者指定的版本。
-
版本記錄: 每一次對Deployment的操作,都能保存下來,給予后續(xù)可能的回滾使用。
-
暫停和啟動:對于每一次升級,都能夠隨時暫停和啟動。
-
多種升級方案:Recreate:刪除所有已存在的pod,重新創(chuàng)建新的; - RollingUpdate:滾動升級,逐步替換的策略,同時滾動升級時,支持更多的附加參數(shù),例如設(shè)置最大不可用pod數(shù)量,最小升級間隔時間等等。
我們編寫一個 Deployment 的資源配置文件
- spec.template: 指定要部署的 Pod
- spec.replicas: 指定要部署的個數(shù)
- spec.selector: 定位需要管理的 Pod
kubectl get deplouyment命令可以查看 httpd-ken 的狀態(tài),輸出顯示一個副本正常運行。
kubectl describe deployment 了解更詳細的信息
創(chuàng)建了一個 ReplicaSet qa-ibaboss-elk-redis-6446fd4484,
Events 是 Deployment 的日志,記錄了 ReplicaSet 的啟動過程。
Deployment 通過 ReplicaSet 來管理 Pod
接著我們將注意力切換到 qa-ibaboss-elk-redis-6446fd4484,執(zhí)行
╰─? kubectl get replicaset NAME DESIRED CURRENT READY AGE qa-ibaboss-elk-redis-6446fd4484 1 1 1 23m查看副本詳細信息:
kubectl describe replicaset
Controlled By 指明此 ReplicaSet 是由 Deployment httpd-ken 創(chuàng)建。
Events 記錄了兩個副本 Pod 的創(chuàng)建。
rollout history
k rollout history deployment deploymentName回到上一個版本
k rollout undo deployment deploymentNameStatefulSet 無狀態(tài)服務(wù)
6 kube-dns發(fā)現(xiàn)服務(wù)
kube-dns可以解決Service的發(fā)現(xiàn)問題,k8s將Service的名稱當(dāng)做域名注冊到kube-dns中,通過Service的名稱就可以訪問其提供的服務(wù)。
● 在k8s集群中,服務(wù)是運行在Pod中的,Pod的發(fā)現(xiàn)和副本間負載均衡是我們面臨的問題。
● 通過Service可以解決這兩個問題,但訪問Service也需要對應(yīng)的IP,因此又引入了Service發(fā)現(xiàn)的問題。
● 得益于kube-dns插件,我們可以通過域名來訪問集群內(nèi)的Service,解決了Service發(fā)現(xiàn)的問題。
● 為了讓Pod中的容器可以使用kube-dns來解析域名,k8s會修改容器的/etc/resolv.conf配置。
部分 DNS 查詢延遲的問題
經(jīng)過搜索發(fā)現(xiàn)這是一個普遍問題。
根本原因是內(nèi)核conntrack模塊的bug。
https://tencentcloudcontainerteam.github.io/2018/10/26/DNS-5-seconds-delay/
7.k8s Endpoints
endpoint 是k8s集群中一個資源對象,存儲在etcd里面,用來記錄一個service對應(yīng)的所有pod的訪問地址。
簡述: endpoints: 實際上servce服務(wù)后端的pod端點集合
k8s集群中創(chuàng)建一個名為test的service,就h會生成一個同名的endpoint 對象,endpoint對象就是關(guān)聯(lián)pod的ip 地址和端口 (使用kubectl describe svc mongodb -n namespace-name, 查看當(dāng)前的service 下面有一個pod 的)
注意的點:
如果在應(yīng)用程序中直接使用存儲應(yīng)用的ip 地址,考慮如果后期的ip變化了,我們要手動修改應(yīng)用的配置。
當(dāng)然使用configmap也可以解決我說的上述問題,只需要將端點存儲在Configmap里面,并將其作為環(huán)境變量用于代碼中讀取,但是如果端點發(fā)生變化,我們可能要重新所有的應(yīng)用的容器
我們需要能夠在k8s里面像使用同一個命名空間下面的服務(wù)那種直接使用service name 名稱,我們可以使用k8s的靜態(tài)服務(wù)來解決,如果后期需要將有狀態(tài)服務(wù)添加到k8s里面,則代碼不需要任何修改。
8.externalTrafficPolicy
把集群外部的服務(wù)引入到集群內(nèi)部來,在集群內(nèi)部直接使用。沒有任何類型代理被創(chuàng)建,這只有 kubernetes 1.7 或更高版本的 kube-dns 才支持【當(dāng)我們的集群服務(wù)需要訪問k8s之外的集群時,可以選擇這種類型,然后把外部服務(wù)的IP及端口寫入到k8s服務(wù)中來,k8s的代理將會幫助我們訪問到外部的集群服務(wù)】
1 什么是external-traffic-policy
在k8s的Service對象(申明一條訪問通道)中,有一個“externalTrafficPolicy”字段可以設(shè)置。有2個值可以設(shè)置:Cluster或者Local。
1)Cluster表示:流量可以轉(zhuǎn)發(fā)到其他節(jié)點上的Pod。
2)Local表示:流量只發(fā)給本機的Pod。
externalTrafficPolicy=Local
為了解決這個問題, k8s 提供了一個功能,通過設(shè)置 externalTrafficPolicy=Local 可以保留源IP地址
- client sends packet to node2:nodePort, which doesn’t have any endpoints
客戶端發(fā)送tcp包到 node2:nodePort, 但是 node2 并沒有 這個pod - packet is dropped
tcp包被丟棄 - client sends packet to node1:nodePort, which does have endpoints
客戶端發(fā)送數(shù)據(jù)包到 node1:nodePort, node1有pod - node1 routes packet to endpoint with the correct source IP
node1 把包路由到對應(yīng)的pod,那么pod 就可以拿到正確的客戶端源IP地址
缺點是負載均衡可能不是很好,因為一旦容器實例分布在多個節(jié)點上,它只轉(zhuǎn)發(fā)給本機,不跨節(jié)點轉(zhuǎn)發(fā)流量。當(dāng)然,少了一次轉(zhuǎn)發(fā),性能會相對好一丟丟。
注:這種模式下的Service類型只能為外部流量,即:LoadBalancer 或者 NodePort 兩種,否則會報錯。
同時,由于本機不會跨節(jié)點轉(zhuǎn)發(fā)報文,所以要想所有節(jié)點上的容器有負載均衡,就需要上一級的Loadbalancer來做了。
9.Kube-proxy
Kube-proxy 是 kubernetes 工作節(jié)點上的一個網(wǎng)絡(luò)代理組件,運行在每個節(jié)點上。
Kube-proxy維護節(jié)點上的網(wǎng)絡(luò)規(guī)則,實現(xiàn)了Kubernetes Service 概念的一部分 。它的作用是使發(fā)往 Service 的流量(通過ClusterIP和端口)負載均衡到正確的后端Pod。
kube-proxy負責(zé)為Service提供cluster內(nèi)部的服務(wù)發(fā)現(xiàn)和負載均衡,它運行在每個Node計算節(jié)點上,負責(zé)Pod網(wǎng)絡(luò)代理, 它會定時從etcd服務(wù)獲取到service信息來做相應(yīng)的策略,維護網(wǎng)絡(luò)規(guī)則和四層負載均衡工作。在K8s集群中微服務(wù)的負載均衡是由Kube-proxy實現(xiàn)的,它是K8s集群內(nèi)部的負載均衡器,也是一個分布式代理服務(wù)器,在K8s的每個節(jié)點上都有一個,這一設(shè)計體現(xiàn)了它的伸縮性優(yōu)勢,需要訪問服務(wù)的節(jié)點越多,提供負載均衡能力的Kube-proxy就越多,高可用節(jié)點也隨之增多。
service是一組pod的服務(wù)抽象,相當(dāng)于一組pod的LB,負責(zé)將請求分發(fā)給對應(yīng)的pod。service會為這個LB提供一個IP,一般稱為cluster IP。kube-proxy的作用主要是負責(zé)service的實現(xiàn),具體來說,就是實現(xiàn)了內(nèi)部從pod到service和外部的從node port向service的訪問。
代理模式
目前 Kube-proxy 支持4中代理模式:
userspace
iptables
ipvs
kernelspace
其中 kernelspace 專用于windows,userspace 是早期版本的實現(xiàn),本文我們不作過多闡述。
iptables
iptables是一種Linux內(nèi)核功能,旨在成為一種高效的防火墻,具有足夠的靈活性來處理各種常見的數(shù)據(jù)包操作和過濾需求。它允許將靈活的規(guī)則序列附加到內(nèi)核的數(shù)據(jù)包處理管道中的各種鉤子上。
在iptables模式下,kube-proxy將規(guī)則附加到“ NAT預(yù)路由”鉤子上,以實現(xiàn)其NAT和負載均衡功能。這種方法很簡單,使用成熟的內(nèi)核功能,并且可以與通過iptables實現(xiàn)網(wǎng)絡(luò)策略的組件“完美配合”。
默認的策略是,kube-proxy 在 iptables 模式下隨機選擇一個后端。
如果 kube-proxy 在 iptables 模式下運行,并且所選的第一個 Pod 沒有響應(yīng), 則連接失敗。 這與用戶空間模式不同:在這種情況下,kube-proxy 將檢測到與第一個 Pod 的連接已失敗, 并會自動使用其他后端 Pod 重試。
但是,kube-proxy對iptables規(guī)則進行編程的方式是一種O(n)復(fù)雜度的算法,其中n與集群大小(或更確切地說,服務(wù)的數(shù)量和每個服務(wù)背后的后端Pod的數(shù)量)成比例地增長)。
所以綜合上面的例子,對于ipable方式的k8s集群內(nèi)cluster-ip類型的service總結(jié)為:
- 流量從pod network namespace中走到host netwok namespace的docker0中。
- 在host netwok namespace的PREROUTING chain中會經(jīng)過一系列target。
- 在這些target里根據(jù)iptable內(nèi)核隨機模塊來實現(xiàn)匹配endpoint target,隨機比率為均勻分配,實現(xiàn)均勻的負載均衡。
- 在endpoint target里實現(xiàn)了DNAT,也就是將目標(biāo)地址cluster ip轉(zhuǎn)化為實際的pod的ip。
- cluster ip是虛擬ip,不會和任何device綁定。
- 負載均衡為內(nèi)核實現(xiàn),使用均勻負載均衡,不可以有自定義的負載均衡算法。
- 需要host開啟路由轉(zhuǎn)發(fā)功能(net.ipv4.ip_forward = 1)。
- 數(shù)據(jù)包在host netwok namespace中經(jīng)過轉(zhuǎn)換以及DNAT之后,由host network namespace的路由表來決定下一跳地址。
ipvs
IPVS是專門用于負載均衡的Linux內(nèi)核功能。在IPVS模式下,kube-proxy可以對IPVS負載均衡器進行編程,而不是使用iptables。這非常有效,它還使用了成熟的內(nèi)核功能,并且IPVS旨在均衡許多服務(wù)的負載。它具有優(yōu)化的API和優(yōu)化的查找例程,而不是一系列順序規(guī)則。 結(jié)果是IPVS模式下kube-proxy的連接處理的計算復(fù)雜度為O(1)。換句話說,在大多數(shù)情況下,其連接處理性能將保持恒定,而與集群大小無關(guān)。
與 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通信的延遲要短,并且在同步代理規(guī)則時具有更好的性能。 與其他代理模式相比,IPVS 模式還支持更高的網(wǎng)絡(luò)流量吞吐量。
k logs -n kube-system kube-proxy-worker-tm4nm10. hpa
最佳實踐
為了實現(xiàn) K8s 集群中資源的有效調(diào)度和充分利用, K8s 采用requests和limits兩種限制類型來對資源進行容器粒度的分配。每一個容器都可以獨立地設(shè)定相應(yīng)的requests和limits。這 2 個參數(shù)是通過每個容器 containerSpec 的 resources 字段進行設(shè)置的。一般來說,在調(diào)度的時候requests比較重要,在運行時limits比較重要。
resources: requests: cpu: 50mmemory: 50Milimits: cpu: 100mmemory: 100Mirequests定義了對應(yīng)容器需要的最小資源量。這句話的含義是,舉例來講,比如對于一個 Spring Boot 業(yè)務(wù)容器,這里的requests必須是容器鏡像中 JVM 虛擬機需要占用的最少資源。如果這里把 pod 的內(nèi)存requests指定為 10Mi ,顯然是不合理的,JVM 實際占用的內(nèi)存 Xms 超出了 K8s 分配給 pod 的內(nèi)存,導(dǎo)致 pod 內(nèi)存溢出,從而 K8s 不斷重啟 pod 。
limits定義了這個容器最大可以消耗的資源上限,防止過量消耗資源導(dǎo)致資源短缺甚至宕機。特別的,設(shè)置為 0 表示對使用的資源不做限制。值得一提的是,當(dāng)設(shè)置limits而沒有設(shè)置requests時,Kubernetes 默認令requests等于limits。
進一步可以把requests和limits描述的資源分為 2 類:可壓縮資源(例如 CPU )和不可壓縮資源(例如內(nèi)存)。合理地設(shè)置limits參數(shù)對于不可壓縮資源來講尤為重要。
前面我們已經(jīng)知道requests參數(shù)會最終的 K8s 調(diào)度結(jié)果起到直接的顯而易見的影響。借助于 Linux 內(nèi)核 Cgroup 機制,limits參數(shù)實際上是被 K8s 用來約束分配給進程的資源。對于內(nèi)存參數(shù)而言,實際上就是告訴 Linux 內(nèi)核什么時候相關(guān)容器進程可以為了清理空間而被殺死( oom-kill )。
總結(jié)一下:
- 對于 CPU,如果 pod 中服務(wù)使用 CPU 超過設(shè)置的limits,pod 不會被 kill 掉但會被限制。如果沒有設(shè)置 limits ,pod 可以使用全部空閑的 CPU 資源。
- 對于內(nèi)存,當(dāng)一個 pod 使用內(nèi)存超過了設(shè)置的limits,pod 中 container 的進程會被 kernel 因 OOM kill 掉。當(dāng) container 因為 OOM 被 kill 掉時,系統(tǒng)傾向于在其原所在的機器上重啟該 container 或本機或其他重新創(chuàng)建一個 pod。
- 0 <= requests <=Node Allocatable, requests <= limits <= Infinity
https://kubesphere.io/zh/blogs/deep-dive-into-the-k8s-request-and-limit/
三.配置存儲 configmap secret
pod env
apiVersion: v1 kind: Pod metadata:name: envar-demolabels:purpose: demonstrate-envars spec:containers:- name: envar-demo-containerimage: gcr.io/google-samples/node-hello:1.0env:- name: DEMO_GREETINGvalue: "Hello from the environment"secret
Secret介紹
k8s secrets用于存儲和管理一些敏感數(shù)據(jù),比如密碼,token,密鑰等敏感信息。它把 Pod 想要訪問的加密數(shù)據(jù)存放到 Etcd 中。然后用戶就可以通過在 Pod 的容器里掛載 Volume 的方式或者環(huán)境變量的方式訪問到這些 Secret 里保存的信息了。
Secret有三種類型
-
Opaque:base64 編碼格式的 Secret,用來存儲密碼、密鑰等;但數(shù)據(jù)也可以通過base64 –decode解碼得到原始數(shù)據(jù),所有加密性很弱。
#secret.yamlapiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: user: YWRtaW4= pass: MWYyZDFlMmU2N2Rm注:通過yaml創(chuàng)建Opaque類型的Secret值需要base64編碼
kubectl create -f secret.yaml
-
Service Account:用來訪問Kubernetes API,由Kubernetes自動創(chuàng)建,并且會自動掛載到Pod的 /run/secrets/kubernetes.io/serviceaccount 目錄中。
-
kubernetes.io/dockerconfigjson : 用來存儲私有docker registry的認證信息。
用來創(chuàng)建用戶docker registry認證的Secret,直接使用kubectl create命令創(chuàng)建即可,如下:
kubectl create secret docker-registry myregistry --docker-server=DOCKER_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
imagePullSecrets 使用docker registry的認證信息
2.secret使用
方式一:通過Volume掛載的方式
#test-projected-volume.yamlapiVersion: v1 kind: Pod metadata:name: test-projected-volume spec:containers:- name: test-secret-volumeimage: busyboxargs:- sleep- "86400"volumeMounts:- name: mysql-credmountPath: "/projected-volume"readOnly: truevolumes:- name: mysql-credprojected:sources:- secret:name: user- secret:name: pass當(dāng) Pod 變成 Running 狀態(tài)之后,我們再驗證一下這些 Secret 對象是不是已經(jīng)在容器里了:
$ kubectl exec -it test-projected-volume -- /bin/sh $ ls /projected-volume/ user pass $ cat /projected-volume/user admin $ cat /projected-volume/pass 1f2d1e2e67df配置熱更新之reloader
Configmap或Secret使用有兩種方式,一種是env系統(tǒng)變量賦值,一種是volume掛載賦值,env寫入系統(tǒng)的configmap是不會熱更新的,而volume寫入的方式支持熱更新!
對于env環(huán)境的,必須要滾動更新pod才能生效,也就是刪除老的pod,重新使用鏡像拉起新pod加載環(huán)境變量才能生效。
對于volume的方式,雖然內(nèi)容變了,但是需要我們的應(yīng)用直接監(jiān)控configmap的變動,或者一直去更新環(huán)境變量才能在這種情況下達到熱更新的目的。
應(yīng)用不支持熱更新,可以在業(yè)務(wù)容器中啟動一個sidercar容器,監(jiān)控configmap的變動,更新配置文件,或者也滾動更新pod達到更新配置的效果。
Reloader 可以觀察 ConfigMap 和 Secret 中的變化,并通過相關(guān)的 deploymentconfiggs、 deploymentconfiggs、 deploymonset 和 statefulset 對 Pods 進行滾動升級。
通過對比配置sha
https://juejin.cn/post/6897882769624727559
當(dāng) Reloader 檢測到 ConfigMap 發(fā)生變化的時候,會使用 SHA1 計算 ConfigMap 的哈希值(使用 SHA1 是因為它高效且不易發(fā)生沖突),計算完哈希值之后,Reloader 獲取所有的 Deployments,Daemonsets,Statefulsets 和 Rollouts 列表,并查找其 anotations 中是否配置了 Reloader 相關(guān)的注解,比如配置了如下 annotations :
metadata:annotations:reloader.stakater.com/auto: "true"接著 Reloader 會查找配置了 Reloader 相關(guān) annotations 的 Deployments,Daemonsets,Statefulsets 中一個特殊的環(huán)境變量。
如果找到這個環(huán)境變量,則獲取其值并將其與前面計算的新 ConfigMap 哈希值進行比較,如果環(huán)境變量中的舊值與新哈希值不同,則 Reloader 會更新環(huán)境變量。
如果環(huán)境變量不存在,那么它會從 ConfigMap 創(chuàng)建一個具有最新哈希值的新環(huán)境變量并更新相關(guān)的deployment,daemonset或者statefulset。
k8s 檢測到這個環(huán)境變量發(fā)生變化,則會觸發(fā) pod 關(guān)聯(lián)的 deployment,daemonset或者statefulset 的滾動升級。
四.安全認證
secret 創(chuàng)建tls
創(chuàng)建https的負載均衡
apiVersion: v1 kind: Service metadata:annotations:service.beta.kubernetes.io/alibaba-cloud-loadbalancer-cert-id: 1858386724757...service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: 'https:443'service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: slb.s1.smallname: ps-svcnamespace: prod spec:ports:- port: 443protocol: TCPtargetPort: 8091selector:app: ps-devtype: LoadBalancer需要通過service的annotation指定規(guī)格 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: "slb.s1.small"
并且很多k8s service 的annotation不可用,
比如指定使用已創(chuàng)建的負載均衡(推薦)service.beta.kubernetes.io/alicloud-loadbalancer-id:lb-xxxx
k8s
PersistentVolume、PersistentVolumeClaim和StorageClass的概念關(guān)系
pv pvc
如果要求Pod重新調(diào)度后仍然能使用之前讀寫過的數(shù)據(jù),就只能使用網(wǎng)絡(luò)存儲了,網(wǎng)絡(luò)存儲種類非常多且有不同的使用方法,通常一個云服務(wù)提供商至少有塊存儲、文件存儲、對象存儲三種,如華為云的EVS、SFS和OBS。
Kubernetes解決這個問題的方式是抽象了PV(PersistentVolume)和PVC(PersistentVolumeClaim)來解耦這個問題,從而讓使用者不用關(guān)心具體的基礎(chǔ)設(shè)施,當(dāng)需要存儲資源的時候,只要像CPU和內(nèi)存一樣,聲明要多少即可。
-
PV:PV描述的是持久化存儲卷,主要定義的是一個持久化存儲在宿主機上的目錄,比如一個NFS的掛載目錄。
-
PVC:PVC描述的是Pod所希望使用的持久化存儲的屬性,比如,Volume存儲的大小、可讀寫權(quán)限等等。
Kubernetes管理員設(shè)置好網(wǎng)絡(luò)存儲的類型,提供對應(yīng)的PV描述符配置到Kubernetes,使用者需要存儲的時候只需要創(chuàng)建PVC,然后在Pod中使用Volume關(guān)聯(lián)PVC,即可讓Pod使用到存儲資源,它們之間的關(guān)系如下圖所示。
$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv-example 10Gi RWX Retain Bound default/pvc-example 50s可以看到狀態(tài)也變成了Bound,CLAIM是default/pvc-example,表示這個PV綁定了default命名空間下的pvc-example這個PVC。
這里一個比較有意思的地方是CLAIM是default/pvc-example,為什么要顯示default呢,這是因為PV是集群級別的資源,并不屬于某個命名空間,而PVC是命名空間級別的資源,PV可以與任何命名空間的PVC資源綁定。
StorageClass
上節(jié)說的PV和PVC方法雖然能實現(xiàn)屏蔽底層存儲,但是PV創(chuàng)建比較復(fù)雜(可以看到PV中csi字段的配置很麻煩),通常都是由集群管理員管理,這非常不方便。
Kubernetes解決這個問題的方法是提供動態(tài)配置PV的方法,可以自動創(chuàng)PV。管理員可以部署PV配置器(provisioner),然后定義對應(yīng)的StorageClass,這樣開發(fā)者在創(chuàng)建PVC的時候就可以選擇需要創(chuàng)建存儲的類型,PVC會把StorageClass傳遞給PV provisioner,由provisioner自動創(chuàng)建PV。
如CCE就提供csi-disk、csi-nas、csi-obs等StorageClass,在聲明PVC時加上StorageClassName,就可以自動創(chuàng)建PV,并自動創(chuàng)建底層的存儲資源。
使用StorageClass,不僅創(chuàng)建了PVC,而且創(chuàng)建了PV,并且將二者綁定了。
定義了StorageClass后,就可以減少創(chuàng)建并維護PV的工作,PV變成了自動創(chuàng)建,作為使用者,只需要在聲明PVC時指定StorageClassName即可,這就大大減少工作量。
k8s監(jiān)控
探針
https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
scale 彈性伸縮命令
http://docs.kubernetes.org.cn/664.html
k scale rc celery-controller --replicas=2- 動態(tài)彈性伸縮
彈性伸縮 監(jiān)控
go-zero 給出的例子
apiVersion: apps/v1 kind: Deployment metadata:name: go-zero-demo02namespace: testlabels:app: go-zero-demo02 spec:replicas: 1revisionHistoryLimit: 5selector:matchLabels:app: go-zero-demo02template:metadata:labels:app: go-zero-demo02spec:containers:- name: go-zero-demo02image: registry.cn-shanghai.aliyuncs.com/russell-cloud/devlop-docker:latestlifecycle:preStop:exec:command: ["sh","-c","sleep 5"]ports:- containerPort: 8888readinessProbe:tcpSocket:port: 8888initialDelaySeconds: 5periodSeconds: 10livenessProbe:tcpSocket:port: 8888initialDelaySeconds: 15periodSeconds: 20resources:requests:cpu: 500mmemory: 512Milimits:cpu: 1000mmemory: 1024MivolumeMounts:- name: timezonemountPath: /etc/localtimevolumes:- name: timezonehostPath:path: /usr/share/zoneinfo/Asia/Shanghai---apiVersion: v1 kind: Service metadata:name: go-zero-demo02-svcnamespace: test spec:ports:- port: 8888selector:app: go-zero-demo02--- apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata:name: go-zero-demo02-hpa-cnamespace: testlabels:app: go-zero-demo02-hpa-c spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: go-zero-demo02minReplicas: 3maxReplicas: 10metrics:- type: Resourceresource:name: cputargetAverageUtilization: 80--- apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata:name: go-zero-demo02-hpa-mnamespace: testlabels:app: go-zero-demo02-hpa-m spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: go-zero-demo02minReplicas: 3maxReplicas: 10metrics:- type: Resourceresource:name: memorytargetAverageUtilization: 80Internet到k8s的流量
https://blog.csdn.net/weixin_43746433/article/details/114290213
k8s 的一些命令
k config get-contexts 查看當(dāng)前上下文以及對應(yīng)使用的名稱空間
k config view 查看配置信息
k cluster-info 集群信息
9-4 ReplicationController 與 deployment 關(guān)系
Replication Controller為Kubernetes的一個核心內(nèi)容,應(yīng)用托管到Kubernetes之后,需要保證應(yīng)用能夠持續(xù)的運行,Replication Controller就是這個保證的key,主要的功能如下:
- 確保pod數(shù)量:它會確保Kubernetes中有指定數(shù)量的Pod在運行。如果少于指定數(shù)量的pod,Replication Controller會創(chuàng)建新的,反之則會刪除掉多余的以保證Pod數(shù)量不變。
- 確保pod健康:當(dāng)pod不健康,運行出錯或者無法提供服務(wù)時,Replication Controller也會殺死不健康的pod,重新創(chuàng)建新的。
- 彈性伸縮 :在業(yè)務(wù)高峰或者低峰期的時候,可以通過Replication Controller動態(tài)的調(diào)整pod的數(shù)量來提高資源的利用率。同時,配置相應(yīng)的監(jiān)控功能(Hroizontal Pod Autoscaler),會定時自動從監(jiān)控平臺獲取Replication Controller關(guān)聯(lián)pod的整體資源使用情況,做到自動伸縮。
- 滾動升級:滾動升級為一種平滑的升級方式,通過逐步替換的策略,保證整體系統(tǒng)的穩(wěn)定,在初始化升級的時候就可以及時發(fā)現(xiàn)和解決問題,避免問題不斷擴大。
port-forward
這是一種通過 kubectl port-forward 指令來實現(xiàn)數(shù)據(jù)轉(zhuǎn)發(fā)的方法。kubectl port-forward 命令可以為 Pod 設(shè)置端口轉(zhuǎn)發(fā),通過在本機指定監(jiān)聽端口,訪問這些端口的請求將會被轉(zhuǎn)發(fā)到 Pod 的容器中對應(yīng)的端口上。
首先,我們來看下 Kubernetes Port Forward 這種方式的工作機制:
使用 Kubectl 創(chuàng)建 Port Forward 后,Kubectl 會主動監(jiān)聽指定的本地端口。
當(dāng)向 Local-Port 建立端口連接并向該端口發(fā)送數(shù)據(jù)時,數(shù)據(jù)流向會經(jīng)過以下步驟:
1].數(shù)據(jù)發(fā)往 Kubctl 監(jiān)聽的 Local-Port。
2].Kubectl 通過 SPDY 協(xié)議將數(shù)據(jù)發(fā)送給 ApiServer。
3].ApiServer 與目標(biāo)節(jié)點的 Kubelet 建立連接,并通過 SPDY 協(xié)議將數(shù)據(jù)發(fā)送到目標(biāo) Pod 的端口上。
4].目標(biāo)節(jié)點的 Kubelet 收到數(shù)據(jù)后,通過 PIPE(STDIN、STDOUT)與 Socat 通信。
5].Socat 將 STDIN 的數(shù)據(jù)發(fā)送給 Pod 內(nèi)部指定的容器端口,并將返回的數(shù)據(jù)寫入到 STDOUT。
6].STDOUT 的數(shù)據(jù)由 Kubelet 接收并按照相反的路徑發(fā)送回去。
注:SPDY 協(xié)議將來可能會被替換為 HTTP/2。
-
查看pod
kubectl get pod -
kubectl port-forward 端口映射
kubectl port-forward dev-db-5959f58bd7-88zlm 5432:5432 --address=0.0.0.0 -
啟動Django 本地環(huán)境
DJANGO_SETTINGS_MODULE=project_name.settings_local python3 ./manage.py runserver
K8S反向代理ip
externalName Service是k8s中一個特殊的service類型,它不需要指定selector去選擇哪些pods實例提供服務(wù),而是使用DNS CNAME機制把自己CNAME到你指定的另外一個域名上,你可以提供集群內(nèi)的名字,比如mysql.db.svc這樣的建立在db命名空間內(nèi)的mysql服務(wù),也可以指定http://mysql.example.com這樣的外部真實域名
CNAME是很有用的一個功能,在不同的域名之間搭建橋梁達到明一個域名暗另一個域名,比如github就通過CNAME機制來達到為用戶提供私有域名站點的功能,云服務(wù)商也都是使用CNAME為用戶提供各種各樣的服務(wù)。作為明域名的所有者,我可以用A云來提供服務(wù),哪天我口味變了,我換成B云提供服務(wù),對我的用戶的來說沒有任何感知。
這么好的功能,k8s當(dāng)然要加以利用,那就是externalName Service。從External這個名字看,把外部服務(wù)引入集群的意味相當(dāng)濃烈吧,我提供給pod一個mysql.db.svc這樣一個數(shù)據(jù)庫服務(wù),至于真實的數(shù)據(jù)庫是運行在同一個集群內(nèi),還是在集群外部,pod不在意也不需要關(guān)心,反正能用就成。這就是extenalName的主要用途。
how to set reverse proxy with ingress
項目中 使用yaml文件經(jīng)過脫敏 后如下
apiVersion: v1 kind: Service metadata:name: service_name spec:externalName: "127.0.0.1"ports:- port: 80protocol: TCPtargetPort: 8433type: ExternalName---apiVersion: extensions/v1beta1 kind: Ingress metadata:name: service_nameannotations:kubernetes.io/ingress.class: "nginx"cert-manager.io/cluster-issuer: "letsencrypt-prod"nginx.ingress.kubernetes.io/upstream-vhost: "127.0.0.1" spec:tls:- hosts:- xxx.域名.netsecretName: service_name-oss-tlsrules:- host: xxx.域名.nethttp:paths:- backend:serviceName: service_nameservicePort: 80path: /這樣可以通過xxx.域名.net 的域名訪問 通過 xxx.域名.net (舉例)訪問127.0 .0.1:8433
LoadBalancer
LoadBalancer 只能在service上定義。這是公有云提供的負載均衡器,如AWS、Azure、CloudStack、GCE等。
kind: Service apiVersion: v1 metadata:name: influxdb spec:type: LoadBalancerports:- port: 8086selector:name: influxdb查看服務(wù):
$ kubectl get svc influxdb NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE influxdb 10.97.121.42 10.13.242.236 8086:30051/TCP 39s內(nèi)部可以使用ClusterIP加端口來訪問服務(wù),如19.97.121.42:8086。
外部可以用以下兩種方式訪問該服務(wù):
使用任一節(jié)點的IP加30051端口訪問該服務(wù)
使用EXTERNAL-IP來訪問,這是一個VIP,是云供應(yīng)商提供的負載均衡器IP,如10.13.242.236:8086。
案例, 設(shè)置service 為LoadBalancer類型,公網(wǎng)訪問
k get svc -o wide -n dev NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR scheduler LoadBalancer 172.22.5.138 8.131.97.41 80:31293/TCP 2m31s app=scheduler訪問 http://8.131.97.41/ 成功
nodeport(節(jié)點端口)的外部流量策略
k8s 好用的工具🔧
kubens命名空間切換工具
激活之后 直接可以操作 而不用每次都帶--namespace
k9s
github 1w+ star, 本地操作k8s神器
缺點網(wǎng)速不好會很難受
https://github.com/derailed/k9s
k8s 發(fā)布模式
藍綠發(fā)布:兩套環(huán)境交替升級,舊版本保留一定時間便于回滾。
項目邏輯上分為AB組(冗余),在項目系統(tǒng)時,首先把A組從負載均衡中摘除,進行新版本的部署。B組仍然繼續(xù)提供服務(wù)。
當(dāng)A組升級完畢,負載均衡重新接入A組,再把B組從負載列表中摘除,進行新版本的部署。A組重新提供服務(wù)。
灰度發(fā)布:根據(jù)比例將老版本升級,例如80%用戶訪問是老版本,20%用戶訪問是新版本。
滾動發(fā)布:按批次停止老版本實例,啟動新版本實例。
三種方式均可以做到平滑式升級,在升級過程中服務(wù)仍然保持服務(wù)的連續(xù)性,升級對外界是無感知的。
那生產(chǎn)上選擇哪種部署方法最合適呢?這取決于哪種方法最適合你的業(yè)務(wù)和技術(shù)需求。
如果你們運維自動化能力儲備不夠,肯定是越簡單越好,建議藍綠發(fā)布,如果業(yè)務(wù)對用戶依賴很強,建議灰度發(fā)布。如果是K8S平臺,滾動更新是現(xiàn)成的方案,建議先直接使用。
總結(jié)
- 上一篇: python生僻字如何转码_Python
- 下一篇: 在线代理浏览国外网站_知道这些在线PS网