Kubernetes學習-相關概念

Kubernetes架構圖php

上圖能夠看到以下組件,使用特別的圖標表示Service和Label:html

    • Pod
    • Container(容器)
    • Label(label)(標籤)
    • Replication Controller(複製控制器)
    • Service(enter image description here)(服務)
    • Node(節點)
    • Kubernetes Master(Kubernetes主節點)

Pod

  Pod 是Kubernetes的基本操做單元,也是應用運行的載體。整個Kubernetes系統都是圍繞着Pod展開的,好比如何部署運行Pod、如何保證Pod的數量、如何訪問Pod等。另外,Pod是一個或多個機關容器的集合,提供了一種容器的組合的模型。前端

 Pod(上圖綠色方框)安排在節點上,包含一組容器和卷。同一個Pod裏的容器共享同一個網絡命名空間,可使用localhost互相通訊。Pod是短暫的,不是持續性實體。node

    • Pod是短暫的,pod重建的時候數據會丟失對於須要持久化的數據,由於Kubernetes支持的概念,故可使用持久化的卷類型。這樣就能持久化容器數據使其可以跨重啓而存在。
    • 建立Pod時能夠手動建立單個Pod,也可使用Replication Controller使用Pod模板建立出多份拷貝。
    • Pod是短暫的,那麼重啓時IP地址可能會改變,那麼怎麼才能從前端容器正確可靠地指向後臺容器呢?這時可使用Service。

   Pods提供兩種共享資源:網絡和存儲。
網絡:
  每一個Pod被分配一個獨立的IP地址,Pod中的每一個容器共享網絡命名空間,包括IP地址和網絡端口。
  Pod內的容器可使用localhost相互通訊。
  當Pod中的容器與Pod 外部通訊時,他們必須協調如何使用共享網絡資源(如端口)。
存儲:
  Pod能夠指定一組共享存儲volumes。
  Pod中的全部容器均可以訪問共享volumes,容許這些容器共享數據。
  volumes 還用於Pod中的數據持久化,以防其中一個容器須要從新啓動而丟失數據。mysql

 

  • 基本操做

  建立  kubectl create -f xxx.yamlnginx

  查詢  kubectl get pod yourPodName  kubectl describe pod yourPodNamegit

  刪除  kubectl delete pod yourPodNamegithub

  更新  kubectl replace /path/to/yourNewYaml.yamlweb

  •  Pod與容器

  在Docker中,容器是最小的處理單元,增刪改查的對象是容器,容器是一種虛擬化技術,容器之間是隔離的,隔離是基於Linux Namespace實現的。而在Kubernetes中,Pod包含一個或者多個相關的容器,Pod能夠認爲是容器的一種延伸擴展,一個Pod也是一個隔離體,而Pod內部包含的一組容器又是共享的(包括PID、Network、IPC、UTS)。除此以外,Pod中的容器能夠訪問共同的數據捲來實現文件系統的共享。redis

  • Pod與Controller

  Controller能夠建立和管理多個Pod,提供副本管理、滾動升級和集羣級別的自愈能力。若是一個Node故障,Controller就能自動將該節點上的Pod調度到其餘健康的Node上。

  • 鏡像

  在kubernetes中,鏡像的下載策略爲:

    Always:每次都下載最新的鏡像

    Never:只使用本地鏡像,從不下載

    IfNotPresent:只有當本地沒有的時候才下載鏡像

  Pod被分配到Node以後會根據鏡像下載策略進行鏡像下載,能夠根據自身集羣的特色來決定採用何種下載策略。不管何種策略,都要確保Node上有正確的鏡像可用。

  •  其餘

  經過yaml文件,能夠在Pod中設置:

    啓動命令,如:spec-->containers-->command;

    環境變量,如:spec-->containers-->env-->name/value;

    端口橋接,如:spec-->containers-->ports-->containerPort/protocol/hostIP/hostPort(使用hostPort時須要注意端口衝突的問題,不過Kubernetes在調度Pod的時候會檢查宿主機端口是否衝突,好比當兩個Pod均要求綁定宿主機的80端口,Kubernetes將會將這兩個Pod分別調度到不一樣的機器上);

    Host網絡,一些特殊場景下,容器必需要以host方式進行網絡設置(如接收物理機網絡纔可以接收到的組播流),在Pod中也支持host網絡的設置,如:spec-->hostNetwork=true;

    數據持久化,如:spec-->containers-->volumeMounts-->mountPath;

    重啓策略,當Pod中的容器終止退出後,重啓容器的策略。這裏的所謂Pod的重啓,實際上的作法是容器的重建,以前容器中的數據將會丟失,若是須要持久化數據,那麼須要使用數據捲進行持久化設置。Pod支持三種重啓策略:Always(默認策略,當容器終止退出後,老是重啓容器)、OnFailure(當容器終止且異常退出時,重啓)、Never(從不重啓);

  •  Pod生命週期

  Pod被分配到一個Node上以後,就不會離開這個Node,直到被刪除。當某個Pod失敗,首先會被Kubernetes清理掉,以後ReplicationController將會在其它機器上(或本機)重建Pod,重建以後Pod的ID發生了變化,那將會是一個新的Pod。因此,Kubernetes中Pod的遷移,實際指的是在新Node上重建Pod。

 

Replication Controller

  Replication Controller確保任意時間都有指定數量的Pod「副本」在運行。若是爲某個Pod建立了Replication Controller而且指定3個副本,它會建立3個Pod,而且持續監控它們。若是某個Pod不響應,那麼Replication Controller會替換它。

  當建立Replication Controller時,須要指定兩個東西:

    1. Pod模板:用來建立Pod副本的模板
    2. Label:Replication Controller須要監控的Pod的標籤。RC與Pod的關聯是經過Label來實現的。

  使用過程:

  1.   rc.yaml文件

 

apiVersion: v1
kind: ReplicationController
metadata:      #設置rc的元數據
  name: frontend
  labels:
    name: frontend
spec:
  replicas: 3    #設置Pod的具體數量
  selector:    #經過selector來匹配相應的Pod的label
    name: frontend
  template:    #設置Pod的模板
    metadata:
     labels:
       name: frontend
    spec:
     containers:
     - name: frontend
       image: kubeguide/guestbook-php-frontend:latest
    imagePullPolicy: IfNotPresent     #鏡像拉取策略,分爲Always,Never,IfNotPresent,默認是Always env : - name : GET_HOSTS_FROM value : env ports: - containerPort: 80

yaml字段的含義: 
spec.replicas:副本數量3 
spec.selector:RC經過spec.selector來篩選要控制的Pod 
spec.template:這裏寫Pod的定義(但不須要apiVersion和kind) 
spec.template.metadata.labels:Pod的label,能夠看到這個label與spec.selector相同

這個文件的意思: 
定義一個RC對象,它的名字是frontend(metadata.name:frontend),保證有3個Pod運行(spec.replicas:3),Pod的鏡像是kubeguide/guestbook-php-frontend:latest(spec.template.spec.containers.image:kubeguide/guestbook-php-frontend:latest)

  1. 關鍵在於spec.selector與spec.template.metadata.labels,這兩個字段必須相同,不然下一步建立RC會失敗。(也能夠不寫spec.selector,這樣默認與spec.template.metadata.labels相同)

RC的經常使用操做命令:

    經過kubectl建立RC

    # kubectl create -f rc.yaml

    查看RC具體信息

    # kubectl describe rc frontend

    經過RC修改Pod副本數量(須要修改yaml文件的spec.replicas字段到目標值,而後替換舊的yaml文件)

    # kubectl replace -f rc.yaml     或     # kubect edit replicationcontroller frontend

    對RC使用滾動升級,來發布新功能或修復BUG

    # kubectl rolling-update frontend --image=kubeguide/guestbook-php-frontend:latest

    當Pod中只有一個容器時,經過–image參數指定新的Tag完成滾動升級,但若是有多個容器或其餘字段修改時,須要指定yaml文件

     # kubectl rolling-update frontend -f FILE.yaml

    若是在升級過程當中出現問題(如發現配置錯誤、長時間無響應),可使用CTRL+C退出,再進行回滾

     # kubectl rolling-update frontend --image=kubeguide/guestbook-php-frontend:latest --rollback

     但若是升級完成後出現問題(好比新版本程序出core),此命令就無能爲力了。咱們須要使用一樣方法,利用原來的鏡像,「升級」爲舊版本。

 

Deployment

  更加方便的管理Pod和Replica Set

  k8s是一個高速發展的項目,在新的版本中,官方推薦使用Replica Set和Deployment來代替RC。那麼它們優點在哪裏,咱們來看一看:

  • RC只支持基於等式的selector(env=dev或environment!=qa),但Replica Set還支持新的,基於集合的selector(version in (v1.0, v2.0)或env notin (dev, qa)),這對複雜的運維管理很方便。

  • 使用Deployment升級Pod,只須要定義Pod的最終狀態,k8s會爲你執行必要的操做,雖然可以使用命令# kubectl rolling-update完成升級,但它是在客戶端與服務端屢次交互控制RC完成的,因此REST API中並無rolling-update的接口,這爲定製本身的管理系統帶來了一些麻煩。

  • Deployment擁有更加靈活強大的升級、回滾功能。

目前,Replica Set與RC的區別只是支持的selector不一樣,後續確定會加入更多功能。Deployment使用了Replica Set,它是更高一層的概念。除非用戶須要自定義升級功能或根本不須要升級Pod,在通常狀況下,咱們推薦使用Deployment而不直接使用Replica Set。

  Deployment的一些基礎命令。

$ kubectl describe deployments  #查詢詳細信息,獲取升級進度
$ kubectl rollout pause deployment/nginx-deployment2  #暫停升級
$ kubectl rollout resume deployment/nginx-deployment2  #繼續升級
$ kubectl rollout undo deployment/nginx-deployment2  #升級回滾
$ kubectl scale deployment nginx-deployment --replicas 10  #彈性伸縮Pod數量
 

  使用子命令create,建立Deployment

  # kubectl create -f deployment.yaml --record

  注意–record參數,使用此參數將記錄後續建立對象的操做,方便管理與問題追溯

  使用子命令edit,編輯spec.replicas/spec.template.spec.container.image字段,完成deployment的擴縮容與滾動升級(這要比子命令rolling-update速度快不少)

  # kubectl edit deployment hello-deployment

  使用rollout history命令,查看Deployment的歷史信息

  # kubectl rollout history deployment hello-deployment

  上面提到RC在rolling-update升級成功後不能直接回滾,而使用Deployment卻能夠回滾到上一版本,但要加上–revision參數,指定版本號

  # kubectl rollout history deployment hello-deployment --revision=2

  使用rollout undo回滾到上一版本

  # kubectl rollout undo deployment hello-deployment 

  使用–to-revision能夠回滾到指定版本

  # kubectl rollout undo deployment hello-deployment --to-revision=2

 

Volume

    在Docker中,容器中的數據是臨時的,當容器被銷燬時,其中的數據將會丟失。若是須要持久化數據,須要使用Docker數據卷掛載宿主機上的文件或者目錄到容器中。Docker中有docker Volume的概念,Docker的Volume只是磁盤中的一個目錄,生命週期不受管理。固然Docker如今也提供Volume將數據持久化存儲,但支持功能比較少(例如,對於Docker 1.7,每一個容器只容許掛載一個Volume,而且不能將參數傳遞給Volume)。
    在Kubernetes中,當Pod重建的時候,數據也會丟失,Kubernetes也是經過數據卷掛載來提供Pod數據的持久化的。Kubernetes數據卷是對Docker數據卷的擴展,Kubernetes數據卷是Pod級別的,能夠用來實現Pod中容器的文件共享。Kubernetes Volume具備明確的生命週期 - 與pod相同。所以,Volume的生命週期比Pod中運行的任何容器要持久,在容器從新啓動時能夠保留數據,固然,當Pod被刪除不存在時,Volume也將消失。注意,Kubernetes支持許多類型的Volume,Pod能夠同時使用任意類型/數量的Volume。
    要使用Volume,pod須要指定Volume的類型和內容(spec.volumes字段),和映射到容器的位置(spec.containers.volumeMounts字段)。
    容器中的進程能夠看到Docker image和volumes組成的文件系統。Docker image處於文件系統架構的root,任何volume都映射在鏡像的特定路徑上。Volume不能映射到其餘volume上,或者硬連接到其餘volume。容器中的每一個容器必須堵路地指定他們要映射的volume。

  Kubernetes支持Volume類型有:

  • emptyDir
  • hostPath
  • gcePersistentDisk
  • awsElasticBlockStore
  • nfs
  • iscsi
  • fc (fibre channel)
  • flocker
  • glusterfs
  • rbd
  • cephfs
  • gitRepo
  • secret
  • persistentVolumeClaim
  • downwardAPI
  • projected
  • azureFileVolume
  • azureDisk
  • vsphereVolume
  • Quobyte
  • PortworxVolume
  • ScaleIO
  • StorageOS
  • local

  emptyDir

  使用emptyDir,當Pod分配到Node上時,將會建立emptyDir,而且只要Node上的Pod一直運行,Volume就會一直存。當Pod(無論任何緣由)從Node上被刪除時,emptyDir也同時會刪除,存儲的數據也將永久刪除。注:刪除容器不影響emptyDir。

  從名稱就能夠看出,它的初始內容爲空。同一個pod中全部容器能夠讀和寫emptyDir中的相同文件。

emptyDir的用途:

  • 臨時空間,例如用於某些應用程序運行時所需的臨時目錄,且無需永久保存;
  • 長時間任務的中間過程CheckPoint臨時保存目錄;
  • 一個容器須要從另外一個容器中獲取數據的目錄(多容器共享目錄)

示例:

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

  hostPath

  hostPath容許掛載Node上的文件系統到Pod裏面去。若是Pod須要使用Node上的文件,可使用hostPath。

hostPath一般應用於:

  • 容器應用程序生成的日誌文件須要永久保存,可使用宿主機的高速文件系統進行存儲;
  • 須要訪問宿主機上Docker引擎內部數據結構的容器應用,能夠經過定義hostpath爲宿主機/var/lib/docker目錄,使得容器內部應用能夠直接訪問Docker的文件系統。

使用此類型的Volume時需注意:

  在不一樣Node上具備相同配置的Pod可能會由於宿主機上的目錄和文件不用而致使對Volume上目錄和文件的訪問結果不一致

示例

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd  #容器路徑
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data      #宿主機路徑

  gcePersistentDisk

  gcePersistentDisk能夠掛載GCE上的永久磁盤到容器,須要Kubernetes運行在GCE的VM中。與emptyDir不一樣,Pod刪除時,gcePersistentDisk被刪除,但Persistent Disk 的內容任然存在。這就意味着gcePersistentDisk可以容許咱們提早對數據進行處理,並且這些數據能夠在Pod之間「切換」。

提示:使用gcePersistentDisk,必須用gcloud或使用GCE API或UI 建立PD

建立PD

使用GCE PD與pod以前,須要建立它

gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk

示例

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    # This GCE PD must already exist.
    gcePersistentDisk:
      pdName: my-data-disk
      fsType: ext4

  awsElasticBlockStore

  awsElasticBlockStore能夠掛載AWS上的EBS盤到容器,須要Kubernetes運行在AWS的EC2上。與emptyDir Pod被刪除狀況不一樣,Volume僅被卸載,內容將被保留。這就意味着awsElasticBlockStore可以容許咱們提早對數據進行處理,並且這些數據能夠在Pod之間「切換」。

提示:必須使用aws ec2 create-volumeAWS API 建立EBS Volume,而後才能使用。

建立EBS Volume

在使用EBS Volume與pod以前,須要建立它。

aws ec2 create-volume --availability-zone eu-west-1a --size 10 --volume-type gp2

AWS EBS配置示例

apiVersion: v1
kind: Pod
metadata:
  name: test-ebs
spec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-ebs
      name: test-volume
  volumes:
  - name: test-volume
    # This AWS EBS volume must already exist.
    awsElasticBlockStore:
      volumeID: <volume-id>
      fsType: ext4

  NFS

  NFS 是Network File System的縮寫,即網絡文件系統。Kubernetes中經過簡單地配置就能夠掛載NFS到Pod中,而NFS中的數據是能夠永久保存的,同時NFS支持同時寫操做。Pod被刪除時,Volume被卸載,內容被保留。這就意味着NFS可以容許咱們提早對數據進行處理,並且這些數據能夠在Pod之間相互傳遞。

  iSCSI

  iscsi容許將現有的iscsi磁盤掛載到咱們的pod中,和emptyDir不一樣的是,刪除Pod時會被刪除,但Volume只是被卸載,內容被保留,這就意味着iscsi可以容許咱們提早對數據進行處理,並且這些數據能夠在Pod之間「切換」。

  flocker

  Flocker是一個開源的容器集羣數據卷管理器。它提供各類存儲後端支持的數據卷的管理和編排。

  glusterfs

  glusterfs,容許將Glusterfs(一個開源網絡文件系統)Volume安裝到pod中。不一樣於emptyDir,Pod被刪除時,Volume只是被卸載,內容被保留。味着glusterfs可以容許咱們提早對數據進行處理,並且這些數據能夠在Pod之間「切換」。

  RBD

  RBD容許Rados Block Device格式的磁盤掛載到Pod中,一樣的,當pod被刪除的時候,rbd也僅僅是被卸載,內容保留,rbd可以容許咱們提早對數據進行處理,並且這些數據能夠在Pod之間「切換」。

  cephfs

  cephfs Volume能夠將已經存在的CephFS Volume掛載到pod中,與emptyDir特色不一樣,pod被刪除的時,cephfs僅被被卸載,內容保留。cephfs可以容許咱們提早對數據進行處理,並且這些數據能夠在Pod之間「切換」。

提示:可使用本身的Ceph服務器運行導出,而後在使用cephfs。

  gitRepo

  gitRepo volume將git代碼下拉到指定的容器路徑中。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: server
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /mypath
      name: git-volume
  volumes:
  - name: git-volume
    gitRepo:
      repository: "git@somewhere:me/my-git-repository.git"
      revision: "22f1d8406d464b0c0874075539c1f2e96c253775"

  secret

  secret volume用於將敏感信息(如密碼)傳遞給pod。能夠將secrets存儲在Kubernetes API中,使用的時候以文件的形式掛載到pod中,而不用鏈接api。 secret volume由tmpfs(RAM支持的文件系統)支持。      

  persistentVolumeClaim

  persistentVolumeClaim用來掛載持久化磁盤的。PersistentVolumes是用戶在不知道特定雲環境的細節的狀況下,實現持久化存儲(如GCE PersistentDisk或iSCSI卷)的一種方式。

  downwardAPI

  經過環境變量的方式告訴容器Pod的信息

  projected

  Projected volume將多個Volume源映射到同一個目錄

目前,能夠支持如下類型的卷源:

  • secret
  • downwardAPI
  • configMap

全部卷源都要求與pod在同一命名空間中。

示例

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
            - key: username
              path: my-group/my-username
      - downwardAPI:
          items:
            - path: "labels"
              fieldRef:
                fieldPath: metadata.labels
            - path: "cpu_limit"
              resourceFieldRef:
                containerName: container-test
                resource: limits.cpu
      - configMap:
          name: myconfigmap
          items:
            - key: config
              path: my-group/my-config

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
            - key: username
              path: my-group/my-username
      - secret:
          name: mysecret2
          items:
            - key: password
              path: my-group/my-password
              mode: 511

  FlexVolume

  alpha功能

  AzureFileVolume

  AzureFileVolume用於將Microsoft Azure文件卷(SMB 2.1和3.0)掛載到Pod中。

  AzureDiskVolume

  Azure是微軟提供的公有云服務,若是使用Azure上面的虛擬機來做爲Kubernetes集羣使用時,那麼能夠經過AzureDisk這種類型的卷插件來掛載Azure提供的數據磁盤。

  vsphereVolume

  須要條件:配置了vSphere Cloud Provider的Kubernetes。

  vsphereVolume用於將vSphere VMDK Volume掛載到Pod中。卸載卷後,內容將被保留。它同時支持VMFS和VSAN數據存儲。

  重要提示:使用POD以前,必須使用如下方法建立VMDK。

  建立一個VMDK卷

  • 使用vmkfstools建立。先將ssh接入ESX,而後使用如下命令建立vmdk
vmkfstools -c 2G /vmfs/volumes/DatastoreName/volumes/myDisk.vmdk
  • 使用vmware-vdiskmanager建立
shell vmware-vdiskmanager -c -t 0 -s 40GB -a lsilogic myDisk.vmdk

示例

apiVersion: v1
kind: Pod
metadata:
  name: test-vmdk
spec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-vmdk
      name: test-volume
  volumes:
  - name: test-volume
    # This VMDK volume must already exist.
    vsphereVolume:
      volumePath: "[DatastoreName] volumes/myDisk"
      fsType: ext4

  Quobyte

  在kubernetes中使用Quobyte存儲,須要提早部署Quobyte軟件,要求必須是1.3以及更高版本,而且在kubernetes管理的節點上面部署Quobyte客戶端。

  PortworxVolume

  Portworx能把你的服務器容量進行蓄積(pool),將你的服務器或者雲實例變成一個聚合的高可用的計算和存儲節點。

  PortworxVolume能夠經過Kubernetes動態建立,也能夠在Kubernetes pod中預先配置和引用。示例:

apiVersion: v1
kind: Pod
metadata:
  name: test-portworx-volume-pod
spec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /mnt
      name: pxvol
  volumes:
  - name: pxvol
    # This Portworx volume must already exist.
    portworxVolume:
      volumeID: "pxvol"
      fsType: "<fs-type>"

  ScaleIO

  ScaleIO是一種基於軟件的存儲平臺(虛擬SAN),可使用現有硬件來建立可擴展共享塊網絡存儲的集羣。ScaleIO卷插件容許部署的pod訪問現有的ScaleIO卷(或者能夠爲持久卷聲明動態配置新卷,請參閱 Scaleio Persistent Volumes)。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: pod-0
spec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: pod-0
    volumeMounts:
    - mountPath: /test-pd
      name: vol-0
  volumes:
  - name: vol-0
    scaleIO:
      gateway: https://localhost:443/api
      system: scaleio
      volumeName: vol-0
      secretRef:
        name: sio-secret
      fsType: xfs

  StorageOS

  StorageOS是一家英國的初創公司,給無狀態容器提供簡單的自動塊存儲、狀態來運行數據庫和其餘須要企業級存儲功能,但避免隨之而來的複雜性、剛性以及成本。

核心:是StorageOS向容器提供塊存儲,可經過文件系統訪問。

StorageOS容器須要64位Linux,沒有額外的依賴關係,提供免費開發許可證。

安裝說明,請參閱StorageOS文檔

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: redis
    role: master
  name: test-storageos-redis
spec:
  containers:
    - name: master
      image: kubernetes/redis:v1
      env:
        - name: MASTER
          value: "true"
      ports:
        - containerPort: 6379
      volumeMounts:
        - mountPath: /redis-master-data
          name: redis-data
  volumes:
    - name: redis-data
      storageos:
        # The `redis-vol01` volume must already exist within StorageOS in the `default` namespace.
        volumeName: redis-vol01
        fsType: ext4

有關動態配置和持久卷聲明的更多信息,請參閱StorageOS示例

  Local

  目前處於 Kubernetes 1.7中的 alpha 級別。

Local 是Kubernetes集羣中每一個節點的本地存儲(如磁盤,分區或目錄),在Kubernetes1.7中kubelet能夠支持對kube-reserved和system-reserved指定本地存儲資源。

經過上面的這個新特性能夠看出來,Local Storage同HostPath的區別在於對Pod的調度上,使用Local Storage能夠由Kubernetes自動的對Pod進行調度,而是用HostPath只能人工手動調度Pod,由於Kubernetes已經知道了每一個節點上kube-reserved和system-reserved設置的本地存儲限制。

示例:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
  annotations:
        "volume.alpha.kubernetes.io/node-affinity": '{
            "requiredDuringSchedulingIgnoredDuringExecution": {
                "nodeSelectorTerms": [
                    { "matchExpressions": [
                        { "key": "kubernetes.io/hostname",
                          "operator": "In",
                          "values": ["example-node"]
                        }
                    ]}
                 ]}
              }'
spec:
    capacity:
      storage: 100Gi
    accessModes:
    - ReadWriteOnce
    persistentVolumeReclaimPolicy: Delete
    storageClassName: local-storage
    local:
      path: /mnt/disks/ssd1

請注意,本地PersistentVolume須要手動清理和刪除。

有關local卷類型的詳細信息,請參閱 Local Persistent Storage user guide

  Using subPath

  有時,能夠在一個pod中,將同一個卷共享,使其有多個用處。volumeMounts.subPath特性能夠用來指定卷中的一個子目錄,而不是直接使用卷的根目錄。

如下是使用單個共享卷的LAMP堆棧(Linux Apache Mysql PHP)的pod的示例。HTML內容映射到其html文件夾,數據庫將存儲在mysql文件夾中:

apiVersion: v1
kind: Pod
metadata:
  name: my-lamp-site
spec:
    containers:
    - name: mysql
      image: mysql
      volumeMounts:
      - mountPath: /var/lib/mysql
        name: site-data
        subPath: mysql
    - name: php
      image: php
      volumeMounts:
      - mountPath: /var/www/html
        name: site-data
        subPath: html
    volumes:
    - name: site-data
      persistentVolumeClaim:
        claimName: my-lamp-site-data

  Resources

  emptyDir Volume的存儲介質(Disk,SSD等)取決於kubelet根目錄(如/var/lib/kubelet)所處文件系統的存儲介質。不限制emptyDir或hostPath Volume使用的空間大小,不對容器或Pod的資源隔離。

 

Service

  Service是定義一系列Pod以及訪問這些Pod的策略的一層抽象由於Service是抽象的,因此在圖表裏一般看不到它們的存在。

  Service經過Label找到Pod組。當你在Service的yaml文件中定義了該Service的selector中的label爲app:my-web,那麼這個Service會將Pod-->metadata-->labeks中label爲app:my-web的Pod做爲分發請求的後端。當Pod發生變化時(增長、減小、重建等),Service會及時更新。這樣一來,Service就能夠做爲Pod的訪問入口,起到代理服務器的做用,而對於訪問者來講,經過Service進行訪問,無需直接感知Pod。

   Service的目標是提供一種橋樑, 它會爲訪問者提供一個固定訪問地址,用於在訪問時重定向到相應的後端,這使得非 Kubernetes原生應用程序,在無須爲Kubemces編寫特定代碼的前提下,輕鬆訪問後端。

  須要注意的是,Kubernetes分配給Service的固定IP是一個虛擬IP,並非一個真實的IP,在外部是沒法尋址的。真實的系統實現上,Kubernetes是經過Kube-proxy組件來實現的虛擬IP路由及轉發。因此在以前集羣部署的環節上,咱們在每一個Node上均部署了Proxy這個組件,從而實現了Kubernetes層級的虛擬轉發網絡。有一個特別類型的Kubernetes Service,稱爲'LoadBalancer',做爲外部負載均衡器使用,在必定數量的Pod之間均衡流量。好比,對於負載均衡Web流量頗有用。


  如今,假定有2個後臺Pod,而且定義後臺Service的名稱爲‘backend-service’,lable選擇器爲(tier=backend, app=myapp)。backend-service 的Service會完成以下兩件重要的事情:

    • 會爲Service建立一個本地集羣的DNS入口,所以前端Pod只須要DNS查找主機名爲 ‘backend-service’,就可以解析出前端應用程序可用的IP地址。
    • 如今前端已經獲得了後臺服務的IP地址,可是它應該訪問2個後臺Pod的哪個呢?Service在這2個後臺Pod之間提供透明的負載均衡,會將請求分發給其中的任意一個。經過每一個Node上運行的代理(kube-proxy)完成。

 

  Service代理外部服務

    Service不只能夠代理Pod,還能夠代理任意其餘後端,好比運行在Kubernetes外部Mysql、Oracle等。這是經過定義兩個同名的service和endPoints來實現的。示例以下:

redis-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  ports:
  - port: 6379
    targetPort: 6379
    protocol: TCP

redis-endpoints.yaml

apiVersion: v1
kind: Endpoints
metadata:
  name: redis-service
subsets:
  - addresses:
    - ip: 10.0.251.145
    ports:
    - port: 6379
      protocol: TCP

基於文件建立完Service和Endpoints以後,在Kubernetes的Service中便可查詢到自定義的Endpoints。

[root@k8s-master demon]# kubectl describe service redis-service
Name:            redis-service
Namespace:        default
Labels:            <none>
Selector:        <none>
Type:            ClusterIP
IP:            10.254.52.88
Port:            <unset>    6379/TCP
Endpoints:        10.0.251.145:6379
Session Affinity:    None
No events.
[root@k8s-master demon]# etcdctl get /skydns/sky/default/redis-service
{"host":"10.254.52.88","priority":10,"weight":10,"ttl":30,"targetstrip":0}

 

  Service內部負載均衡

    當Service的Endpoints包含多個IP的時候,及服務代理存在多個後端,將進行請求的負載均衡。默認的負載均衡策略是輪訓或者隨機(有kube-proxy的模式決定)。同時,Service上經過設置Service-->spec-->sessionAffinity=ClientIP,來實現基於源IP地址的會話保持。

  發佈Service

    Service的虛擬IP是由Kubernetes虛擬出來的內部網絡,外部是沒法尋址到的。可是有些服務又須要被外部訪問到,例如web前段。這時候就須要加一層網絡轉發,即外網到內網的轉發。Kubernetes提供了NodePort、LoadBalancer、Ingress三種方式。

  • NodePort,在以前的Guestbook示例中,已經延時了NodePort的用法。NodePort的原理是,Kubernetes會在每個Node上暴露出一個端口:nodePort,外部網絡能夠經過(任一Node)[NodeIP]:[NodePort]訪問到後端的Service。
  • LoadBalancer,在NodePort基礎上,Kubernetes能夠請求底層雲平臺建立一個負載均衡器,將每一個Node做爲後端,進行服務分發。該模式須要底層雲平臺(例如GCE)支持。
  • Ingress,是一種HTTP方式的路由轉發機制,由Ingress Controller和HTTP代理服務器組合而成。Ingress Controller實時監控Kubernetes API,實時更新HTTP代理服務器的轉發規則。HTTP代理服務器有GCE Load-Balancer、HaProxy、Nginx等開源方案。

   servicede 自發性機制

    Kubernetes中有一個很重要的服務自發現特性。一旦一個service被建立,該service的service IP和service port等信息均可以被注入到pod中供它們使用。Kubernetes主要支持兩種service發現 機制:環境變量和DNS。

   環境變量方式

    Kubernetes建立Pod時會自動添加全部可用的service環境變量到該Pod中,若有須要.這些環境變量就被注入Pod內的容器裏。須要注意的是,環境變量的注入只發送在Pod建立時,且不會被自動更新。這個特色暗含了service和訪問該service的Pod的建立時間的前後順序,即任何想要訪問service的pod都須要在service已經存在後建立,不然與service相關的環境變量就沒法注入該Pod的容器中,這樣先建立的容器就沒法發現後建立的service。

   DNS方式

    Kubernetes集羣如今支持增長一個可選的組件——DNS服務器。這個DNS服務器使用Kubernetes的watchAPI,不間斷的監測新的service的建立併爲每一個service新建一個DNS記錄。若是DNS在整個集羣範圍內均可用,那麼全部的Pod都可以自動解析service的域名。

  多個service如何避免地址和端口衝突

    此處設計思想是,Kubernetes經過爲每一個service分配一個惟一的ClusterIP,因此當使用ClusterIP:port的組合訪問一個service的時候,無論port是什麼,這個組合是必定不會發生重複的。另外一方面,kube-proxy爲每一個service真正打開的是一個絕對不會重複的隨機端口,用戶在service描述文件中指定的訪問端口會被映射到這個隨機端口上。這就是爲何用戶能夠在建立service時隨意指定訪問端口。

  service目前存在的不足

    Kubernetes使用iptables和kube-proxy解析service的人口地址,在中小規模的集羣中運行良好,可是當service的數量超過必定規模時,仍然有一些小問題。首當其衝的即是service環境變量氾濫,以及service與使用service的pod二者建立時間前後的制約關係。目前來看,不少使用者在使用Kubernetes時每每會開發一套本身的Router組件來替代service,以便更好地掌控和定製這部分功能。

相關文章
相關標籤/搜索