學習K8s:從 Deployment 到 Service

K8s,Kubernetes 的縮寫,起源於希臘語意爲舵手、領航員。是一種容器編排工具,於14.7被Docker收購,同類產品有docker swarm:

 

 

k8s master 節點:

master節點:k8s集羣的管理節點,提供集羣資源數據訪問入口,負責運行Api Server進程、Scheduler服務進程、Controller Manager服務進程、etcd存儲服務,負責關聯工作節點 Node。

 

k8s node 節點:

node節點:k8s集羣中運行Pod的服務節點,是k8s集羣最小操作單元,用於承載被分配Pod的運行(Pod宿主機); 關聯Master管理節點,擁有名稱、IP、系統資源信息; 負責運行:docker eninge服務、守護進程kunelet、負載均衡器kube-proxy;

 

每個Node節點都運行一組關鍵進程: Docker Engine:負責本機容器的創建和管理工作; kubelet:負責對 Pod對應的容器的創建、啓停等任務;(Node節點可以在運行時動態增加到K8s集羣中) kube-proxy:實現K8s Service的通信與負載均衡機制的重要組件;

K8s【推薦的、默認的】Node管理方式:kubelet會向master註冊自己,kubelet進程會定時向Master彙報自身情報(如操作系統、Docker版本、CPU和內存,以及有哪些Pod在運行等等),這樣Master可以獲知每個Node節點的資源使用情況,並實現高效均衡的資源調度策略。

 

Pod:是k8s最小的調度單位,包含一/多個container,內部共享一個namespace。

 

什麼是控制器?

K8s 中內建了很多 Controller 控制器,這些相當於一個狀態機,用來控制 Pod 的具體狀態和行爲。

ReplicationController 和 ReplicaSet Deployment(RC、RS)
Deployment
DaemonSet
StateFulSet
Job/CronJob
Horizontal Pod Autoscaling

ReplicationController 和 ReplicaSet:

ReplicationController(RC)用來確保容器應用的副本數始終保持在用戶定義的副本數,即如果有容器異常退出,會自動創建新的 Pod 來替代;而如果異常多出來的容器也會自動回收;在新版本的 Kubernetes 中建議使用 ReplicaSet 來取代 ReplicationController 。ReplicaSet 跟 ReplicationController 沒有本質的不同,只是名字不一樣,並且 ReplicaSet 支持集合式的 selector;

 

RS/RC 與 Deployment 的關聯

apiVersion: extensions/v1beta1 
kind: ReplicaSet
metadata:
    name: frontend
spec:
    replicas: 3
    selector:
        matchLabels:
            tier: frontend
    template:
        metadata: 
            labels:
                tier: frontend
        spec:
            containers:
            -  name: php-redis
                image:  nginx:1.7.9 
                env:
                - name: GET_HOSTS_FROM
                    value: dns
                ports:
                -  containerPort: 80

RS 與 Deployment 的關聯

 

Deployment:

Deployment,是常見的K8s對象類型,提供了對 Pod 和 ReplicaSet 的聲明式定義 (declarative) 方法和管理方式,每個Deployment對應集羣的一次部署,常用來創建 ReplicaSet 和 Pod,解決了 ReplicaSet 更新的諸多問題,用來替代以前的ReplicationController來方便的管理應用。(部署一個新的微服務往往不會直接在集羣中使用 ReplicaSet,因爲ReplicaSet功能不夠強大,不支持一些常見的更新、擴容、縮容運維操作,引入 Deployment 就是爲了支持這些複雜操作。)

在 K8s 集羣中創建 Deployment 對象時,會創建 Deployment 資源、ReplicaSet、三個Pod對象,組成以下的拓撲結構:

 

拓撲結構中的子節點都是穩定的,任意節點刪除都會被 K8s 控制器重啓。

每個 Deployment 都會和它的依賴組成以下的拓撲結構,在這個拓撲結構中的子節點都是『穩定』的,任意節點的刪除都會被 Kubernetes 的控制器重啓。

DeploymentController:負責管理 K8s 集羣中的所有 Deployment 對象,實現 Deployment 對象的各種操作:同步、擴容、重新創建、滾動更新、回滾、暫定恢復、刪除。

Deployment:典型的應用場景包括: ​ ·定義 Deployment 來創建 Pod 和 ReplicaSet; ​ ·滾動升級和回滾應用 ​ ·擴容和縮容; ​ ·暫停和繼續 Deployment;

 

1.部署一個簡單的 Nginx 應用

apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
    name: nginx-deployment
spec:
    replicas: 3
    template:
        metadata: 
            labels:
                app: nginx
        spec:
            containers:
            -  name: nginx
                image:  nginx:1.7.9 
                ports:
                -  containerPort: 80
kubectl  create  -f  https://kubernetes.io/docs/user-guide/nginx-deployment.yaml  --record
## --record 參數可以記錄命令,我們可以很方便的查看每次revision的變化

2.擴容

kubectl  scale  deployment  nginx-deployment  --replicas  10

3.爲 Deployment 設置自動擴展

## (若集羣支持 horizontal pod autoscaling)
kubectl  autoscale  deployment  nginx-deployment  --min=10  --max=15  --cpu-percent=80

4.更新鏡像

kubectl  set  image  deployment/nginx-deployment  nginx=nginx:1.9.1

5.回滾

kubectl  rollout  undo  deployment/nginx-deployment

 

​集羣service管理包括:

  • 網絡代理模式
  • 服務代理
  • 服務發現
  • 發佈服務

概述


​Service 是對一組提供相同功能的 Pods 的抽象,併爲它們提供一個統一的入口。

藉助 Service,應用可以方便的實現服務發現與負載均衡,並實現應用的零宕機升級。

Service 通過標籤來選取服務後端,一般配合 Replication Controller 或者 Deployment 來保證後端容器的正常運行。這些匹配標籤的 Pod IP 和端口列表組成 endpoints,由 kube-proxy 負責將服務 IP 負載均衡到這些 endpoints 上。

Service 有四種類型:

  • ClusterIP:默認類型,自動分配一個僅 cluster 內部可以訪問的虛擬 IP
  • NodePort:在 ClusterIP 基礎上爲 Service 在每臺機器上綁定一個端口,這樣就可以通過 NodeIP:NodePort 來訪問該服務。如果 kube-proxy 設置了 –nodeport-addresses=10.240.0.0/16(v1.10 支持),那麼僅該 NodePort 僅對設置在範圍內的 IP 有效。
  • LoadBalancer:在 NodePort 的基礎上,藉助 cloud provider 創建一個外部的負載均衡器,並將請求轉發到 :NodePort
  • ExternalName:將服務通過 DNS CNAME 記錄方式轉發到指定的域名(通過 spec.externlName 設定)。需要 kube-dns 版本在 1.7 以上。

​​

另外,也可以將已有的服務以 Service 的形式加入到 Kubernetes 集羣中來,只需要在創建 Service 的時候不指定 Label selector,而是在 Service 創建好後手動爲其添加 endpoint。

K8s 的 Service

K8s 中的 Pod 是有生命週期的對象,隨時都有可能由於集羣的狀態變化而被銷燬和創建,此時要面臨的問題:當一些 Pod 需要爲其它 Pod 提供服務時,如何提供同一功能服務的一組 Pod 建立一個抽象並追蹤這組服務中節點的健康狀態。 ​ 這個抽象在 K8s 集羣中就是 Service,每個K8s的 Service 都是一組Pod的邏輯集合和訪問方式的抽象,可以把 Service 加上的一組 Pod 稱爲一個微服務。

K8s Service 定義了這樣一個抽象:一個Pod的邏輯分組,一種夠可以訪問它們的策略 - - 通常稱爲微服務。 這一組Pod能夠被Service訪問到,通常是通過Label Selector。

K8s 中 Service 實現原理: 1.如何處理服務的創建;2.如何轉發來自節點內部和外部的流量;

創建服務:

在 K8s 中創建一個新的 Service 對象需要兩大模塊同時協作:控制器 與 kube-proxy。 控制器,需要在每次客戶端創建新的 Service 對象時生成其他用於暴露一組 Pod 的 K8s 對象,即 Endpoint 對象; kube-proxy,運行在 K8s 集羣中的每一個節點上,會根據 Service 和 Endpoint 的變動改變節點上 iptables 或 ipvs 中保存的規則。

ServiceController 在 Service 對象變動時發生了什麼事情:

 

 

網絡代理模式


擁有三種代理模式:userspace、iptables和ipvs。

現在默認使用iptables,在1.8版本之後增加了ipvs功能。

早期代理的方式

 

client先請求serviceip,經由iptables轉發到kube-proxy上之後再轉發到pod上去。這種方式效率比較低。

當前iptables代理方式

 

​client請求serviceip後會直接轉發到pod上。這種模式性能會高很多。kube-proxy就會負責將pod地址生成在node節點iptables規則中。

ipvs代理方式

這種方式是通過內核模塊ipvs實現轉發,這種效率更高。

服務代理


​​

創建yaml配置文件

創建一個service.yaml文件:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443

selector字段中指定了爲哪一個標籤的app進行負載均衡。ports字段指定了暴露的端口,每一個- name指定一組端口,targetPort爲目標容器的端口。

創建service

kubectl create -f service.yaml

查看service

然後通過命令kubectl get svc查看創建的service

 

通過命令kubectl get endpoints my-service查看創建的service當後端代理的pod的ip 

 

並沒有給它分配pod所以代理的ip爲空。

配置service代理pod

首先查看了一下當前有哪些pod: 

 

現在想讓剛創建的service代理nginx-pod

​​修改service.yaml文件中app:MyAppapp:nginx,這樣就可以匹配到標籤爲app=nginx的pod了。

然後重新生效這個service:

kubectl replace -f service.yaml --force

 

pod已經連接上了。

通過clusterip訪問pod

首先查看下service的clusterip: 

 

然後在節點上可以通過這個ip和端口的方式訪問pod上的應用: 

 

service服務發現


服務發現支持Service環境變量和DNS兩種模式

環境變量

當一個pod運行到node,kubelet會爲每個容器添加一組環境變量,Pod容器中程序就可以使用這些環境變量發現Service。

環境變量名格式如下:

{SVCNAME}_SERVICE_HOST
{SVCNAME}_SERVICE_PORT

 

其中服務名和端口名轉爲大寫,連字符轉換爲下劃線。查看方法是進入pod中輸入env查看環境變量,在程序中調用這個變量就可以訪問這個組件。

​​限制: 
1)Pod和Service的創建順序是有要求的,Service必須在Pod創建之前被創建,否則環境變量不會設置到Pod中。 
2)Pod只能獲取同Namespace中的Service環境變量。

​​

DNS

DNS服務監視Kubernetes API,爲每一個Service創建DNS記錄用於域名解析。這樣Pod中就可以通過DNS域名獲取Service的訪問地址。

工作原理

 

kube-dns用於記錄集羣svc的域名解析相關記錄,dnsmasq主要用於dns緩存。

yaml文件中爲kube-dns指定了一個固定的ip,所以需要注意修改node節點kubelet配置的kube-dns是否爲這個ip(我之前配置的不是,所以要修改)

 

集羣應用發佈


服務類型

ClusterIP: 
分配一個內部集羣IP地址,只能在集羣內部訪問(同Namespace內的Pod),默認ServiceType。

NodePort: 
分配一個內部集羣IP地址,並在每個節點上啓用一個端口來暴露服務,可以在集羣外部訪問。 
訪問地址:<NodeIP>:<NodePort>

LoadBalancer: 
分配一個內部集羣IP地址,並在每個節點上啓用一個端口來暴露服務。 
除此之外,Kubernetes會請求底層雲平臺上的負載均衡器,將每個Node([NodeIP]:[NodePort])作爲後端添加進去。 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章