kubernetes 概念

基础对象

对象 说明
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]}

node selection

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

kubectl apply 如何计算差异并合并修改内容

Nodes
Node Status包含以下信息

对象 包含内容
Addresses HostName, 可以使用kubelet --hostname-override修改
ExternalIP:集群外IP
InternalIP:集群内IP
Condition OutOfDisk:添加新pod空间不足为True,否则为False
Ready:node 正常为True,node不健康为False,node控制器没有接收到node-monitor-grace-period为Unknown,默认接收间隔时间40S
MemoryPressure node内存不足为True,否则为False
PIDPressurenode进程太多True,否则为False
DiskPressure 磁盘大小不足为True,否则为False
NetworkUnavailable 网络配置不正确为True,否则为False
node状态为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的健康。

猜你喜欢

转载自yq.aliyun.com/articles/697387