k8s部分名詞解釋
NameSpace:命名空間
Namespace是對一組資源和對象的抽象集合,比如可以用來將系統內部的對象划分為不同的項目組或用戶組。常見的pods, services,
replication controllers和deployments等都是屬於某一個namespace的(默認是default),而node,
persistentVolumes等則不屬於任何namespace。
Namespace常用來隔離不同的用戶,比如Kubernetes自帶的服務一般運行在kube-system namespace中。
Namespace操作:
查看命名空間 :
[root@master ~]# kubectl get ns
NAME STATUS AGE
default Active 3d11h
kube-public Active 3d11h
kube-system Active 3d11h
## namespace包含兩種狀態”Active”和”Terminating”。在namespace刪除過程中,namespace狀態被設置成”Terminating”。
創建命名空間:
kubectl create namespace jason-namespace
查看指定的命名空間
kubectl get ns jason-namespace
命名空間名稱滿足正則表達式a-z0-9?,最大長度為63位
刪除命名空間:
kubectl delete namespaces new-namespace
kubectl delete namespace jason-namespace
刪除一個namespace會自動刪除所有屬於該namespace的資源。
default和kube-system命名空間不可刪除。
Replication Controller(用於保證pod的數量)
Replication Controller 保證了在所有時間內,都有特定數量的Pod副本正在運行,如果太多了,Replication Controller就殺死幾個,如果太少了,Replication Controller會新建幾個。可以這樣理解它,他就是一個pod的管理器,隨時監管着這個pod,讓它始終有那么多個pod在提供服務。
Replication Controller只會對那些RestartPolicy = Always的Pod的生效,(RestartPolicy的默認值就是Always),Replication Controller 不會去管理那些有不同啟動策略pod。
由Replication Controller監控的Pod的數量是是由一個叫 label selector(標簽選擇器)決定的,label
selector在Replication
Controller和被控制的pod創建了一個松散耦合的關系,與pod相比,pod與他們的定義文件關系緊密。
replication controller的任務就是保證預計數量的pod並並保證其可用性
replication controller的任務永遠都只會是單一的。它自身不會進行是否可讀和是否可用的檢測,相比與自動進行縮放和放大,replication controller更傾向與使用外部的自動平衡工具,這些外部工具要作的僅僅是修改replicas的值來實現Pod數量的變化,我們不會增加replicationcontroller的調度策率,也不會讓replication controller來驗證受控的Pod是否符合特定的模版,因為這些都會阻礙自動調整和其它的自動的進程。
常見的使用模式
Rescheduling(重新規划)
也就是說當你的pod掛了或者怎么了,它會重新給你規划以保證有足夠數量的pod在任意時刻都在提供服務。
Scaling(縮放)
Replication Controller讓我們更容易的控制pod的副本的數量,不管我們是手動控制還是通過其它的自動管理的工具,最簡單的:修改replicas的值。
這個就是彈性伸縮,當你流量很大的時候,可以增加pod來提供服務,當你流量降下來了可以減少相應的pod數量。
Rolling updates(動態更新)
Replication Controller 可以支持動態更新,當我們更新一個服務的時候,它可以允許我們一個一個的替換pod
也就是說不用一下子全部更新,類似於迭代更新。
推薦的方法是創建一個新的只有1個pod副本的Replication Controller,然后新的每次+1,舊的每次-1,直到舊的Replication Controller 的值變成0,然后我們就可以刪除舊的了,這樣就可以規避升級過程中出現的未知錯誤了。
理論上,動態更新控制器應考慮應用的可用性,並確保足夠的pod制成服務在任何時間都能正常提供服務。
兩個 Replication Controller創建的pod至少要由一個不同的標簽,可以是鏡像的標簽,因為一般鏡像的更新都會帶來一個新的更新。
kubectl是實現動態更新的客戶端
ReplicaSet
ReplicaSet是下一代副本控制器。ReplicaSet和 Replication Controller之間的唯一區別是現在的選擇器支持。Replication Controller只支持基於等式的selector(env=dev或environment!=qa),但ReplicaSet還支持新的,基於集合的selector(versionin (v1.0, v2.0)或env notin (dev, qa))。在試用時官方推薦ReplicaSet。
大多數kubectl支持Replication Controller的命令也支持ReplicaSets。rolling-update命令有一個例外 。如果您想要滾動更新功能,請考慮使用Deployments。此外, rolling-update命令是必須的,而Deployments是聲明式的,因此我們建議通過rollout命令使用Deployments。
雖然ReplicaSets可以獨立使用,但是今天它主要被 Deployments 作為協調pod創建,刪除和更新的機制。當您使用Deployments時,您不必擔心管理他們創建的ReplicaSets。Deployments擁有並管理其ReplicaSets。
ReplicaSet可確保指定數量的pod“replicas”在任何設定的時間運行。然而,Deployments是一個更高層次的概念,它管理ReplicaSets,並提供對pod的聲明性更新以及許多其他的功能。因此,我們建議您使用Deployments而不是直接使用ReplicaSets,除非您需要自定義更新編排或根本不需要更新。
這實際上意味着您可能永遠不需要操作ReplicaSet對象:直接使用Deployments並在規范部分定義應用程序。
Node:node節點名詞解釋
Node是Pod真正運行的主機,可以物理機,也可以是虛擬機。為了管理Pod,每個Node節點上至少要運行container runtime(比如docker或者rkt)、kubelet和kube-proxy服務。
Node管理
Node本質上不是Kubernetes來創建的,Kubernetes只是管理Node上的資源。雖然可以通過Manifest創建一個Node對象,但Kubernetes也只是去檢查是否真的是有這么一個Node,如果檢查失敗,也不會往上調度Pod。
這個檢查是由Node Controller來完成的。Node Controller負責
- 維護Node狀態
- 與Cloud Provider同步Node
- 給Node分配容器CIDR
- 刪除帶有NoExecute taint的Node上的Pods
默認情況下,kubelet在啟動時會向master注冊自己,並創建Node資源。這個注冊的過程就是授權的過程,是需要master授權。
Node的狀態
每個Node都包括以下狀態信息
- 地址:包括hostname、外網IP和內網IP
- 條件(Condition):包括OutOfDisk、Ready、MemoryPressure和DiskPressure
- 容量(Capacity):Node上的可用資源,包括CPU、內存和Pod總數
- 基本信息(Info):包括內核版本、容器引擎版本、OS類型等
Taints和tolerations
Taints和tolerations用於保證Pod不被調度到不合適的Node上,Taint應用於Node上,而toleration則應用於Pod上(Toleration是可選的)。
Node維護模式
標志Node不可調度但不影響其上正在運行的Pod,這種維護Node時是非常有用的
kubectl cordon $NODENAME
Service對象:名詞解釋
Kubernete Service 是一個定義了一組Pod的策略的抽象,我們也有時候叫做宏觀服務。這些被服務標記的Pod都是(一般)通過label Selector決定的。
對於Kubernete原生的應用,Kubernete提供了一個簡單的Endpoints API,這個Endpoints
api的作用就是當一個服務中的pod發生變化時,Endpoints
API隨之變化,對於哪些不是原生的程序,Kubernetes提供了一個基於虛擬IP的網橋的服務,這個服務會將請求轉發到對應的后台pod。
一個Kubernete服務是一個最小的對象,類似pod,和其它的終端對象一樣,我們可以朝paiserver發送請求來創建一個新的實例。
Virtual IPs and service proxies(虛擬IP和服務代理)
每一個節點上都運行了一個kube-proxy,這個應用監控着Kubermaster增加和刪除服務,對於每一個服務,kube-proxy會隨機開啟一個本機端口,任何發向這個端口的請求都會被轉發到一個后台的Pod當中,而如何選擇是哪一個后台的pod的是基於SessionAffinity進行的分配。kube-proxy會增加iptables rules來實現捕捉這個服務的Ip和端口來並重定向到前面提到的端口。
最終的結果就是所有的對於這個服務的請求都會被轉發到后台的Pod中,這一過程用戶根本察覺不到。
默認的,后台的選擇是隨機的,基於用戶session機制的策略可以通過修改service.spec.sessionAffinity 的值從NONE到ClientIP。
也可以實現多端口服務,因為有時候需要開放不同的端口。
也可以在創建服務的時候指定ip地址
我們可以在創建服務的時候指定IP地址,將spec.clusterIP的值設定為我們想要的IP地址即可。例如,我們已經有一個DNS域我們希望用來替換,或者遺留系統只能對指定IP提供服務,並且這些都非常難修改,用戶選擇的IP地址必須是一個有效的IP地址,並且要在API
server分配的IP范圍內,如果這個IP地址是不可用的,apiserver會返回422http錯誤代碼來告知是IP地址不可用
服務的發現
Kubernetes 支持兩種方式的來發現服務 ,環境變量和 DNS。
環境變量
當一個Pod在一個node上運行時,kubelet 會針對運行的服務增加一系列的環境變量,它支持Docker links compatible 和普通環境變量。
使用環境變量是需要注意的是:對系統有一個要求:所有的想要被POD訪問的服務,必須在POD創建之前創建,否則這個環境變量不會被填充,使用DNS則沒有這個問題。
DNS
一個可選擇的雲平台插件就是DNS,DNS 服務器監控着API SERVER ,當有服務被創建的時候,DNS 服務器會為之創建相應的記錄,如果DNS這個服務被添加了,那么Pod應該是可以自動解析服務的。
舉個例子來說:如果我們在my-ns命名空間下有一個服務叫做“my-service”,這個時候DNS就會創建一個my-service.my-ns的記錄,所有my-ns命名空間下的Pod,都可以通過域名my-service查詢找到對應的ip地址,不同命名空間下的Pod在查找是必須使用my-sesrvice.my-ns才可以。
Kubernete 同樣支持端口的解析,如果my-service有一個提供http的TCP主持的端口,那么我們可以通過查詢“_http._tcp.my-service.my-ns”來查詢這個端口。
External services(外部服務)
對於我們的應用程序來說,我們可能有一部分是放在Kubernete外部的(比如我們有單獨的物理機來承擔數據庫的角色),Kubernetes支持兩種方式:NodePorts,LoadBalancers。
每一個服務都會有一個字段定義了該服務如何被調用(發現),這個字段的值可以為:
- ClusterIP:使用一個集群固定IP,這個是默認選項
- NodePort:使用一個集群固定IP,但是額外在每個POD上均暴露這個服務,端口
- LoadBalancer:使用集群固定IP,和NODEPord,額外還會申請申請一個負載均衡器來轉發到服務(load balancer )
注意:NodePort 支持TCP和UDN,但是LoadBalancers在1.0版本只支持TCP。
Type NodePort
如果你選擇了“NodePort”,那么 Kubernetes master 會分配一個區域范圍內,(默認是30000-32767),並且,每一個node,都會代理(proxy)這個端口到你的服務中,我們可以在spec.ports[*].nodePort 找到具體的值
如果我們向指定一個端口,我們可以直接寫在nodePort上,系統就會給你指派指定端口,但是這個值必須是指定范圍內的。這樣的話就能夠讓開發者搭配自己的負載均衡器,去撘建一個kubernete不是完全支持的系統,又或者是直接暴露一個node的ip地址。
Type LoadBalancer
在支持額外的負載均衡器的的平台上,將值設置為LoadBalancer會提供一個負載均衡器給你的服務,負載均衡器的創建其實是異步的。所有服務的請求均會直接到Pod,具體是如何工作的是由平台決定的。
LoadBalancers 只支持TCP,不支持UDP。
Volume數據卷
Docker有一個Volumes的概念,雖然這個Volume有點寬松和管理性比較小。在Docker中,一個 Volume 是一個簡單的所在主機的一個目錄或者其它容器中的。生命周期是沒有辦法管理,直到最近才有 local-disk-backed 磁盤。Docker現在提供了磁盤驅動,但是功能非常有限(例如Docker1.7只能掛在一個磁盤每個容器,並且無法傳遞參數)
從另外一個方面講,一個Kubernetes volume,擁有明確的生命周期,與所在的Pod的生命周期相同。因此,Kubernetes volume獨立與任何容器,與Pod相關,所以數據在重啟的過程中還會保留,當然,如果這個Pod被刪除了,那么這些數據也會被刪除。更重要的是,Kubernetes volume 支持多種類型,任何容器都可以使用多個Kubernetes volume。
它的核心,一個 volume 就是一個目錄,可能包含一些數據,這些數據對pod中的所有容器都是可用的,這個目錄怎么使用,什么類型,由什么組成都是由特殊的volume 類型決定的。想要使用一個volume,Pod必須指明Pod提供了那些磁盤,並且說明如何掛在到容器中。
Kubernete 支持如下類型的volume:
emptyDir,hostPath,gcePersistentDisk,awsElasticBlockStore,nfs, iscsi, glusterfs, rbd, gitRepo,secret,persistentVolumeClaim
emptyDir
一個emptyDir
第一次創建是在一個pod被指定到具體node的時候,並且會一直存在在pod的生命周期當中,正如它的名字一樣,它初始化是一個空的目錄,pod中的容器都可以讀寫這個目錄,這個目錄可以被掛在到各個容器相同或者不相同的的路徑下。當一個pod因為任何原因被移除的時候,這些數據會被永久刪除。注意:一個容器崩潰了不會導致數據的丟失,因為容器的崩潰並不移除pod.
emptyDir 磁盤的作用:
- 普通空間,基於磁盤的數據存儲
- 作為從崩潰中恢復的備份點
- 存儲那些那些需要長久保存的數據,例web服務中的數據
默認的,emptyDir 磁盤會存儲在主機所使用的媒介上,可能是SSD,或者網絡硬盤,這主要取決於你的環境。當然,我們也可以將emptyDir.medium的值設置為Memory來告訴Kubernetes 來掛在一個基於內存的目錄tmpfs,因為tmpfs速度會比硬盤快了,但是,當主機重啟的時候所有的數據都會丟失。
Deployment名詞解析
Deployment為Pod和ReplicaSet提供了一個聲明式定義(declarative)方法,用來替代以前的ReplicationController來方便的管理應用。典型的應用場景包括:
- 定義Deployment來創建Pod和ReplicaSet
- 滾動升級和回滾應用
- 擴容和縮容
- 暫停和繼續Deployment
例如一個簡單的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 scale deployment nginx-deployment --replicas 10
如果集群支持 horizontal pod autoscaling 的話,還可以為Deployment設置自動擴展:
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
更新鏡像
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
//也可以直接使用edit進行編輯
kubectl edit deployment/nginx-deployment
回滾
kubectl rollout undo deployment/nginx-deployment
Deployment為Pod和Replica Set(下一代Replication Controller)提供聲明式更新。
它會自動的去給你創建pod和副本數,讓任何時候都有足夠的副本在提供服務。
//查看rs狀態,rs的名稱總是deployment的名稱+hash值
kubectl get rs
//查看pod
kubectl get pods
Secret名詞解析
Secret解決了密碼、token、密鑰等敏感數據的配置問題,而不需要把這些敏感數據暴露到鏡像或者Pod Spec中。Secret可以以Volume或者環境變量的方式使用。
Secret有三種類型:
- Service Account:用來訪問Kubernetes API,由Kubernetes自動創建,並且會自動掛載到Pod的
/run/secrets/kubernetes.io/serviceaccount
目錄中; - Opaque:base64編碼格式的Secret,用來存儲密碼、密鑰等;
kubernetes.io/dockerconfigjson
:用來存儲私有docker registry的認證信息。
Opaque Secret
Opaque類型的數據是一個map類型,要求value是base64編碼格式:
$ echo -n "admin" | base64
YWRtaW4=
$ echo -n "1f2d1e2e67df" | base64
MWYyZDFlMmU2N2Rm
secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: MWYyZDFlMmU2N2Rm
username: YWRtaW4=
然后進行創建kubectl create -f secrets.yml
使用secret有兩種方式:
- 以Volume方式
- 以環境變量方式
第一種使用Volume掛載的方式:
apiVersion: v1
kind: Pod
metadata:
labels:
name: db
name: db
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
containers:
- image: gcr.io/my_project_id/pg:v1
name: db
volumeMounts:
- name: secrets
mountPath: "/etc/secrets"
readOnly: true
ports:
- name: cp
containerPort: 5432
hostPort: 5432
將Secret導出到環境變量中
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: wordpress-deployment
spec:
replicas: 2
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: wordpress
visualize: "true"
spec:
containers:
- name: "wordpress"
image: "wordpress"
ports:
- containerPort: 80
env:
- name: WORDPRESS_DB_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
其他的兩個都沒有怎么用,而且都是k8s自動創建的,所以這兒就不用再去創建了,對於那些比較私密的數據也就是密碼用戶名和賬號等信息,這個時候可以使用secret來進行管理,可以是volume掛載到數據卷,也可以是以變量的形式進行引用。
其他參見:https://www.kubernetes.org.cn/secret
StatefulSet名詞解析
StatefulSet是為了解決有狀態服務的問題(對應Deployments和ReplicaSets是為無狀態服務而設計),其應用場景包括
-
穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基於PVC來實現
-
穩定的網絡標志,即Pod重新調度后其PodName和HostName不變,基於Headless Service(即沒有Cluster IP的Service)來實現
-
有序部署,有序擴展,即Pod是有順序的,在部署或者擴展的時候要依據定義的順序依次依次進行(即從0到N-1,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態),基於init containers來實現
-
有序收縮,有序刪除(即從N-1到0)
從上面的應用場景可以發現,StatefulSet由以下幾個部分組成:
- 用於定義網絡標志(DNS domain)的Headless Service
- 用於創建PersistentVolumes的volumeClaimTemplates
- 定義具體應用的StatefulSet
StatefulSet中每個Pod的DNS格式為statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
,其中
serviceName
為Headless Service的名字0..N-1
為Pod所在的序號,從0開始到N-1statefulSetName
為StatefulSet的名字namespace
為服務所在的namespace,Headless Servic和StatefulSet必須在相同的namespace.cluster.local
為Cluster Domain,
簡單的一個web.yaml示例
---
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: gcr.io/google_containers/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
annotations:
volume.alpha.kubernetes.io/storage-class: anything
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
#根據文件進行創建服務
$ kubectl create -f web.yaml
service "nginx" created
statefulset "web" created
# 查看創建的headless service和statefulset
$ kubectl get service nginx
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx None <none> 80/TCP 1m
$ kubectl get statefulset web
NAME DESIRED CURRENT AGE
web 2 2 2m
# 根據volumeClaimTemplates自動創建PVC(在GCE中會自動創建kubernetes.io/gce-pd類型的volume)
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-d064a004-d8d4-11e6-b521-42010a800002 1Gi RWO 16s
www-web-1 Bound pvc-d06a3946-d8d4-11e6-b521-42010a800002 1Gi RWO 16s
# 查看創建的Pod,他們都是有序的
$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 5m
web-1 1/1 Running 0 4m
# 使用nslookup查看這些Pod的DNS
$ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
/ # nslookup web-0.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.2.10
/ # nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.3.12
/ # nslookup web-0.nginx.default.svc.cluster.local
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx.default.svc.cluster.local
Address 1: 10.244.2.10
其他操作,擴容縮容,更新鏡像刪除等操作
# 擴容
$ kubectl scale statefulset web --replicas=5
# 縮容
$ kubectl patch statefulset web -p '{"spec":{"replicas":3}}'
# 鏡像更新(目前還不支持直接更新image,需要patch來間接實現)
$ kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.7"}]'
# 刪除StatefulSet和Headless Service
$ kubectl delete statefulset web
$ kubectl delete service nginx
# StatefulSet刪除后PVC還會保留着,數據不再使用的話也需要刪除
$ kubectl delete pvc www-web-0 www-web-1
DaemonSet
DaemonSet保證在每個Node上都運行一個容器副本,常用來部署一些集群的日志、監控或者其他系統管理應用。典型的應用包括:
- 日志收集,比如fluentd,logstash等
- 系統監控,比如Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond等
- 系統程序,比如kube-proxy, kube-dns, glusterd, ceph等
指定Node節點
DaemonSet會忽略Node的unschedulable狀態,有兩種方式來指定Pod只運行在指定的Node節點上:
- nodeSelector:只調度到匹配指定label的Node上
- nodeAffinity:功能更豐富的Node選擇器,比如支持集合操作
- podAffinity:調度到滿足條件的Pod所在的Node上
nodeSelector示例
給node打標簽
kubectl label nodes node-01 disktype=ssd
然后指定在daemonset中指定標簽
spec:
nodeSelector:
disktype: ssd
nodeAffinity示例
nodeAffinity目前支持兩種:requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution,分別代表必須滿足條件和優選條件。比如下面的例子代表調度到包含標簽kubernetes.io/e2e-az-name並且值為e2e-az1或e2e-az2的Node上,並且優選還帶有標簽another-node-label-key=another-node-label-value的Node。
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: gcr.io/google_containers/pause:2.0
podAffinity示例
podAffinity基於Pod的標簽來選擇Node,僅調度到滿足條件Pod所在的Node上,支持podAffinity和podAntiAffinity。這個功能比較繞,以下面的例子為例:
- 如果一個“Node所在Zone中包含至少一個帶有security=S1標簽且運行中的Pod”,那么可以調度到該Node
- 不調度到“包含至少一個帶有security=S2標簽且運行中Pod”的Node上
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: failure-domain.beta.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-affinity
image: gcr.io/google_containers/pause:2.0
靜態Pod
除了DaemonSet,還可以使用靜態Pod來在每台機器上運行指定的Pod,這需要kubelet在啟動的時候指定manifest目錄:
kubelet --pod-manifest-path=/etc/kubernetes/manifests
然后將所需要的Pod定義文件放到指定的manifest目錄中。
注意:靜態Pod不能通過API Server來刪除,但可以通過刪除manifest文件來自動刪除對應的Pod。
Ingress名詞解析
通常情況下,service和pod的IP僅可在集群內部訪問。集群外部的請求需要通過負載均衡轉發到service在Node上暴露的NodePort上,然后再由kube-proxy將其轉發給相關的Pod。
而Ingress就是為進入集群的請求提供路由規則的集合。
Ingress可以給service提供集群外部訪問的URL、負載均衡、SSL終止、HTTP路由等。為了配置這些Ingress規則,集群管理員需要部署一個Ingress controller,它監聽Ingress和service的變化,並根據規則配置負載均衡並提供訪問入口。
例如
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
rules:
- http:
paths:
- path: /testpath
backend:
serviceName: test
servicePort: 80
每個Ingress都需要配置rules,目前Kubernetes僅支持http規則。上面的示例表示請求/testpath時轉發到服務test的80端口。
ingress的分類:
單服務ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
backend:
serviceName: testsvc
servicePort: 80
單個服務還可以通過設置Service.Type=NodePort或者Service.Type=LoadBalancer來對外暴露。
路由到多服務的Ingress
路由到多服務的Ingress即根據請求路徑的不同轉發到不同的后端服務上。例如下面的ingress配置
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: s1
servicePort: 80
- path: /bar
backend:
serviceName: s2
servicePort: 80
ConfigMap
ConfigMap用於保存配置數據的鍵值對,可以用來保存單個屬性,也可以用來保存配置文件。ConfigMap跟secret很類似,但它可以更方便地處理不包含敏感信息的字符串。
configMap的創建
可以使用kubectl create configmap從文件、目錄或者key-value字符串創建等創建ConfigMap。
# 從key-value字符串創建ConfigMap
$ kubectl create configmap special-config --from-literal=special.how=very
configmap "special-config" created
$ kubectl get configmap special-config -o go-template='{{.data}}'
map[special.how:very]
# 從env文件創建
$ echo -e "a=b\nc=d" | tee config.env
a=b
c=d
$ kubectl create configmap special-config --from-env-file=config.env
configmap "special-config" created
$ kubectl get configmap special-config -o go-template='{{.data}}'
map[a:b c:d]
# 從目錄創建
$ mkdir config
$ echo a>config/a
$ echo b>config/b
$ kubectl create configmap special-config --from-file=config/
configmap "special-config" created
$ kubectl get configmap special-config -o go-template='{{.data}}'
map[a:a
b:b
]
configMap的使用
ConfigMap可以通過多種方式在Pod中使用,比如設置環境變量、設置容器命令行參數、在Volume中創建配置文件等。
需要注意的是:
- ConfigMap必須在Pod引用它之前創建
- 使用envFrom時,將會自動忽略無效的鍵
- Pod只能使用同一個命名空間內的ConfigMap
用作環境變量時
//先創建configmap
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
kubectl create configmap env-config --from-literal=log_level=INFO
然后以環境變量形式引用
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
當pod運行結束后輸出
SPECIAL_LEVEL_KEY=very
SPECIAL_TYPE_KEY=charm
log_level=INFO
用作命令行參數
將ConfigMap用作命令行參數時,需要先把ConfigMap的數據保存在環境變量中,然后通過$(VAR_NAME)的方式引用環境變量。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
restartPolicy: Never
當pod結束后輸出
very charm
使用volume將ConfigMap作為文件或目錄直接掛載
將創建的ConfigMap直接掛載至Pod的/etc/config目錄下,其中每一個key-value鍵值對都會生成一個文件,key為文件名,value為內容。
apiVersion: v1
kind: Pod
metadata:
name: vol-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "cat /etc/config/special.how" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
restartPolicy: Never
當Pod結束后會輸出
very
將創建的ConfigMap中special.how這個key掛載到/etc/config目錄下的一個相對路徑/keys/special.level。如果存在同名文件,直接覆蓋。其他的key不掛載。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh","-c","cat /etc/config/keys/special.level" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: special.how
path: keys/special.level
restartPolicy: Never
因為這個和以上的那個存在了相同的文件special.how所以會覆蓋,而其他key則不會再進行掛載。
所以輸出還是very。