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

使用 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
Copied!
前面提到,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
Copied!

使用 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/
Copied!
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.
Copied!
这样,在 cluster 内部就可以通过 http://10.0.0.66http://node-ip:30772 来访问 nginx-app。而在 cluster 外面,则只能通过 http://node-ip:30772 来访问。
最近更新 2mo ago