在本文中,咱們從技術細節上對kubernetes進行簡單運用介紹,利用一些yaml腳本層面上實例告訴你們kubernetes基本概念。Kubernetes以及它呈現出的編程範式值得你去使用和整合到本身的技術棧中。php
你們若有興趣,能夠關注由達觀數據出品的更多經典好文datagrand達觀數據html
Kubernetes最初認爲是谷歌開源的容器集羣管理系統,是Google多年大規模容器管理技術Borg或Omega的開源版本。準確來講的話,kubernetes更是一個全新的平臺,一個全新的
平臺管理工具,它是專門爲job和service設計。徹底開放,2014年6月開始接受公開的commit,任何人均可以提供意見。因爲kubernetes簡化了開發、運維和管理負荷,愈來愈多
的企業開始在生產環境使用,所以kubernetes獲得了迅速的發展。node
Kubernetes主要由如下幾個核心組件組成:mysql
若是隻是爲了瞭解kubernetes,可使用minikube的方式進行單機安裝,minikube 實際就是本地建立了一個虛擬機,裏面運行了kubernetes 的一些必要的環境,至關於 k8s 的服務環境,建立 pod,service,deployment等都是在裏面進行建立和管理。
在本文中,我使用kubeadm方式安裝kubernetes 1.10.0,具體kubernetes部署步驟:nginx
請注意:上述環境只是測試環境,生產環境部署大同小異。git
Container(容器)是一種便攜式、輕量級的操做系統級虛擬化技術。它使用 namespace 隔離不一樣的軟件運行環境,並經過鏡像自包含軟件的運行環境,
從而使得容器能夠很方便的在任何地方運行。因爲容器體積小且啓動快,所以能夠在每一個容器鏡像中打包一個應用程序。這種一對一的應用鏡像關係擁有不少好處。使用容器,
不須要與外部的基礎架構環境綁定, 由於每個應用程序都不須要外部依賴,更不須要與外部的基礎架構環境依賴。完美解決了從開發到生產環境的一致性問題。
容器一樣比虛擬機更加透明,這有助於監測和管理。尤爲是容器進程的生命週期由基礎設施管理,而不是由容器內的進程對外隱藏時更是如此。最後,
每一個應用程序用容器封裝,管理容器部署就等同於管理應用程序部署。
在 Kubernetes 必需要使用 Pod 來管理容器,每一個 Pod 能夠包含一個或多個容器。web
上面已經說了「Pod是kubernetes中你能夠建立和部署的最小也是最簡的單位。一個Pod表明着集羣中運行的一個進程。」Pod中封裝着應用的容器(有的狀況下是好幾個容器),
存儲、獨立的網絡IP,管理容器如何運行的策略選項。Pod表明着部署的一個單位:kubernetes中應用的一個實例,可能由一個或者多個容器組合在一塊兒共享資源。
請注意:Docker是kubernetes中最經常使用的容器運行時,可是Pod也支持其餘容器運行時。redis
(1)一個Pod中運行一個容器
「每一個Pod中一個容器」的模式是最多見的用法;在這種使用方式中,你能夠把Pod想象成是單個容器的封裝,kuberentes管理的是Pod而不是直接管理容器。sql
apiVersion: v1 kind: Pod metadata: name: nginx-test labels: app: web spec: containers: - name: front-end image: nginx:1.7.9 ports: - containerPort: 80
建立Pod: kubectl create -f ./pod1-deployment\ 查看Pod: kubectl get po 查看Pod詳細狀況: kubectl describe po nginx-test 進入到Pod(容器)內部: kubectl exec -it nginx-test /bin/bash
(2)在一個Pod中同時運行多個容器
說明:在一個Pod中同時運行多個容器是一種比較高級的用法。只有當你的容器須要緊密配合協做的時候才考慮用這種模式。
一個Pod中也能夠同時封裝幾個須要緊密耦合互相協做的容器,它們之間共享資源。這些在同一個Pod中的容器能夠互相協做成爲一個service單位——一個容器共享文件,
另外一個「sidecar」容器來更新這些文件。Pod將這些容器的存儲資源做爲一個實體來管理。docker
apiVersion: v1 kind: Pod metadata: name: rss-site labels: app: web spec: containers: - name: front-end image: nginx:1.7.9 ports: - containerPort: 80 - name: rss-reader image: redis ports: - containerPort: 88
建立Pod: kubectl create -f ./test-deployment 查看pod kubectl get po 查看Pod詳細狀況 kubectl describe po rss-site 進入front-end內部: kubectl exec -it rss-site -c front-end /bin/bash 進入rss-reade內部: kubectl exec -it rss-site -c rss-reader /bin/bash
以上是關於Pod的簡單介紹,如需瞭解更多,請參考Pod
Node 是 Pod 真正運行的主機,能夠物理機,也能夠是虛擬機。爲了管理 Pod,每一個 Node 節點上至少要運行 container runtime(好比 docker 或者 rkt)、kubelet 和 kube-proxy 服務。
Namespace 是對一組資源和對象的抽象集合,好比能夠用來將系統內部的對象劃分爲不一樣的項目組或用戶組。常見的 pods, services, replication controllers 和 deployments 等都是屬於
某一個 namespace 的(默認是 default),而 node, persistentVolumes 等則不屬於任何 namespace。
咱們既然有Pod了,爲何還要使用Deployment呢?這是由於實際工做中,咱們不多會直接在kubernetes中建立單個Pod。由於Pod的生命週期是短暫的,用後即焚的實體。
Deployment 爲 Pod 和 ReplicaSet 提供了一個聲明式定義(declarative)方法,用來替代之前的ReplicationController 來方便的管理應用。
你只須要在 Deployment 中描述想要的目標狀態是什麼,Deployment controller 就會幫你將 Pod 和ReplicaSet 的實際狀態改變到你的目標狀態。你能夠定義一個全新的 Deployment 來建立
ReplicaSet 或者刪除已有的 Deployment 並建立一個新的來替換。
RC是K8s集羣中最先的保證Pod高可用的API對象。經過監控運行中的Pod來保證集羣中運行指定數目的Pod副本。指定的數目能夠是多個也能夠是1個;少於指定數目,RC就會啓動運行新的Pod副本;
多於指定數目,RC就會殺死多餘的Pod副本。即便在指定數目爲1的狀況下,經過RC運行Pod也比直接運行Pod更明智,由於RC也能夠發揮它高可用的能力,保證永遠有1個Pod在運行。RC是K8s較早期
的技術概念,只適用於長期伺服型的業務類型,好比控制小機器人提供高可用的Web服務。
RS是新一代RC,提供一樣的高可用能力,區別主要在於RS後來居上,能支持更多種類的匹配模式。副本集對象通常不單獨使用,而是做爲Deployment的理想狀態參數使用。
好比,咱們這裏定義一個簡單的nginx應用:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-test namespace: test spec: replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
建立deploy kubectl create -f ./nginx-deployment 查看deploy kubectl get deploy --namespace=test 查看rs(副本集) kubectl get rs --namespace=test 查看pods(容器組) kubectl get po --namespace=test
關於Deployment的應用還有不少,如:擴容、縮容、滾動升級、回滾應用等,這裏因爲篇幅的問題再也不一一介紹,詳見Deployment的應用
Label 是識別 Kubernetes 對象的標籤,以 key/value 的方式附加到對象上(key 最長不能超過 63 字節,value 能夠爲空,也能夠是不超過 253 字節的字符串)。
Label 不提供惟一性,而且實際上常常是不少對象(如 Pods)都使用相同的 label 來標誌具體的應用。
Label 定義好後其餘對象可使用 Label Selector 來選擇一組相同 label 的對象(好比 ReplicaSet 和 Service 用 label 來選擇一組 Pod)。Label Selector 支持如下幾種方式:
Service account是爲了方便Pod裏面的進程調用Kubernetes API或其餘外部服務。
運行在pod裏的進程須要調用Kubernetes API以及非Kubernetes API的其它服務。Service Account它並非給kubernetes集羣的用戶使用的,而是給pod裏面的進程使用的,它爲pod提供必要的身份認證。
apiVersion: v1 kind: Namespace metadata: name: datagrand labels: name: test
建立namespace:test kubectl create -f ./test.yaml 查看命名空間test的sa kubectl get sa -n test 查看命名空間test生成的default kubectl get sa default -o yaml -n test 咱們能夠建立Deployment時,使用這個test命名空間了,如上例Deployment實戰。
Service Account爲服務提供了一種方便的認知機制,但它不關心受權的問題。能夠配合RBAC來爲Service Account鑑權:
咱們在Kubernetes Dashboard1.8.3部署中,碰到首次登入出現訪問權限報錯的問題,緣由就是ServiceAccount的建立問題。
apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: kubernetes-dashboard labels: k8s-app: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kube-system
Service Account介紹請參考博文
Secret解決了密碼、token、密鑰等敏感數據的配置問題,而不須要把這些敏感數據暴露到鏡像或者Pod Spec中。Secret能夠以Volume或者環境變量的方式使用。
Opaque類型的數據是一個map類型,要求value是base64編碼格式: 建立admin帳戶 echo -n "admin" | base64 YWRtaW4= echo -n "1f2d1e2e67df" | base64 MWYyZDFlMmU2N2Rm
建立secret.yaml cat >> secrets.yml << EOF apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: password: MWYyZDFlMmU2N2Rm username: YWRtaW4=
建立secret kubectl create -f secrets.yml
查看secret運行狀態 kubectl get secret --all-namespaces
apiVersion: v1 kind: Pod metadata: name: mypod labels: name: wtf spec: volumes: - name: secrets secret: secretName: mysecret containers: - image: nginx:1.7.9 name: nginx volumeMounts: - name: secrets mountPath: "/etc/secrets" readOnly: true ports: - name: cp containerPort: 5432 hostPort: 5432
說明:這樣就能夠經過文件的方式掛載到容器內,在/etc/secrets目錄下回
生成這個文件。
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: wordpress-deployment spec: replicas: 2 template: metadata: labels: app: wordpress spec: containers: - name: "wordpress" image: "wordpress:latest" ports: - containerPort: 80 env: - name: WORDPRESS_DB_USER valueFrom: secretKeyRef: name: mysecret key: username - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password
查看Pod運行狀態 kubectl get po NAME READY STATUS RESTARTS AGE wordpress-deployment-6b569fbb7d-8qcpg 1/1 Running 0 2m wordpress-deployment-6b569fbb7d-xwwkg 1/1 Running 0 2m
進入容器內部查看環境變量 kubectl exec -it wordpress-deployment-694f4c79b4-cpsxw /bin/bash root@wordpress-deployment-694f4c79b4-cpsxw:/var/www/html# env WORDPRESS_DB_USER=admin WORDPRESS_DB_PASSWORD=1f2d1e2e67df
想要了解更多,請詳見Kubernetes的Secret
ConfigMaps容許你將配置文件、命令行參數或環境變量中讀取的配置信息與docker image分離,以保持集裝箱化應用程序的便攜性。即ConfigMap API給咱們提供了向容器中注入配置信息的機制。
ConfigMap API資源用來保存key-value pair配置數據,這個數據能夠在pods裏使用,或者被用來爲像controller同樣的系統組件存儲配置數據。雖然ConfigMap跟Secrets相似,可是ConfigMap更方便的處理不含敏感信息的字符串。
注意:ConfigMaps不是屬性配置文件的替代品。ConfigMaps只是做爲多個properties文件的引用。你能夠把它理解爲Linux系統中的/etc目錄,專門用來存儲配置文件的目錄。
kind: ConfigMap apiVersion: v1 metadata: creationTimestamp: 2016-02-18×××9:14:38Z name: example-config namespace: default data: example.property.1: hello example.property.2: world example.property.file: |- property.1=value-1 property.2=value-2 property.3=value-3
data一欄包括了配置數據,ConfigMap能夠被用來保存單個屬性,也能夠用來保存一個配置文件。 配置數據能夠經過不少種方式在Pods裏被使用。ConfigMaps能夠被用來:
更多ConfigMap實戰,詳見ConfigMap - Kubernetes
容器磁盤上文件的生命週期是短暫的,這就使得在容器中運行重要應用時出現一些問題。好比,當容器崩潰時,kubelet會重啓它,可是容器中的文件將丟失--容器以乾淨的狀態
(鏡像最初的狀態)從新啓動。其次,在 Pod 中同時運行多個容器時,這些容器之間一般須要共享文件。Kubernetes 中的 Volume 抽象就很好的解決了這些問題。
Docker 中也有一個 volume 的概念,儘管它稍微寬鬆一些,管理也不多。在 Docker 中,卷就像是磁盤或是另外一個容器中的一個目錄。它的生命週期不受管理,直到最近纔有了 local-disk-backed 卷。Docker 如今提供了卷驅動程序,可是功能還很是有限(例如Docker1.7只容許每一個容器使用一個卷驅動,而且沒法給卷傳遞參數)。
Kubernetes 中的卷有明確的壽命——與封裝它的 Pod 相同。因此,卷的生命比 Pod 中的全部容器都長,當這個容器重啓時數據仍然得以保存。固然,當 Pod 再也不存在時,卷也將不復存在。也許更重要的是,Kubernetes 支持多種類型的卷,Pod 能夠同時使用任意數量的卷。
要使用卷,須要爲 pod 指定爲卷(spec.volumes 字段)以及將它掛載到容器的位置(spec.containers.volumeMounts 字段)。
Kubernetes 支持如下類型的卷:
awsElasticBlockStore、azureDisk、azureFile、cephfs、csi、downwardAPI、emptyDir、fc (fibre channel)、flocker、gcePersistentDisk、gitRepo、glusterfs、hostPath、iscsi、local、nfs、persistentVolumeClaim、projected、portworxVolume、quobyte、rbd、scaleIO、secret、storageos、vsphereVolume等
K8S的存儲系統從基礎到高級大體分爲三個層次:普通Volume,Persistent Volume 和動態存儲供應。
最簡單的普通Volume是單節點Volume。它和Docker的存儲卷相似,使用的是Pod所在K8S節點的本地目錄。
它和普通Volume的區別是什麼呢?
普通Volume和使用它的Pod之間是一種靜態綁定關係,在定義Pod的文件裏,同時定義了它使用的Volume。Volume 是Pod的附屬品,咱們沒法單首創建一個Volume,由於它不是一個獨立的K8S資源對象。
而Persistent Volume 簡稱PV是一個K8S資源對象,因此咱們能夠單首創建一個PV。它不和Pod直接發生關係,而是經過Persistent Volume Claim,簡稱PVC來實現動態綁定。Pod定義裏指定的是PVC,而後PVC會根據Pod的要求去自動綁定合適的PV給Pod使用。
PV的訪問模式有三種:
通常來講,PV和PVC的生命週期分爲5個階段:
根據這5個階段,Volume的狀態有如下4種:
變成Released的PV會根據定義的回收策略作相應的回收工做。有三種回收策略:
在實際使用場景裏,PV的建立和使用一般不是同一我的。這裏有一個典型的應用場景:管理員建立一個PV池,開發人員建立Pod和PVC,PVC裏定義了Pod所需存儲的大小和訪問模式,而後PVC會到PV池裏自動匹配最合適的PV給Pod使用。
前面在介紹PV的生命週期時,提到PV的供給有兩種方式,靜態和動態。其中動態方式是經過StorageClass來完成的,這是一種新的存儲供應方式。
使用StorageClass有什麼好處呢?除了由存儲系統動態建立,節省了管理員的時間,還有一個好處是能夠封裝不一樣類型的存儲供PVC選用。在StorageClass出現之前,PVC綁定一個PV只能根據兩個條件,一個是存儲的大小,另外一個是訪問模式。在StorageClass出現後,等於增長了一個綁定維度。
好比這裏就有兩個StorageClass,它們都是用谷歌的存儲系統,可是一個使用的是普通磁盤,咱們把這個StorageClass命名爲slow。另外一個使用的是SSD,咱們把它命名爲fast。
在PVC裏除了常規的大小、訪問模式的要求外,還經過annotation指定了Storage Class的名字爲fast,這樣這個PVC就會綁定一個SSD,而不會綁定一個普通的磁盤。
限於篇幅問題,我這裏簡單說一下emptyDir、nfs、PV和PVC。
EmptyDir類型的volume建立於pod被調度到某個宿主機上的時候,而同一個pod內的容器都能讀寫EmptyDir中的同一個文件。一旦這個pod離開了這個宿主機,EmptyDir中的數據就會被永久刪除。因此目前EmptyDir類型的volume主要用做臨時空間,好比Web服務器寫日誌或者tmp文件須要的臨時目錄。
apiVersion: v1 kind: Pod metadata: labels: name: test-emptypath role: master name: test-emptypath spec: containers: - name: test-emptypath image: nginx:1.7.9 volumeMounts: - name: log-storage mountPath: /tmp/ volumes: - name: log-storage emptyDir: {}
apiVersion: v1 kind: Pod metadata: name: datagrand spec: containers: - name: test1 image: nginx:1.7.9 volumeMounts: - name: log-storage mountPath: /usr/share/nginx/html - name: test2 image: centos volumeMounts: - name: log-storage mountPath: /html command: ["/bin/sh","-c"] args: - while true;do data >> /html/index.html; sleep 1; done volumes: - name: log-storage emptyDir: {}
簡單解釋下上面的內容:
在這個例子中,咱們定義了一個名爲HTML的卷。它的類型是emptyDir,這意味着當一個Pod被分配到一個節點時,卷先被建立,並只要Pod在節點上運行時,這個卷仍存在。正如名字所說,它最初是空的。第一容器運行nginx的
服務器並將共享卷掛載到目錄/ usr /share/ nginx /html。第二容器使用centos的鏡像,並將共享卷掛載到目錄/HTML。每一秒,第二容器添加當前日期和時間到index.html文件中,它位於共享卷。當用戶發出一個HTTP請求到Pod,
nginx的服務器讀取該文件並將其傳遞給響應請求的用戶。
更多volume實戰,詳見Kubernetes部分Volume類型介紹及yaml示例--emptyDir
nfs 卷容許將現有的 NFS(網絡文件系統)共享掛載到你的容器中。不像 emptyDir,當刪除 Pod 時,nfs 卷的內容被保留,卷僅僅是被卸載。這意味着 NFS 卷能夠預填充數據,而且能夠在 pod 之間「切換」數據。 NFS 能夠被多個寫入者同時掛載。
apiVersion: v1 kind: Pod metadata: name: nginx-test labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 volumeMounts: #Mount the path to the container - mountPath: "/tmp/" name: pv0003 volumes: - name: pv0003 nfs: #fixed:This ip is the address of the nfs server server: 192.168.246.169 #fixed:This path is shared externally by the nfs server path: "/data"
更多volume實戰,詳見Kubernetes部分Volume類型介紹及yaml示例--NFS(網絡數據卷)
nfs 做爲 k8s 的網絡存儲驅動,能夠知足持久存儲業務的需求,支持多節點讀寫。下面是兩個Pod同時使用一個持久性volume實例。
#建立PV apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv spec: capacity: storage: 4Gi accessModes: - ReadWriteMany nfs: server: 192.168.246.168 ##NFS服務器的ip地址 path: "/data" ##NFS服務器上的共享目錄
#建立PVC apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-pvc spec: accessModes: - ReadWriteMany storageClassName: "" resources: requests: storage: 3Gi
#建立Deployment apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 volumeMounts: - mountPath: "/wtf" name: datadir volumes: - name: datadir persistentVolumeClaim: claimName: nfs-pvc
更多PV和PVC實戰,詳見實戰kubernetes持久性卷使用
Kubernetes Pod 是有生命週期的,它們能夠被建立,也能夠被銷燬,然而一旦被銷燬生命就永遠結束。 經過 ReplicaSets 可以動態地建立和銷燬 Pod(例如,須要進行擴縮容,或者執行 滾動升級)。 每一個 Pod 都會獲取它本身的 IP 地址,即便這些 IP 地址不老是穩定可依賴的。 這會致使一個問題:在 Kubernetes 集羣中,若是一組 Pod(稱爲 backend)爲其它 Pod (稱爲 frontend)提供服務,那麼那些 frontend 該如何發現,並鏈接到這組 Pod 中的哪些 backend 呢?
Kubernetes Service 定義了這樣一種抽象:一個 Pod 的邏輯分組,一種能夠訪問它們的策略 —— 一般稱爲微服務。 這一組 Pod 可以被 Service 訪問到,一般是經過 Label Selector(查看下面瞭解,爲何可能須要沒有 selector 的 Service)實現的。
舉個例子,考慮一個圖片處理 backend,它運行了3個副本。這些副本是可互換的 —— frontend 不須要關心它們調用了哪一個 backend 副本。 然而組成這一組 backend 程序的 Pod 實際上可能會發生變化,frontend 客戶端不該該也不必知道,並且也不須要跟蹤這一組 backend 的狀態。 Service 定義的抽象可以解耦這種關聯。
對 Kubernetes 集羣中的應用,Kubernetes 提供了簡單的 Endpoints API,只要 Service 中的一組 Pod 發生變動,應用程序就會被更新。 對非 Kubernetes 集羣中的應用,Kubernetes 提供了基於 VIP 的網橋的方式訪問 Service,再由 Service 重定向到 backend Pod。
一個 Service 在 Kubernetes 中是一個 REST 對象,和 Pod 相似。 像全部的 REST 對象同樣, Service 定義能夠基於 POST 方式,請求 apiserver 建立新的實例。 例如,假定有一組 Pod,它們對外暴露了 9376 端口,同時還被打上 "app=MyApp" 標籤。
kind: Service apiVersion: v1 metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
上述配置將建立一個名稱爲 「my-service」 的 Service 對象,它會將請求代理到使用 TCP 端口 9376,而且具備標籤 "app=MyApp" 的 Pod 上。 這個 Service 將被指派一個 IP 地址(一般稱爲 「Cluster IP」),它會被服務的代理使用(見下面)。 該 Service 的 selector 將會持續評估,處理結果將被 POST 到一個名稱爲 「my-service」 的 Endpoints 對象上。
須要注意的是, Service 可以將一個接收端口映射到任意的 targetPort。 默認狀況下,targetPort 將被設置爲與 port 字段相同的值。 可能更有趣的是,targetPort 能夠是一個字符串,引用了 backend Pod 的一個端口的名稱。 可是,實際指派給該端口名稱的端口號,在每一個 backend Pod 中可能並不相同。 對於部署和設計 Service ,這種方式會提供更大的靈活性。 例如,能夠在 backend 軟件下一個版本中,修改 Pod 暴露的端口,並不會中斷客戶端的調用。
Kubernetes Service 可以支持 TCP 和 UDP 協議,默認 TCP 協議。
不少 Service 須要暴露多個端口。對於這種狀況,Kubernetes 支持在 Service 對象中定義多個端口。 當使用多個端口時,必須給出全部的端口的名稱,這樣 Endpoint 就不會產生歧義,例如:
kind: Service apiVersion: v1 metadata: name: my-service spec: selector: app: MyApp ports: - name: http protocol: TCP port: 80 targetPort: 9376 - name: https protocol: TCP port: 443 targetPort: 9377
Service 抽象了該如何訪問 Kubernetes Pod,但也可以抽象其它類型的 backend,例如:
根據以上的應用場景,咱們都可以定義沒有selector的Service,以下:
kind: Service apiVersion: v1 metadata: name: my-service spec: ports: - protocol: TCP port: 80 targetPort: 9376
因爲這個 Service 沒有 selector,就不會建立相關的 Endpoints 對象。能夠手動將 Service 映射到指定的 Endpoints:
kind: Endpoints apiVersion: v1 metadata: name: my-service subsets: - addresses: - ip: 10.0.0.3 ##Endpoint IP = PodIP + ContainerPort ports: - port: 9376
注意:Endpoint IP 地址不能是 loopback(127.0.0.0/8)、 link-local(169.254.0.0/16)、或者 link-local 多播(224.0.0.0/24)。
訪問沒有 selector 的 Service,與有 selector 的 Service 的原理相同。請求將被路由到用戶定義的 Endpoint(該示例中爲 10.0.0.3:9376)。
對一些應用(如 Frontend)的某些部分,可能但願經過外部(Kubernetes 集羣外部)IP 地址暴露 Service。
Kubernetes ServiceTypes 容許指定一個須要的類型的 Service,默認是 ClusterIP 類型。
Type 的取值以及行爲以下:
若是設置 type 的值爲 "NodePort",Kubernetes master 將從給定的配置範圍內(默認:30000-32767)分配端口,每一個 Node 將從該端口(每一個 Node 上的同一端口)代理到 Service。該端口將經過 Service 的 spec.ports[*].nodePort 字段被指定。
若是須要指定的端口號,能夠配置 nodePort 的值,系統將分配這個端口,不然調用 API 將會失敗(好比,須要關心端口衝突的可能性)。
# pwd /data # tree -L 3 . ├── mysql │ ├── conf │ │ └── my.cnf │ └── data │ ├── auto.cnf │ ├── edusoho │ ├── ibdata1 │ ├── ib_logfile0 │ ├── ib_logfile1 │ ├── mysql │ └── performance_schema ├── nginx │ ├── conf │ │ └── nginx.conf │ ├── edusoho │ │ ├── api │ │ ├── app │ │ ├── bootstrap │ │ ├── plugins │ │ ├── src │ │ ├── vendor │ │ ├── vendor_user │ │ └── web │ └── log │ └── error.log ├── php │ ├── log │ │ └── php-fpm.log │ ├── php-fpm.conf │ ├── php.ini │ └── www.conf
apiVersion: v1 kind: Pod metadata: name: lamp-edusoho labels: app: lamp-edusoho restartPolicy: Always spec: containers: - name: nginx abels: app: lamp-nginx image: dockerhub.datagrand.com/global/nginx:v1 ports: - containerPort: 80 volumeMounts: - name: datadir mountPath: "/var/log/nginx/error.log" subPath: ./nginx/log/error.log - name: datadir mountPath: "/etc/nginx/nginx.conf" subPath: ./nginx/conf/nginx.conf - name: datadir mountPath: "/usr/share/nginx/html" subPath: ./nginx/edusoho - name: php image: dockerhub.datagrand.com/global/php:v1 ports: - containerPort: 9000 volumeMounts: - mountPath: /usr/local/php/etc/php-fpm.conf name: datadir subPath: ./php/php-fpm.conf - mountPath: /usr/local/php/etc/php-fpm.d/www.conf name: datadir subPath: ./php/www.conf - mountPath: /usr/local/php/etc/php.ini name: datadir subPath: ./php/php.ini - mountPath: /usr/local/php/var/log/php-fpm.log name: datadir subPath: ./php/log/php-fpm.log - mountPath: /usr/share/nginx/html name: datadir subPath: ./nginx/edusoho - name: mysql image: dockerhub.datagrand.com/global/mysql:5.6 ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: "123456" - name: MYSQL_DATABASE value: "edusoho" - name: MYSQL_USER value: "edusoho" - name: MYSQL_PASSWORD value: "edusoho" args: ['--character-set-server=utf8'] volumeMounts: - name: datadir mountPath: "/var/lib/mysql" subPath: ./mysql/data - name: datadir mountPath: "/etc/my.cnf" subPath: ./mysql/conf/my.cnf volumes: - name: datadir persistentVolumeClaim: claimName: nfs-pvc
apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv spec: capacity: storage: 4Gi accessModes: - ReadWriteMany nfs: server: 192.168.246.168 ##NFS服務器的ip地址 path: "/data" ##NFS服務器上的共享目錄
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-pvc spec: accessModes: - ReadWriteMany storageClassName: "" resources: requests: storage: 3Gi
apiVersion: v1 kind: Service metadata: name: edusoho labels: app: edusoho spec: type: NodePort ports: - port: 80 nodePort: 32756 selector: app: lamp-edusoho
查看Pod kubectl get po -o wide 查看Service kubectl get svc 進入容器內部某個應用,如這裏的nginx kubectl exec -it lamp-edusoho -c nginx /bin/bash
http://192.168.246.168:32756/install/start-install.php 說明:這裏的192.168.246.168是kubernetes的node節點IP,32756是Service中定義的nodePort。