Kubernetes 101

体验Kubernetes最简单的方法是跑一个nginx容器,然后使用kubectl操作该容器。Kubernetes提供了一个类似于docker run的命令kubectl run,可以方便的创建一个容器(实际上创建的是一个由deployment来管理的Pod):

  1. $ kubectl run --image=nginx:alpine nginx-app --port=80
  2. deployment "nginx-app" created
  3. $ kubectl get pods
  4. NAME READY STATUS RESTARTS AGE
  5. nginx-app-4028413181-cnt1i 1/1 Running 0 52s

等到容器变成Running后,就可以用kubectl命令来操作它了,比如

  • kubectl get - 类似于docker ps,查询资源列表
  • kubectl describe - 类似于docker inspect,获取资源的详细信息
  • kubectl logs - 类似于docker logs,获取容器的日志
  • kubectl exec - 类似于docker exec,在容器内执行一个命令
  1. $ kubectl get pods
  2. NAME READY STATUS RESTARTS AGE
  3. nginx-app-4028413181-cnt1i 1/1 Running 0 6m
  4. $ kubectl exec nginx-app-4028413181-cnt1i ps aux
  5. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  6. root 1 0.0 0.5 31736 5108 ? Ss 00:19 0:00 nginx: master process nginx -g daemon off;
  7. nginx 5 0.0 0.2 32124 2844 ? S 00:19 0:00 nginx: worker process
  8. root 18 0.0 0.2 17500 2112 ? Rs 00:25 0:00 ps aux
  9. $ kubectl describe pod nginx-app-4028413181-cnt1i
  10. Name: nginx-app-4028413181-cnt1i
  11. Namespace: default
  12. Node: boot2docker/192.168.64.12
  13. Start Time: Tue, 06 Sep 2016 08:18:41 +0800
  14. Labels: pod-template-hash=4028413181
  15. run=nginx-app
  16. Status: Running
  17. IP: 172.17.0.3
  18. Controllers: ReplicaSet/nginx-app-4028413181
  19. Containers:
  20. nginx-app:
  21. Container ID: docker://4ef989b57d0a7638ad9c5bbc22e16d5ea5b459281c77074fc982eba50973107f
  22. Image: nginx
  23. Image ID: docker://sha256:4efb2fcdb1ab05fb03c9435234343c1cc65289eeb016be86193e88d3a5d84f6b
  24. Port: 80/TCP
  25. State: Running
  26. Started: Tue, 06 Sep 2016 08:19:30 +0800
  27. Ready: True
  28. Restart Count: 0
  29. Environment Variables: <none>
  30. Conditions:
  31. Type Status
  32. Initialized True
  33. Ready True
  34. PodScheduled True
  35. Volumes:
  36. default-token-9o8ks:
  37. Type: Secret (a volume populated by a Secret)
  38. SecretName: default-token-9o8ks
  39. QoS Tier: BestEffort
  40. Events:
  41. FirstSeen LastSeen Count From SubobjectPath Type Reason Message
  42. --------- -------- ----- ---- ------------- -------- ------ -------
  43. 8m 8m 1 {default-scheduler } Normal Scheduled Successfully assigned nginx-app-4028413181-cnt1i to boot2docker
  44. 8m 8m 1 {kubelet boot2docker} spec.containers{nginx-app} Normal Pulling pulling image "nginx"
  45. 7m 7m 1 {kubelet boot2docker} spec.containers{nginx-app} Normal Pulled Successfully pulled image "nginx"
  46. 7m 7m 1 {kubelet boot2docker} spec.containers{nginx-app} Normal Created Created container with docker id 4ef989b57d0a
  47. 7m 7m 1 {kubelet boot2docker} spec.containers{nginx-app} Normal Started Started container with docker id 4ef989b57d0a
  48. $ curl http://172.17.0.3
  49. <!DOCTYPE html>
  50. <html>
  51. <head>
  52. <title>Welcome to nginx!</title>
  53. <style>
  54. body {
  55. width: 35em;
  56. margin: 0 auto;
  57. font-family: Tahoma, Verdana, Arial, sans-serif;
  58. }
  59. </style>
  60. </head>
  61. <body>
  62. <h1>Welcome to nginx!</h1>
  63. <p>If you see this page, the nginx web server is successfully installed and
  64. working. Further configuration is required.</p>
  65. <p>For online documentation and support please refer to
  66. <a href="http://nginx.org/">nginx.org</a>.<br/>
  67. Commercial support is available at
  68. <a href="http://nginx.com/">nginx.com</a>.</p>
  69. <p><em>Thank you for using nginx.</em></p>
  70. </body>
  71. </html>
  72. $ kubectl logs nginx-app-4028413181-cnt1i
  73. 127.0.0.1 - - [06/Sep/2016:00:27:13 +0000] "GET / HTTP/1.0 " 200 612 "-" "-" "-"

使用yaml定义Pod

上面是通过kubectl run来启动了第一个Pod,但是kubectl run并不支持所有的功能。在Kubernetes中,更经常使用yaml文件来定义资源,并通过kubectl create -f file.yaml来创建资源。比如,一个简单的nginx Pod可以定义为:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: nginx
  5. labels:
  6. app: nginx
  7. spec:
  8. containers:
  9. - name: nginx
  10. image: nginx
  11. ports:
  12. - containerPort: 80

前面提到,kubectl run并不是直接创建一个Pod,而是先创建一个Deployment资源(replicas=1),再由与Deployment关联的ReplicaSet来自动创建Pod,这等价于这样一个配置:

  1. apiVersion: extensions/v1beta1
  2. kind: Deployment
  3. metadata:
  4. labels:
  5. run: nginx-app
  6. name: nginx-app
  7. namespace: default
  8. spec:
  9. replicas: 1
  10. selector:
  11. matchLabels:
  12. run: nginx-app
  13. strategy:
  14. rollingUpdate:
  15. maxSurge: 1
  16. maxUnavailable: 1
  17. type: RollingUpdate
  18. template:
  19. metadata:
  20. labels:
  21. run: nginx-app
  22. spec:
  23. containers:
  24. - image: nginx
  25. name: nginx-app
  26. ports:
  27. - containerPort: 80
  28. protocol: TCP
  29. dnsPolicy: ClusterFirst
  30. restartPolicy: Always

使用Volume

Pod的生命周期通常比较短,只要出现了异常,就会创建一个新的Pod来代替它。那容器产生的数据呢?容器内的数据会随着Pod消亡而自动消失。Volume就是为了持久化容器数据而生,比如可以为redis容器指定一个hostPath来存储redis数据:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: redis
  5. spec:
  6. containers:
  7. - name: redis
  8. image: redis
  9. volumeMounts:
  10. - name: redis-persistent-storage
  11. mountPath: /data/redis
  12. volumes:
  13. - name: redis-persistent-storage
  14. hostPath:
  15. path: /data/

Kubernetes volume支持非常多的插件,可以根据实际需要来选择:

  • emptyDir
  • hostPath
  • gcePersistentDisk
  • awsElasticBlockStore
  • nfs
  • iscsi
  • flocker
  • glusterfs
  • rbd
  • cephfs
  • gitRepo
  • secret
  • persistentVolumeClaim
  • downwardAPI
  • azureFileVolume
  • vsphereVolume

使用Service

前面虽然创建了Pod,但是在kubernetes中,Pod的IP地址会随着Pod的重启而变化,并不建议直接拿Pod的IP来交互。那如何来访问这些Pod提供的服务呢?使用Service。Service为一组Pod(通过labels来选择)提供一个统一的入口,并为它们提供负载均衡和自动服务发现。比如,可以为前面的nginx-app创建一个service:

  1. $ kubectl expose deployment nginx-app --port=80 --target-port=80 --type=NodePort
  2. service "nginx-app" exposed
  3. $ kubectl describe service nginx-app
  4. Name: nginx-app
  5. Namespace: default
  6. Labels: run=nginx-app
  7. Selector: run=nginx-app
  8. Type: ClusterIP
  9. IP: 10.0.0.66
  10. Port: <unset> 80/TCP
  11. NodePort: <unset> 30772/TCP
  12. Endpoints: 172.17.0.3:80
  13. Session Affinity: None
  14. No events.

这样,在cluster内部就可以通过http://10.0.0.66http://node-ip:30772来访问nginx-app。而在cluster外面,则只能通过http://node-ip:30772来访问。