Kubernetes Pod 概念及定义

2018/04/27 Kubernetes

在 Kubernetes 中 Pod 是创建、部署、调度的最小单位,是由一个或多个容器组成。而在一般应用层面上由于以下几点原因,使 Pod 看起来比较像我们平时使用的虚拟机:

  • 同一组 Pod 内的所有容器共享同一个 IP 地址和 Port。
  • 共享存储空间(Volumes)
  • 耦合度较高的应用程序

虚拟机对比Pod

共享 IP 地址和 Port

在 Docker 中每个容器都拥有独立的 IP 地址,Kubernetes 则是每个 Pod 的中的容器共享同样的 IP 地址和 Port。Pod 中的容器可以直接使用 localhost 进行通信。这样 Pod 就更加像我们平时使用的虚拟机了。

共享存储空间(Volumes)

Kubernetes 支持多种不同的 Volume,举例来说 emptyDir 会在 Pod 创建时建立,Pod 销毁时删除,Pod 内部的所有容器都可以挂载写入文件。

假如我们在一个 Pod 内部运行了 Nginx 和 Logstash 两个容器,Nginx 只要把日志放到 Volume 内,Logstash 就可以读取 Nginx 的日志进行分析处理。这样就达到了分工的效果。两个程序的镜像是独立的,所以在升级某个程序版本时不会互相影响。

耦合度较高的应用程序

通常来说一个容器内只允许一个应用程序,但是很多情况下我们可能需要一个程序作为另一个程序的辅助,还是上面所说的例子,我们将 Nginx 和 Logstash 运行在一个 Pod ,让 Pod 的功能更加完整。

创建 Pod

创建一个含有两个容器:frontendbackend的 Pod。

  • backend: 每秒钟将现在的时间输出到共享存储空间的 index.html (/tmp/index.html)

  • frontend: 运行一个 Nginx 服务将共享存储空间中的 index.html 作为默认首页。

$ vim examply-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  labels:
    service: example-pod
spec:
  containers:
    - name: backend
      image: centos:7.4.1708
      command:
        - "bash"
        - "-c"
      args:
        - "while true; do date > /tmp/index.html; sleep 1;done"
      volumeMounts:
        - name: content-volume
          mountPath: /tmp
    - name: frontend
      image: nginx:1.10
      ports:
        - containerPort: 80
      volumeMounts:
        - name: content-volume
          mountPath: /usr/share/nginx/html/
  volumes:
    - name: content-volume
      emptyDir: {}

# kind 为 Pod 表明这是一个 Pod 的定义。
# metadata 里的 name 属性为 Pod 的名字,metadata 里还能定义资源对象的标签(Label),这里声明 example-pod 拥有一个 service=examply-pod 的标签。
# Pod 里所包含的容器组定义则在spec中声明,这里定义了两个容器,backend 和 frontend。

创建 Pod

$ kubectl create -f example-pod.yaml

查看 Pod

接下来我们在任意一个 Node 节点请求 nginx 服务都会出现当前时间

分配 Pod 运行到指定 Node 节点

目前 Kubernetes 支持 nodeSelector、affinity、anti-affinity 来限制每个 Pod 能够运行在哪些节点之上。下面介绍如何用 nodeSelector 实现此功能。

官方文档:https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity

1. 查询现有标签

$ kubectl get nodes --show-labels
NAME           STATUS    ROLES     AGE       VERSION   LABELS
10.100.4.197   Ready     <none>    57d       v1.9.0    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.100.4.197
10.100.4.198   Ready     <none>    57d       v1.9.0    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.100.4.198

2. 添加标签

假设我们的服务器性能有高有低,通过给 Node 添加不同的标签,我们可以更多的 Pod 运行在配置高的服务器上。

# 语法格式
$ kubectl label node <node name> <label>=<value>

# 在 10.100.4.197 节点上添加一个标签
$ kubectl label node 192.168.1.1 networkSpeed=high

检查标签是否更新到了节点上

root@k8s-master:~ # kubectl get nodes --show-labels                  
NAME           STATUS    ROLES     AGE       VERSION   LABELS
10.100.4.197   Ready     <none>    57d       v1.9.0    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.100.4.197,networkSpeed=high
10.100.4.198   Ready     <none>    57d       v1.9.0    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.100.4.198

3. 移除标签

# 语法格式
$ kubectl label node <node name> <label>-

# 移除 10.100.4.197 上的标签
$ kubectl label node 10.100.4.197 networkSpeed-
node "10.100.4.197" labeled

# 检查标签是否移除
$ kubectl get nodes --show-labels              
NAME           STATUS    ROLES     AGE       VERSION   LABELS
10.100.4.197   Ready     <none>    57d       v1.9.0    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.100.4.197
10.100.4.198   Ready     <none>    57d       v1.9.0    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.100.4.198

4. 创建测试 Deployment

$ vim test-deploy.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: test-deploy
spec:
  replicas: 1
  template:
    metadata:
      labels:
        env: beat
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
      nodeSelector:
        networkSpeed: high
        
# 创建 Deployment
$ kubectl create -f test-deploy.yaml

检查 Pod 是否运行在 networkSpeed=high 的节点

资源限制

Kubernetes 通过 cgroups 限制容器的 CPU 和内存等计算资源,包括requests(请求,调度器保证调度到资源充足的 Node 上)和 limits(上限)等:

  • spec.containers[].resources.limits.cpu:CPU 上限,可以短暂超过,容器也不会被停止。

  • spec.containers[].resources.limits.memory:内存上限,不可以超过;如果超过,容器可能会被停止或调度到其他资源充足的机器上。

  • spec.containers[].resources.requests.cpu:CPU请求,可以超过。

  • spec.containers[].resources.requests.memory:内存请求,可以超过;但如果超过,容器可能会在Node内存不足时清理。

比如nginx容器请求30%的CPU和56MB的内存,但限制最多只用50%的CPU和128MB的内存:

$ vim nginx-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  containers:
    - image: nginx
      name: nginx
      resources:
        requests:
          cpu: "300m"
          memory: "56Mi"
        limits:
          cpu: "500m"
          memory: "128Mi"

参考资料

https://www.kubernetes.org.cn/kubernetes-pod

http://shiyanjun.cn/archives/1671.html#comments

Search

    Table of Contents