在安装完 Kubernets 之后,下一步就该开始玩耍 Kubernetes 了,当你玩 Kubernetes 的时候,你会有一个很直观的感受,那么就是在 Kubernetes 中,一切都是资源,你可以通过 get/describe/delete 来操作这些资源,那么这些资源本质上都是做什么用可能你还不太了解。所以,第一种我要介绍的资源就是 Kubernetes 中的原子资源:Pod。

Kubernetes 最初大家对它的定位是容器编排工具,但是,事实上我们在使用的时候并不是直接和容器打交道,反而是一种叫作 Pod 的资源接触得比较多。Pod 可以理解为运行某一种服务的资源,内部其实还是容器,那么为什么不直接用容器就好了,还要引入一个和容器差不多的概念:Pod。

注意,这里的用词是“差不多”的概念,意思就是有一些区别,而这些区别却是影响很重要的点,假设这么一个场景,你想提供一个开箱即用的博客系统,以前在容器的时候你可以就将代码和数据库都塞到同一个 Container 里面了,然后别人直接 docker run 就开启了一个博客系统,但是,这样的模式却是有很多问题,这里列举几个:

所以 Pod 存在得意义就出来了,你可以提供开箱即用的资源:Pod,但是缺不用放在同一个容器里面。

Pod 的操作

在 Kubernetes 里面,操作 Pod 也是极为简单的,在 K8S 中,对于集群资源的操作虽然使用命令行都是没关系的,但是,推荐使用 YAML 配置文件来更好一些,复用性自然不用说,命令执行也简单呀,而且还遍于追踪管理。

在操作一种资源之前,我们需要先对这个资源进行定义,在 K8S 中,常用的方式是用 YAML 配置文件配置,下面我就给出一个简单的执行 Nginx 的配置:

  1. [root@liqiang.io]# cat /home/liqiang.io/blog/kubernetes/guide/chap03/00-simple-pod.yaml
  2. ---
  3. apiVersion: v1
  4. kind: Pod
  5. metadata:
  6. name: first-pod
  7. labels:
  8. app: nginx
  9. spec:
  10. containers:
  11. - name: 00-simple-pod-nginx
  12. image: nginx:1.17.0

这就是一个 K8S 资源定义的比较通用的方式了,对于 K8S 的资源(包括自定义的)来说,这几个字段都是必包含的:

例如我这里是运行一个 Nginx 的 Pod,那么就需要指定我要运行的是哪个版本的 Nginx,运行的 Container 叫什么名字,除此之外就可以不指定其他参数了。启动一个 Pod 很简单,你可以通过:

  1. [root@liqiang.io]# kubectl apply -f 00-simple-pod.yaml
  2. pod/first-pod created

就这么简单,你就让你定义的资源运行在了 K8S 之上,对于更新也是那么简单,分两步:

  1. 修改一下资源的定义文件
  2. 再次执行 kubectl apply -f 00-simple-pod.yaml 就可以了

那么我们要怎么知道我执行的这个 Pod 的状态呢?这个很简单,可以直接通过:

  1. [root@liqiang.io]# kubectl get pods first-pod
  2. NAME READY STATUS RESTARTS AGE
  3. first-pod 0/1 ContainerCreating 0 8m2s

这样就可以看到我们 Pod 的状态了,很显然,这里的 Pod 并没有成功运行起来,而是出于一个叫作 ContainerCreating 的状态,那么我们想知道更多关于这个 Pod,或者说 Pod 里面的 Container 的细节,那么可以尝试看一下这个 Pod 的详情:

  1. [root@liqiang.io]# kubectl describe pods first-pod
  2. Name: first-pod
  3. ... ...
  4. Events:
  5. Type Reason Age From Message
  6. ---- ------ ---- ---- -------
  7. Normal Scheduled 10m default-scheduler Successfully assigned default/first-pod to host-79
  8. Warning FailedCreatePodSandBox 6m40s (x8 over 9m52s) kubelet, host-79 Failed create pod sandbox: rpc error: code = Unknown desc = failed pulling image "k8s.gcr.io/pause:3.1": Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
  9. Warning DNSConfigForming 5m2s (x12 over 10m) kubelet, host-79 Nameserver limits were exceeded, some nameservers have been omitted, the applied nameserver line is: 192.168.1.21 192.168.48.1 8.8.8.8
  10. Warning MissingClusterDNS <invalid> (x23 over 10m) kubelet, host-79 pod: "first-pod_default(a79f2657-9a6a-11e9-9a22-5254006b0617)". kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to "Default" policy.

OK,很明显,从这个 Events 中可以看到问题就除在 K8S 在拉取镜像的时候出现了问题,而且也明确得告诉了我们这个 Pod 所在的机器是哪个,所以我们需要解决这个网络问题,解决方式多种,当你解决之后,再来看一下:

  1. [root@liqiang.io]# k get pods first-pod
  2. NAME READY STATUS RESTARTS AGE
  3. first-pod 1/1 Running 0 51m

可以看到这个时候 Pod 的状态就是 Running 了,就表示我们的 Pod 已经创建成功了。

设置环境变量为运行参数

  1. [root@liqiang.io]# kubectl descirbe pods
  2. spec:
  3. containers:
  4. - args:
  5. - -c
  6. - /config/envoy.yaml
  7. - --log-path
  8. - /log/$(POD_NAME).log
  9. env:
  10. - name: POD_NAME
  11. valueFrom:
  12. fieldRef:
  13. apiVersion: v1
  14. fieldPath: metadata.name

小结

本文就介绍了一下 K8S 的基本单元 Pod,并且介绍了一下 K8S 中资源的通用结构以及 Pod 的一些基本操作。下面是一些没有提到的 Pod 附带信息。

Pod 和 Container 的状态

日志

外部访问 POD

注解

向Kubemetes引入新特性时,通常也会使用注解 。一般来说,新功能的 alpha 和 beta 版本不会向 API 对象引入任何新字段,因此使用的是注解 而不是字段,一旦所需的API更改变得清晰并得到所有相关人员的认可,就会引入新的字段并废弃相关注解。

大量使用注解可以为每个pod或其他API对象添加说明,以便每个使用该集群的入都可以快速查找有关每个单独对象的信息。

Pod 探针

重启策略