Kubernetes指南:主要资源对象

发布于 2017-11-20 · 本文总共 6467 字 · 阅读大约需要 19 分钟

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间创建防火墙。




本博客所有文章采用的授权方式为 自由转载-非商用-非衍生-保持署名 ,转载请务必注明出处,谢谢。
声明:
本博客欢迎转发,但请保留原作者信息!
博客地址:邱文奇(qiuwenqi)的博客;
内容系本人学习、研究和总结,如有雷同,实属荣幸!
阅读次数:

文章评论

comments powered by Disqus


章节列表