基础对象
对象 | 说明 |
---|---|
Pod | k8s最小单位 |
Service | 网络、自动发现 |
Volume | 存储 |
Namespace | 命名空间 |
基于基础对象抽象出以下Controllers
对象 | 说明 |
---|---|
ReplicaSet | |
Deployment | 无状态服务 |
StatefulSet | 有状态服务 |
jobs |
master组件
对象 | 说明 |
---|---|
kube-apiserver | 暴露Kubernetes api |
etcd | etcd 用来存储所有的集群数据 |
kube-scheduler | 调度pods |
kube-controller-manager | 控制Controller |
cloud-controller-manager
Node组件,node的组件在每个节点都会有
对象 | 说明 |
---|---|
kubelet | 保证容器跑在pod里 并且保证pod的健康,kubelet只管理用Kubernetes创建的容器。 |
kube-proxy | 网络和连接转发 |
Container Runtime |
插件Addons
Client Libraries:自己写代码调用Kubernetes API
yaml写法
yaml spec pod
yaml spec deployment
labels
annotations
Namespaces
使用场景: 多团队或者多项目 ,如果只是为了区分服务,使用 labels就可以了。区分开发、测试、预发布、正式环境
通过Resource Quotas分配集群资源
创建和删除namespaces
#查看命名空间
kubectl get namespaces
#设置命名空间
kubectl --namespace=<insert-namespace-name-here> run nginx --image=nginx
kubectl --namespace=<insert-namespace-name-here> get pods
#设置默认使用哪个命名空间
kubectl config set-context $(kubectl config current-context) --namespace=<insert-namespace-name-here>
创建Service的时候会创建对应的dns, dns的入口是..svc.cluster.local,这表示dns只解析本的命名空间请求,这在使用命名空间区分测试、预发布、正式环境很有用。如果你需要跨命名空间访问则需要域名。
并不是所有的Kubernetes 资源都在同一个命名空间里,可以使用以下的命令查看
#在namespace里的资源
kubectl api-resources --namespaced=true
#不在namespace里的资源
kubectl api-resources --namespaced=false
Labels and Selectors
Labels 对object而言的key是唯一的。
一个合理的key应该由前缀和名称组成,使用/分隔。
名称不超过63个字符,可以使用- _ .分隔
前缀是可选的,如果指定了不超过253个字符 并且以/结尾
value不超过63个字符,不要有除- _ .外的特殊字符。
labels搜索
操作 | 说明 | 示例 |
---|---|---|
= | 等于 | environment=production |
== | 等于 | environment==production |
!= | 不等于 | environment!=production |
in | in | environment in (production, qa) |
notin | notin | tier notin (frontend, backend) |
exists | exists只检测key有没有存在 | partition |
noexists | exists只检测key有没有存在 | !partition |
多个合并操作environment=production,tier!=frontend |
#查询environment=production&&tier=frontend
kubectl get pods -l environment=production,tier=frontend
kubectl get pods -l 'environment in (production),tier in (frontend)'
#查询key是environment && environment值不是frontend
kubectl get pods -l 'environment,environment notin (frontend)'
#matchExpressions,key、operator、values ,operator支持In、NotIn、Exists、DoesNotExist
selector:
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
Annotations
Labels 用来搜索object和object集合,相反 Annotations用来注释让其他工具或者类库可以检索到metadata。
#annotations可以包含labels中不允许的字符
"metadata": {
"annotations": {
"key1" : "value1",
"key2" : "value2"
}
}
Field Selectors
使用resource字段值查询Kubernetes resource 比如:
metadata.name=my-service
metadata.namespace!=default
status.phase=Pending
#使用--field-selector查询pod为Running状态
kubectl get pods --field-selector status.phase=Running
支持的fields因不同的资源类型而不通,所有的资源类型都支持metadata.name和metadata.namespace
但其他的fields就不一定,如果遇到不支持的fields会报错。
操作符支持=、==和!=
kubectl get services --field-selector metadata.namespace!=default
链式操作
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
同时搜索多资源
kubectl get statefulsets,services --field-selector metadata.namespace!=default
推荐做法
有状态服务
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql #名称
app.kubernetes.io/instance: wordpress-abcxzy #唯一名称,标识应用程序
app.kubernetes.io/version: "5.7.21" #版本
app.kubernetes.io/component: database #架构中的组件
app.kubernetes.io/part-of: wordpress #哪个程序的一部分
app.kubernetes.io/managed-by: helm #用什么工具管理
无状态服务labels例子:
#Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
#Service
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
#注意同一个服务里的 Deployment和Service里的labels是一样
包含数据库的web应用
#Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
#Service
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
#Mysql StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/version: "5.7.21"
...
#Mysql Service
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/version: "5.7.21"
...
Kubernetes对象管理
管理技巧
Warning: Kubernetes 对象有多种管理技巧,不要混用。
#创建Deployment 对象
kubectl run nginx --image nginx
kubectl create deployment nginx --image nginx
#创建Deployment
kubectl run
#创建Service 对象
kubectl expose
#创建一个可自动扩缩容的controller,比如Deployment
kubectl autoscale
#指定子命令
create <objecttype> [<subtype>] <instancename>
kubectl create service nodeport <myservicename>
#查看帮助
kubectl create service nodeport -h
#水平扩容
kubectl scale
#添加或者删除注释
kubectl annotate
#添加或者删除label
kubectl label
#设置object里的字段
kubectl set <field>
#直接用编辑器打开配置修改
kubectl edit
#使用patch来修改object
kubectl patch
#使用set命令在创建objects 之前修改内容
#kubectl create service -o yaml --dry-run 这个命令不会发送给Kubernetes 而是输出YAML 内容到标准输出,通过管道发送给下一个命令
#kubectl set selector --local -f - -o yaml 从管道接收配置然后写入到YAML
#kubectl create -f - 执行创建命令
kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run | kubectl set selector --local -f - 'environment=qa' -o yaml | kubectl create -f -
#使用--edit在创建前修改objects
kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run > /tmp/srv.yaml
kubectl create --edit -f /tmp/srv.yaml
Imperative object configuration命令式对象配置
#创建objects
kubectl create -f <filename|url>
kubectl create -f nginx.yaml
#更新objects
kubectl replace -f <filename|url>
kubectl replace -f nginx.yaml
replace局限性:
1.从一个配置文件里创建一个object
2.用其他方式修改object 里的某些字段
3.再修改第1步的配置文件然后使用replace 执行,这样第2步修改的内容就会丢失。
所以要注意不要用多种方式管理同一个object 。如果你想用多个文件管理同一个object要使用kubectl apply来管理。
#删除objects
kubectl delete -f <filename|url>
kubectl delete -f nginx.yaml -f redis.yaml
kubectl delete <type>/<name>
kubectl delete deployment/nginx
#查看objects , -o yaml 输出完整的object 配置,使用kubectl get -h查看详细内容
kubectl get -f <filename|url> -o yaml
#查看pod的输出或者错误
kubectl logs
#修改object 但不保存在配置文件里
kubectl create -f <url> --edit
#从命令行管理转成配置管理 imperative object configuration
#1.导出object配置到本地文件
kubectl get <kind>/<name> -o yaml --export > <kind>_<name>.yaml
#2从导出的配置文件中删除status 字段
#3使用replace更新
kubectl replace -f <kind>_<name>.yaml
定义controller selectors和PodTemplate labels
警告:强烈建议不要修改controller的selectors,推荐的方法是使用PodTemplate
selector:
matchLabels:
controller-selector: "extensions/v1beta1/deployment/nginx"
template:
metadata:
labels:
controller-selector: "extensions/v1beta1/deployment/nginx"
Declarative object configuration声明式对象配置
#创建objects
kubectl apply -f <directory>/
#simple_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
minReadySeconds: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
#查看变动,类似 git diff
kubectl diff -f simple_deployment.yaml
#执行变动
kubectl apply -f simple_deployment.yaml
#打印配置信息
kubectl get -f simple_deployment.yaml -o yaml
#递归查看变动
kubectl diff -R -f configs/
#递归执行变动
kubectl apply -R -f configs/
#使用kubectl scale扩容
kubectl scale deployment/nginx-deployment --replicas=2
#删除objects
#推荐使用imperative command 去删除objects
kubectl delete -f <filename>
#prune 还处于alpha阶段,后续版本可能会修改,并且该命令是查询label来删除的~ 所以可能删除其他东西
kubectl apply -f <directory/> --prune -l <labels>
#查看object配置
kubectl get -f <filename|url> -o yaml
Nodes
Node Status包含以下信息
对象 | 包含内容 |
---|---|
Addresses |
HostName, 可以使用kubelet --hostname-override修改 ExternalIP:集群外IP InternalIP:集群内IP |
Condition |
OutOfDisk :添加新pod空间不足为True,否则为FalseReady :node 正常为True,node不健康为False,node控制器没有接收到node-monitor-grace-period为Unknown,默认接收间隔时间40SMemoryPressure node内存不足为True,否则为FalsePIDPressure node进程太多True,否则为FalseDiskPressure 磁盘大小不足为True,否则为FalseNetworkUnavailable 网络配置不正确为True,否则为Falsenode状态为Unknown或者False时间超过pod-eviction-timeout设定的时间(默认5分钟),出问题的node上的所有pod会被删除。 在某些情况下,node因为网络问题 unreachable,apiserver 无法和kubelet 通讯, 删除pod命令在恢复通讯后发送。 在Kubernetes 1.5版本以前node controller 会强制删除unreachable 的pod,在1.5 版本以后不会强制删除。 |
Capacity |
描述node上的可用资源: CPU,内存以及可以在节点上调度的最大pod数 |
Info |
node的一般信息比如内核版本、Kubernetes 版本、Docker版本、OS 名称。由Kubelet从node收集。 |
管理node
Kubernetes本身不创建node,他通过外部提供者创建,比如本地物理机、虚拟机、谷歌云等。所以Kubernetes创建node的时候其实是创建一个object 来表示node。一旦创建成功,Kubernetes会检查node是否有效。比如如果你用下面的内容创建node:
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
Kubernetes创建一个内部node对象,并且通过metadata.name检查node是否健康。如果node有效,所有的服务都会执行。否则集群会忽略它直到node变成有效。Kubernetes 会不断的检查无效的node对象。你必须删除node才能停止检查。
node controller、 kubelet和 kubectl 三个组件和Kubernetes node接口交互。
Node Controller
node controller是Kubernetes的主要组件,管理node的各方面。
node controller 在node的生命周期里扮演多个角色。
1.注册的时候为node 分配CIDR 块(如果CIDR 开启)。
2.node controller云服务商的可用集群列表最新的内部节点列表,当在云环境里执行的时候,每当node unhealthy, node controller 会请求云服务商 那个node的VM 是否依旧可用。如果不可用,node controller 会从node列表里把这个node删除。
3.监控nodes的健康。