Kubernetes指南:主要资源对象
Kubernetes是一个高度自动化的资源控制系统,通过跟踪对比etcd库里保存的“资源期望状态”, 与当前环境中的“实际资源状态”的差异来实现自动控制和自动纠错的高级功能;
Master
集群控制节点,每个Kubernetes需要一个Master节点来负责整个集群的管理和控制; 通常Master节点占据一个独立的x86服务器或者一个虚拟机;
Node
集群中的工作负载节点; 运行以下关键进程:
-
kubelet:负责Pod对应容器的创建、启停等任务;与master节点合作实现集群管理的基本功能;
-
kube-proxy:实现Kubernetes Service的通信与负载均衡机制;
-
Docker Engine:docker引擎,负责本机的容器创建和管理工作;
默认情况下kubelet会向Master注册自己,一旦Node被纳入集群管理范围,kubelet进程定时向Master节点汇报自身的状态,如OS、docker版本、机器CPU和内存情况;
NameSpace
多用于实现多租户的资源隔离
pod
最重要、最基本的概念; 每个Pod都有一个Pause容器, Pause容器对应的镜像属于Kubernetes平台的一部分;
Pause容器:
1.引入业务无关且不易死亡的Pause容器作为Pod容器的根容器,以他的状态代表整个容器组的状态;
2.Pod里的多个业务容器共享Pause容器的IP、Volume,简化了密切关联的业务容器之间的通信问题, 解决了文件共享问题;
两种Pod类型:
-
普通Pod:可以被调度;
-
静态Pod(Static Pod):不存放在etcd存储里,而是在某个具体Node上的一个文件中;
pod的状态
-
Pending:创建pod的请求已经被k8s接受,但是容器并没有启动成功, 可能处在:写数据到etcd,调度,pull镜像,启动容器这四个阶段中的任何一个阶段, pending伴随的事件通常会有:ADDED, Modified这两个事件的产生。
-
Running:pod已经绑定到node节点,并且所有的容器已经启动成功, 或者至少有一个容器在运行,或者在重启中。
-
Succeeded:pod中的所有的容器已经正常的自行退出,并且k8s永远不会自动重启这些容器, 一般会是在部署job的时候会出现。
-
Failed:pod中的所有容器已经终止,并且至少有一个容器已经终止于失败(退出非零退出代码或被系统停止)。
-
Unknown:由于某种原因,无法获得pod的状态,通常是由于与pod的主机通信错误。
Label
Label通常在资源对象定义时创建,也可以在对象创建后动态添加或者删除; 实现多维度的资源分组管理功能,便于灵活地进行资源分配、调度、配置、部署等管理工作
Label selector在Kubernetes中的使用场景:
1.kube-controller进程通过资源对象RC上定义的Label来筛选要监控的Pod副本的数量,从而使Pod数量符合预期;
2.kube-proxy进程通过Service的Label来选择对应的Pod,自动建立起每个Service到对应Pod的请求转发路由表,从而实现Service的智能负载均衡机制;
3.kube-scheduler通过Node的label用来实现对Pod的“定向调度”
总结: Label和Label selector共同构成了Kubernetes系统中最核心的应用模型,实现精细的分组管理和集群的高可用;
RC
核心概念之一,定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值;
包括: 1.Pod期待的副本数:replicas
2.用于筛选目标Pod的Label Selector
3.当Pod的副本数量小于预期时,用于创建新的Pod的模板;
apiVersion: v1
kind: ReplicaSet
metadata:
name: testing-xxxx
namespace: testing
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/instance: my-app
template:
metadata:
labels:
app.kubernetes.io/instance: my-app
spec:
containers:
- env:
- name: xxxx
Deployment
deployment引入的目的是为了更好的解决Pod的编排问题; 内部使用了Replica Set来实现, 是RS的升级;
使用场景:
1.创建一个Deployment对象来生成对应的Replica Set并完成Pod副本的创建过程;
2.检查Deployment来看部署当动作是否完成(Pod数量是否达到预期);
3.更新deployment以创建新的Pod;
4.如果当前deployment不稳定,则回滚到一个早先的deployment版本;
5.挂起或者恢复一个Deployment;
查看Deployment信息: kubectl -n testing get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
my-app-deployment 1/1 1 1 228d
pods命名以deployment对应的replica set的名字为前缀
Service
最核心的资源对象之一,每个service可以理解为“微服务”;
yaml示例:
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/version: v1.3.4
name: my-app-service
namespace: testing
resourceVersion: "123456"
spec:
clusterIP: 10.96.1.200
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app.kubernetes.io/instance: my-app-deployment
type: ClusterIP
status:
loadBalancer: {}
概述
客户端如何访问多个Pod副本组成的集群? 部署一个负载均衡器(软件或者硬件),为这组Pod开启一个对外的服务端口,并且将这些Pod的EndPoint列表 加入转发列表,客户端就可以通过负载均衡器对外IP地址+服务端口号来访问此服务; 客户端的请求会转发到哪个Pod,则由负载均衡器的算法决定;
运行在每个Node上的kube-proxy进程就是一个智能的软件负载均衡器,负责把对Service的请求转发到后端的 某个Pod实例上,并在内部实现服务的负载均衡与会话保持机制;
每个Service分配一个全局唯一的虚拟IP地址—-ClusterIP 这样每个服务就变成了具备唯一IP地址的“通信节点”;
Pod和Service的IP
Pod的Endpoint会随着Pod的销毁和重新创建而发生改变—-新的Pod的Ip地址与之前旧的Pod的IP不同;
Service一旦创建,ClusterIP不变;
Kubernetes服务发现机制
大部分分布式系统通过提供特定的API接口来实现服务发现的功能;(平台的侵入性比较强,增加了开发测试的难度)
Kubernetes:
- 每个Service都有一个唯一的ClusterIP以及唯一的名字
如何通过Service名字找到ClusterIP:
1.早期通过Linux环境变量;
2.后来通过Add-On增量包的方式引入了DNS系统,把服务名作为DNS域名
外部系统访问Service
Kubernetes里的三种IP:
-
NodeIP:Node节点的IP
-
Pod IP:Pod的IP地址
-
Cluster IP:Service的IP地址
关于ClusterIP:
1.ClusterIP仅作用于Kubernetes Service对象,由Kubernetes管理和分配IP地址(ClusterIP地址池);
2.ClusterIP无法被ping通,没有实体网络对象;
3.只能结合Service Port组成一个具体的通信端口,单独的ClusterIP不具备TCP/IP通信的基础;
ClusterIP只是集群内部的IP,如何把服务暴露给集群外部: NodePort是最直接、有效,最常用的做法, 在service定义做扩展即可:
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
type: NodePort
ports:
- port: 8080
nodePort: 62032
selector:
app.kubernetes.io/instance: my-app-deployment
NodePort没有完全解决外部访问Service的所有问题,比如负载均衡 通常使用软件(如HAProxy或者Nginx)或者硬件负载均衡的方式来实现
Volume
Pod中能够被多个容器访问的共享目录;Kubernetes的Volume和Docker Volume的概念、用途和目的比较类似;
Kubernetes的Volume:
1.volume定义在pod上,被一个Pod里的多个容器挂载到具体文件目录下;
2.Volume的生命周期与Pod的生命周期相同;
3.支持多种类型的Volume;
Volume类型:
1.emptyDir
2.hostPath
在Pod上挂载宿主机上的文件或目录
3.gcePersistentDisk
谷歌公有云提供的永久磁盘(Persistent Disk)
4.awsElasticBlockStore
5.NFS
6.其他
iscsi、flocker、glusterfs、rbd、gitRepo、secret
Persistent Volume
PV(Persistent Volume)
PVC(Persistent Volume Claim)
PV是Kubernetes集群中的某个网络存储中对应的一块存储,与PVC类似,区别在于:
1.PV属于网络存储,不属于任何Node,但可以在每个Node上访问;
2.PV不是定义在Pod上,而是独立于Pod之外定义;
accessModes:
-
ReadWriteOnce:读写权限,并且只能被单个Node挂载
-
ReadOnlyMany:只读权限,允许被多个Node挂载
-
ReadWriteMany:读写权限,允许被多个Node挂载
例:
apiVersion: v1
kind: PersistentVolume
metadata:
name: xxxx-storage-pv
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 1Gi
local:
path: /path/to/dir
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: project
operator: In
values:
- xxxx
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
configmap
Kubernetes允许为pod中的每个容器指定自定义的环境变量集合,pod定义硬编码意味着要有效区分生产环境与开发环境中的pod定义。 configmap将配置从pod定义描述中解耦出来;
configmap本质上就是一个键/值对,值可以是短字面量,也可以是完整的配置文件;
应用无需直接读取configmap,映射内容通过环境变量或者卷文件的形式传递给容器;
创建configmap
1.使用kubectl命令直接创建
kubectl create configmap configmap_test --from-literal=server_port=8001
kubectl create configmap configmap_test --from-literal=server_port=8001 --from-literal=server_host=127.0.0.1
kubectl get configmap configmap_test -o yaml
kubectl create -f configmap_test.yaml
2.从文件内容创建configmap
kubectl create config my_config --from-file=config_file.conf
key:config_file.conf, value: file data
kubectl create config my_config --from-file=test_key=config_file.conf
key:test_key, value: file data
3.从文件夹创建
kubectl create config my_config --from-file=test_key=/path/to/dir
如何将映射中的值传递给pod容器?
1.给容器传递configmap条目作为环境变量
env:
- name: SERVER_PORT
valueFrom:
configMapKeyRef:
name:my_config
key:test_key
在pod中引用不存在的configmap容器会启动失败,可以设置configMapKeyRef.optional:true解决
2.一次性传递configmap的所有条目作为环境变量
envFrom:
- prefix: CONFIG_
configMapKeyRef:
name:my_config
3.传递configmap内容作为命令行参数
env:
- name: SERVER_PORT
valueFrom:
configMapKeyRef:
name:my_config
key:test_key
args: ["$(SERVER_PORT)"]
4.使用configmap卷将条目暴露为文件
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d // 也可以挂载至某一文件/etc/nginx/my.conf
subPath: myconfig.conf //仅挂载指定的条目
readOnly: true
- name: config
configMap:
name: my_config
defaultMode: "6600" // 设置所有文件的权限为-rw-rw-----
更新配置是否需要重启程序?
1.使用环境变量或者命令行参数作为配置—-需要重启
2.将configmap暴露为卷—-可以热更新,无需重新创建pod或者重启容器
secret
采用secret存储敏感的数据
默认token secret
default-token-xxxx被默认挂载至所有容器
包含三个条目:ca.crt,namespace,token,用于从pod内部安全访问Kubernetes API服务器
可以设置:automountServiceAccountToken为false
创建secret
openssl genrsa -aes256 -out server.key 2048
openssl req -new -x509 -days 3650 -key server.key -sha256 -out server.cert -subj/CN=www.qiuwenqi.com
kubectl create secret generic my_secret --from-file=server.key --from-file=server.cert
在Docker hub上使用私有镜像仓库
1.创建包含Docker镜像仓库证书的secret
2.pod中定义imagePullSecret字段引用该secret
NetworkPolicy
NetworkPolicy是Kubernetes的一个新特性,它负责配置Pod组如何与彼此和其他网络端点进行通信。 换句话说,它在运行于Kubernetes集群上的Pod间创建防火墙。