kubernetes-handbook/introduction/101.md

6.6 KiB
Raw Blame History

Kubernetes 101

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

$ kubectl run --image=nginx nginx-app --port=80               
deployment "nginx-app" created                                         
$ kubectl get pods
NAME                         READY     STATUS    RESTARTS   AGE
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,在容器内执行一个命令
$ kubectl get pods
NAME                         READY     STATUS    RESTARTS   AGE
nginx-app-4028413181-cnt1i   1/1       Running   0          6m
$ kubectl exec nginx-app-4028413181-cnt1i ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.5  31736  5108 ?        Ss   00:19   0:00 nginx: master process nginx -g daemon off;
nginx        5  0.0  0.2  32124  2844 ?        S    00:19   0:00 nginx: worker process
root        18  0.0  0.2  17500  2112 ?        Rs   00:25   0:00 ps aux
$ kubectl describe pod nginx-app-4028413181-cnt1i
Name:  		nginx-app-4028413181-cnt1i
Namespace:     	default
Node:  		boot2docker/192.168.64.12
Start Time:    	Tue, 06 Sep 2016 08:18:41 +0800
Labels:		pod-template-hash=4028413181
       		run=nginx-app
Status:		Running
IP:    		172.17.0.3
Controllers:   	ReplicaSet/nginx-app-4028413181
Containers:
  nginx-app:
    Container ID:      		docker://4ef989b57d0a7638ad9c5bbc22e16d5ea5b459281c77074fc982eba50973107f
    Image:     			nginx
    Image ID:  			docker://sha256:4efb2fcdb1ab05fb03c9435234343c1cc65289eeb016be86193e88d3a5d84f6b
    Port:      			80/TCP
    State:     			Running
      Started: 			Tue, 06 Sep 2016 08:19:30 +0800
    Ready:     			True
    Restart Count:     		0
    Environment Variables:     	<none>
Conditions:
  Type 		Status
  Initialized  	True
  Ready        	True
  PodScheduled 	True
Volumes:
  default-token-9o8ks:
    Type:      	Secret (a volume populated by a Secret)
    SecretName:	default-token-9o8ks
QoS Tier:      	BestEffort
Events:
  FirstSeen    	LastSeen       	Count  	From   			SubobjectPath  			Type   		Reason 		Message
  ---------    	--------       	-----  	----   			-------------  			--------       	------ 		-------
  8m   		8m     		1      	{default-scheduler }   					Normal 		Scheduled      	Successfully assigned nginx-app-4028413181-cnt1i to boot2docker
  8m   		8m     		1      	{kubelet boot2docker}  	spec.containers{nginx-app}     	Normal 		Pulling		pulling image "nginx"
  7m   		7m     		1      	{kubelet boot2docker}  	spec.containers{nginx-app}     	Normal 		Pulled 		Successfully pulled image "nginx"
  7m   		7m     		1      	{kubelet boot2docker}  	spec.containers{nginx-app}     	Normal 		Created		Created container with docker id 4ef989b57d0a
  7m   		7m     		1      	{kubelet boot2docker}  	spec.containers{nginx-app}     	Normal 		Started		Started container with docker id 4ef989b57d0a


$ kubectl logs nginx-app-4028413181-cnt1i
127.0.0.1 - - [06/Sep/2016:00:27:13 +0000] "GET / HTTP/1.0 " 200 612 "-" "-" "-"
127.0.0.1 - - [06/Sep/2016:00:27:15 +0000] "GET / HTTP/1.0 " 200 612 "-" "-" "-"

使用yaml定义Pod

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

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80

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

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: nginx-app
  name: nginx-app
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-app
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        run: nginx-app
    spec:
      containers:
      - image: nginx
        name: nginx-app
        ports:
        - containerPort: 80
          protocol: TCP
      dnsPolicy: ClusterFirst
      restartPolicy: Always

使用Volume

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

apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    volumeMounts:
    - name: redis-persistent-storage
      mountPath: /data/redis
  volumes:
  - name: redis-persistent-storage
    hostPath:
      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

$ kubectl expose deployment nginx-app --type=NodePort --port=80 --target-port=80
service "nginx-app" exposed
$ kubectl describe service nginx-app
Name:  			nginx-app
Namespace:     		default
Labels:			run=nginx-app
Selector:      		run=nginx-app
Type:  			NodePort
IP:    			10.0.0.66
Port:  			<unset>	80/TCP
NodePort:      		<unset>	30772/TCP
Endpoints:     		172.17.0.3:80
Session Affinity:      	None
No events.

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