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。