Docker集群管理之Kubernetes

docker技术 靠谱运维 3494℃ 0评论

一、概念简介

Kubernetes是Google开源的容器集群管理系统。它构建Ddocker技术之上,为容器化的应用提供资源调度、部署运行、服务发现、扩容缩容等整一套功能,本质上可看作是基于容器技术的mini-PaaS平台。本文旨在梳理Kubernetes的架构、概念及基本工作流,并且通过运行一个简单的示例应用来介绍如何使用Kubernetes。

优点:

—轻量级、简单

—公有云、私有云、混合云部署

—模块化、可插拔化、可挂接、可组合

—自动恢复、自动重启、自动复制

总体概览

如下图(网上摘的,经典图)所示,基本上可以从如下三个维度来认识Kubernetes。

操作对象

Kubernetes以RESTFul形式开放接口,用户可操作的REST对象有三个:

  • pod:是Kubernetes最基本的部署调度单元,可以包含container,逻辑上表示某种应用的一个实例。比如一个web站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那么我们可以创建包含三个container的pod。
  • service:是pod的路由代理抽象,用于解决pod之间的服务发现问题。因为pod的运行状态可动态变化(比如切换机器了、缩容过程中被终止了等),所以访问端不能以写死IP的方式去访问该pod提供的服务。service的引入旨在保证pod的动态变化对访问端透明,访问端只需要知道service的地址,由service来提供代理。
  • replicationController:是pod的复制抽象,用于解决pod的扩容缩容问题。通常,分布式应用为了性能或高可用性的考虑,需要复制多份资源,并且根据负载情况动态伸缩。通过replicationController,我们可以指定一个应用需要几份复制,Kubernetes将为每份复制创建一个pod,并且保证实际运行pod数量总是与该复制数量相等(例如,当前某个pod宕机时,自动创建新的pod来替换)。可以看到,service和replicationController只是建立在pod之上的抽象,最终是要作用于pod的,那么它们如何跟pod联系起来呢?这就要引入label的概念:label其实很好理解,就是为pod加上可用于搜索或关联的一组key/value标签,而service和replicationController正是通过label来与pod关联的。如下图所示,有三个pod都有label为”app=backend”,创建service和replicationController时可以指定同样的label:”app=backend”,再通过label selector机制,就将它们与这三个pod关联起来了。例如,当有其他frontend pod访问该service时,自动会转发到其中的一个backend pod。

功能组件

master运行三个组件:

  • apiserver:作为kubernetes系统的入口,封装了核心对象的增删改查操作,以RESTFul接口方式提供给外部客户和内部组件调用。它维护的REST对象将持久化到etcd(一个分布式强一致性的key/value存储)。
  • scheduler:负责集群的资源调度,为新建的pod分配机器。这部分工作分出来变成一个组件,意味着可以很方便地替换成其他的调度器。
  • controller-manager:负责执行各种控制器,目前有两类:
  • endpoint-controller:定期关联service和pod(关联信息由endpoint对象维护),保证service到pod的映射总是最新的。
  • replication-controller:定期关联replicationController和pod,保证replicationController定义的复制数量与实际运行pod的数量总是一致的。

slave(称作minion)运行两个组件:

  • kubelet:负责管控docker容器,如启动/停止、监控运行状态等。它会定期从etcd获取分配到本机的pod,并根据pod信息启动或停止相应的容器。同时,它也会接收apiserver的HTTP请求,汇报pod的运行状态。
  • proxy:负责为pod提供代理。它会定期从etcd获取所有的service,并根据service信息创建代理。当某个客户pod要访问其他pod时,访问请求会经过本机proxy做转发。

功能特性

将在之后慢慢融入

 

二、最初搭建

需要至少一个master和一个minion,为了方便以后操作,可以先定义hosts(这里只用了两台,如果做两台以上需要网络支持,参考之前Docker网络部分)

10.20.161.77    centos-master

10.20.161.88    centos-minion

 

1、使用yum安装【master、minion】

vim /etc/yum.repos.d/virt7-testing.repo

1
2
3
4
[virt7-testing]
name=virt7-testing
baseurl=http://cbs.centos.org/repos/virt7-testing/x86_64/os/
gpgcheck=0

如果之前安装了docker,防止版本冲突,需要卸载之前安装的版本,安装kubernetes的时候会自动安装docker。

1
yum -y install --enablerepo=virt7-testing kubernetes

2、关闭防火墙【master、minion】

systemctl disable iptables-services firewalld

systemctl stop iptables-services firewalld

 

3、修改公共配置文件【master、minion】

vim /etc/kubernetes/config

KUBE_MASTER=”–master=http://centos-master:8080″

KUBE_ETCD_SERVERS=”–etcd_servers=http://centos-master:4001″   #下面安装

 

4、安装etcd【master】

yum install http://cbs.centos.org/kojifiles/packages/etcd/0.4.6/7.el7.centos/x86_64/etcd-0.4.6-7.el7.centos.x86_64.rpm

 

5、修改apiserver配置文件【master】

vim /etc/kubernetes/apiserver

KUBE_API_ADDRESS=”–address=0.0.0.0″

KUBE_API_PORT=”–port=8080″

#KUBE_ETCD_SERVERS=”–etcd_servers=http://127.0.0.1:2379″     注释掉

 

6、启动master相关服务(全部为active running状态则为正常,否则tail -f /var/log/messages |grep kube查看错误日志)

vim /etc/init.d/kubernetes-master

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/bash
usage () {
        echo -en "Usage: $0 {start|stop|restart|status|enable}\n" 1>&2
        exit 1
}
CMD="$1"
if [ -z "${CMD}" ];then
        usage
fi
# For minion
#for SERVICES in kube-proxy kubelet docker
# For master
for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler
do
        case "${CMD}" in
                'start'*)
                        systemctl start $SERVICES
                        ;;
                'stop'*)
                        systemctl stop $SERVICES
                        ;;
                'restart'*)
                        systemctl restart $SERVICES
                        ;;
                'status'*)
                        systemctl status $SERVICES
                        ;;
                'enable'*)
                        systemctl enable $SERVICES
                        ;;
                *)
                        usage
                        exit 1
                        ;;
        esac
done

 

7、修改kubelet配置文件【minion】

vim /etc/kubernetes/kubelet

KUBELET_ADDRESS=”–address=0.0.0.0″

KUBELET_PORT=”–port=10250″

KUBELET_HOSTNAME=”–hostname_override=centos-minion”

KUBELET_API_SERVER=”–api_servers=http://centos-master:8080“

 

8、启动minion相关服务【minion】

vim kubernetes-minion

参考上面脚本修改即可。

 

9、minion导入根镜像pause【minion】PS:所有容器的根镜像,必备。因可能被墙,所以需要手动导入。

下载地址:http://pan.baidu.com/s/1o72tqSq

1
2
docker load < pause.tar    #导入
docker tag gcr.io/google_containers/pause gcr.io/google_containers/pause:0.8.0    #改名

 

10、查看状态是否正常【master】

kubectl get nodes

查看到节点注册成功,则表明系统安装正常

 

三、常用命令(持续更新)

https://cloud.google.com/container-engine/docs/kubectl/     #官网参数详解

kubectl –help

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  get              #查看各类资源信息
  describe         #查看各类资源的详细信息,排错很有用
  create           #创建资源,后面跟-f参数指定文件名(json/yaml),或者标准输入比如管道
  replace          #替换资源和create 类似
  patch            #更新资源信息,和replace作用类似,但这个是直接在命令行里修改资源的某项信息,类似于打补丁
  delete           #删除资源,指定资源类型以及资源名称
  namespace        #查看或者设置命名空间相关,没试过
  logs             #打印日志,排错很有用
  rolling-update   #在线升级版本
  scale            #在线动态设置rc的副本数量
  exec             #在某个容器里执行命令
  port-forward     #设置pod的映射端口
  proxy            #设置一个apiserver的代理
  run              #运行一个rc,用于简单测试,创建资源建议还是创建完整的yaml文件
  stop             #停止某个资源,可以是名称或者文件名
  expose           #映射rc,svc,pod的端口
  label            #设置资源的label
  config           #配置修改kubeconfig,具体应用规则见官网
  cluster-info     #查看集群信息
  api-versions     #查看api的版本
  version          #查看版本号
  help             #帮助

1、常用操作类

kubectl create -f XXX.yaml   根据yaml文件创建指定的资源   –validate检测配置文件是否正确

kubectl delete pod POD_NAME 删除指定pod

kubectl scale rc RC名 –replicas=5   动态调整pod数量

kubectl rolling-update RC名 –update-period=3s –image=XXXX    每隔3秒钟进行更新images

kubectl patch pod valid-pod -p ‘{“spec”:{“containers”:[{"name":"kubernetes-serve-hostname","image":"new image"}]}}’              修改vaild-pod的image名称

kubectl run nginx-test01 –image=10.20.161.77:5000/nginx      运行一个rc

 

2、常用排错类

kubectl get po,rc,svc  查看pods、rc、service列表

kubectl describe pod POD_NAME  查看某个pod的具体信息

kubectl get pod nginx -o yaml   以yaml的格式输出pod更详细的信息

kubectl get nodes 查看工作节点列表

kubectl get events  查看事件信息

kubectl logs POD_NAME 查看pod的输出日志

kubectl label nodes centos-minion01 zone=minion01  设置node的label标签

 

 

四、资源配置解析(期待完善)

kubernetes里面几乎一切都是资源,那么创建各种资源就依赖于配置文件,跟好多软件类似,k8s默认装好也就是空壳,什么都没有,一切都需要自己定义各种配置文件,然后基于配置文件来创建资源。下面就开始来解析各类配置文件。Google官方说明地址:https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/HEAD/docs/api-reference/v1/definitions.html

Pods:目的是为了更好的进行资源共享以及容期间的通信

  • 创建、调度以及管理的最小单元(docker里是容器,在k8s的世界里是pods)
  • 共存的一组容器的集合(也就是说pods是一个或者多个容器组成的单位)
  • 容器共享PID、网络、IPC以及UTS命名空间(同一个pod里的容器可以看到彼此的进程,可以使用同样的ip及端口,可以使用System V IPC或者posix通信,可以使用相同的主机名)
  • 容器共享存储卷(同一个pods里的容器可以共享存储卷)
  • 短暂存在(和容器一样属于短暂存在,共四个状态:Pending(指令已被系统接受,但容器并未创建)、Running(成功运行)、Successed(pod里的容器已被成功停止)、Failed(pod里的容器出现停止错误))
  • 下面来创建一个pod例子

vim nginx-pod.yaml

1
2
3
4
5
6
7
8
9
10
apiVersion: v1                           #api版本号
kind: Pod                                #定义资源类型
metadata:                                #定义资源属性信息
    name: nginx
spec:                                    #定义资源的具体信息
    containers:
    - name: nginx
      image: 10.20.161.77:5000/nginx
      ports:
      - containerPort: 80

kubectl create -f nginx-pod.yaml

列一些常用参数:

command: ["/bin/echo"]

args: ["hello","world"]

 

Volumes:目的是为了解决数据的持久化问题

  • 数据持久化(容器的数据是短暂存在的,当容器奔溃时,数据丢失,Volumes就是为了解决这个问题)
  • pod中容器共享数据(同一pod里的容器可以共享数据)
  • 生命周期(和定义pod的生命周期一样,当一个pod被停止退出,那么volumes也停止退出)
  • 支持多种类型的数据卷
  • emptyDir:初始为空,是在Pod分配到Node时创建,当Pod移除时,emptyDir里的数据也会永久删除。但当容器奔溃时,数据不会删除。

用途:

临时空间,例如用于某些应用程序运行时所需的临时目录,且无需永久保留

长时间任务的中间过程CheckPoint临时保存目录

一个容器需要从另一个容器中获取数据的目录(多容器共享目录)

  • hostpath:在Pod上挂载宿主机上的文件或目录

用途:

容器应用程序生成的日志文件需要永久保留,可以使用宿主机的告诉文件系统进行存储

需要访问宿主机上Docker引擎内部数据的容器应用,可以通过定义hostpath为宿主机/var/lib/docker目录使用容器内部应用可以直接访问Docker的文件系统

需要注意:

在不同Node上具有相同配置的pod可能会因为宿主机上的目录和文件不同而导致对Volumes上目录和文件访问结果不一致

  • 云存储:gcePersistentDisk、awkElasticBlockStore
  • 网络存储:nfs、iscsi、glusterfs
  • secrets:用来保存敏感数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Pod
metadata:
    name: redis
spec:
    containers:
    - name: redis
      image: 10.20.161.77:5000/redis
      VolumeMounts:                                    #4、对容器的属性进行定义        
      - name: redis-persistent-storage                 #5、指定调用名称为redis-persistent-storage的volumes,也就是下方预先定义的
        mountpath: /data/redis                         #6、挂载到容器内部的路径
    Volumes:                                     #1、定义一个Volumes资源
    - name: redis-persistent-storage             #2、定义Volumes资源名称
      emptyDir: {}                               #3、定义Volumes的类型

 

Lables:目的是为了更方便的选取对象

  • 用以标示对象(如Pod)的key/value对(就是比如定义pod的时候定义一个 app:nginx,那么选择的时候就可以通过标签选择器选择所有app=nginx的pod)
  • 组织并选择对象子集
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1                           #api版本号
kind: Pod                                #定义资源类型
metadata:                                #定义资源属性信息
    name: nginx
    lables:                              #定义lables
      app: nginx                         #定义key/value对
spec:                                    #定义资源的具体信息
    containers:
    - name: nginx
      image: 10.20.161.77:5000/nginx
      ports:
      - containerPort: 80

选择的话可以使用参数 -l,例如:kubectl get pods -l app=nginx

 

Replication Controllers:目的是保证pods始终保持预定义的状态运行,rc应该算是k8s里最棒的设计了。

  • 确保在任一时刻运行指定数目的Pod
  • 容器重新调度(监控多台主机上的多个pod,当A主机上出现问题,那么会自动把A主机上的pod调度到B主机上。)
  • 规模调整(如果要规模调整,那么只需要修改需要运行的pod数量,rc便会根据现有的数量进行增减操作)
  • 在线升级(通过一个接着一个的升级替换的方式,可以实现在线升级。需要至少一处lables不同以标记不同版本)
  • 多发布版本跟踪
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: ReplicationController
metadata:
   name: nginx-controller
spec:
   replicas: 2                      #定义运行pod的数量为2
   selector:                        #定义标签选择器为app=nginx
     app: nginx
   template:                        #定义rc的模板(和定义pod的方法类似,见上方pod的解释)
     metadata:
        labels:
           app: nginx
     spec:
        containers:
        - name: nginx
          image: 10.20.161.77:5000/nginx
          ports:
          - containerPort: 80

创建好之后,就可以使用kubectl get rc nginx-controller来查看刚刚创建的rc。

PS:可以做个小验证:查看pods关于刚刚创建好的pod有两个,是以nginx-controller开头的。手动delete一个。看会发生什么?

 

Services:目的是解决了pod对外访问的问题

  • 抽象一系列Pod并定义其访问规则
  • 固定ip地址和DNS域名
  • 通过环境变量和DNS发现服务
  • 负载均衡
  • 外部服务
  • ClusterIP:使用集群内的私有ip —— 这是默认值。
  • NodePort:除了使用cluster ip外,也将service的port映射到每个node的一个指定内部port上,映射的每个node的内部port都一样。PS:网上有说法是在工作节点暴露端口,其实准确说法应该是node上映射一个随机端口来指向service里定义的端口,然后通过iptables的规则来实现转发。具体解析见最后附
  • LoadBalancer:使用一个ClusterIP & NodePort,但是会向cloud provider申请映射到service本身的负载均衡。  (注意:NodePort支持TCP/UDP,LoadBalancer只支持TCP)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Service                   #资源为Service
metadata:
    name: nginx-service
    labels:
      app: nginx
spec:
    type: NodePort              #类型为NodePort,默认为ClusterIP
    selector:
      app: nginx                #定义选择器为所有app=nginx的pod
    ports:                      #定义端口相关
    - port: 80                  #源端口(容器的端口)
      protocol: TCP             #协议类型
      nodePort: 30001           #暴露外部的端口(访问方式就是用任一节点的ip加上nodePort的端口)

PS:如果习惯使用–validate来测试配置文件的话,有可能测试service的时候会一直报:error validating data: field nodePort: is required。网上查了说可能是bug,忽略错误,直接创建即可。

–service-node-port-range=: A port range to reserve for services with NodePort visibility.  Example: ’30000-32767′.  用来指定服务映射的端口范围

 

五、常见问题(持续更新)

1、启动kubernetes时,查看日志出现如下提示,是因为没有相应的目录,以及授权。

Nov 13 19:19:29 xutao kube-apiserver[13630]: E1113 19:19:29.981529   13630 server.go:454] Unable to generate self signed cert: open /var/run/kubernetes/apiserver.crt: permission denied

 

Nov 13 19:19:29 xutao kube-apiserver[13630]: E1113 19:19:29.981624   13630 server.go:464] Unable to listen for secure (open /var/run/kubernetes/apiserver.crt: no such file or directory); will try again.

 

解决办法:

 

vim /usr/lib/systemd/system/kube-apiserver.service

1
2
3
4
[Service]
PermissionsStartOnly=true
ExecStartPre=-/usr/bin/mkdir /var/run/kubernetes
ExecStartPre=/usr/bin/chown -R kube:kube /var/run/kubernetes/

systemctl daemon-reload

重启kube-apiserver

systemctl restart kube-apiserver.service

systemctl status kube-apiserver.service

或者(关闭https):

vim /etc/kubernetes/apiserver

可以在KUBE_API_ARGS加上–secure-port=0

systemctl restart kube-apiserver.service

 


 

2、使用yaml文件创建资源时出现如下提示,是由于默认开启了鉴权,关闭接口。

[root@xutao kubernetes]# kubectl create -f nginx-pod.yaml

Error from server: error when creating “nginx-pod.yaml”: Pod “nginx” is forbidden: no API token found for service account default/default, retry after the token is automatically created and added to the service account

解决办法:

vim /etc/kubernetes/apiserver

1
KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"

将ServiceAccount,去掉

systemctl restart kube-apiserver  重启apiserver服务

 


 

3、创建pod时出现如下提示,是由于缺少的镜像pause被墙了。

解决办法:

需要pause的镜像,可以现在这个已经被墙,使用附件的tar包,手动导入到docker里。(具体见上方部署部分)

也可以指定内网仓库

vim /etc/kubernetes/kubelet

KUBELET_ARGS=”–pod-infra-container-image=docker3:5000/pause:latest”

 


 

4、etcd版本问题,原因为新版的端口和旧版本的端口不一致

解决办法(两种):

  • 更改为旧版本0.4.6
  • 更改apiserver的配置文件,使用2379端口

 


 

5、docker无法启动,原因有可能磁盘不够,或者没有解析到。

Nov 19 20:29:36 centos7 systemd: Starting Docker Storage Setup…

Nov 19 20:29:36 centos7 docker-storage-setup: Rounding up size to full physical extent 32.00 MiB

Nov 19 20:29:36 centos7 docker-storage-setup: Volume group “centos_centos7″ has insufficient free space (0 extents): 8 required.

Nov 19 20:29:36 centos7 systemd: docker-storage-setup.service: main process exited, code=exited, status=5/NOTINSSTALLED

Nov 19 20:29:36 centos7 systemd: Failed to start Docker Storage Setup.

Nov 19 20:29:36 centos7 systemd: Unit docker-storage-setup.service entered failed state.

Nov 19 20:29:36 centos7 systemd: Starting Docker Application Container Engine…

Nov 19 20:29:36 centos7 docker: time=”2015-11-19T20:29:36.538243264+08:00″ level=info msg=”Listening for HTTP on unix (/var/run/docker.sock)”

Nov 19 20:29:36 centos7 docker: time=”2015-11-19T20:29:36.540394247+08:00″ level=error msg=”WARNING: No –storage-opt dm.thinpooldev specified, using loopback; this configuration is strongly discouraged for production use”

解决办法:

增加vg容量,重启机器试试

不行就删除 /usr/lib/systemd/system/docker.service 里的DOCKER_STORAGE_OPTIONS

systemctl daemon-reload

systemctl restart docker.service

 


 

6、还是无法启动docker,原因可能为docker没有识别到正常的thinpooldev,需要手动指定

Error starting daemon: error initializing graphdriver: EOF

/usr/bin/docker daemon –selinux-enabled –storage-driver devicemapper –storage-opt dm.fs=xfs –storage-opt dm.thinpooldev=/dev/mapper/centos_centos7-docker–pool-tpool

解决办法:

https://gist.github.com/joshix/ec1673f2791bf5cb352f#file-thin-pool-md

dmsetup status

找到tpool结尾的那行,比如centos_centos7-docker–pool-tpool

修改文件

vim /etc/sysconfig/docker-storage

DOCKER_STORAGE_OPTIONS=–storage-driver devicemapper –storage-opt dm.fs=xfs –storage-opt dm.thinpooldev=/dev/mapper/centos_centos7-docker–pool-tpool

重启

systemctl daemon-reload

systemctl restart docker.service

 


 

7、node为不可用状态,查看日志发现

Nov 19 16:19:57 centos-master kube-controller-manager: W1119 16:19:57.618729   11352 nodecontroller.go:256] Missing timestamp for Node centos-minion01. Assuming now as a timestamp.

解决办法:

尝试时间同步

 


 

8、pull镜像失败,原因是没有添加信任地址

Failed to pull image “10.20.161.77:5000/mysql”: unable to ping registry endpoint https://10.20.161.77:5000/v0/

解决办法:

手动添加信任关系

vim /etc/sysconfig/docker

INSECURE_REGISTRY=’–insecure-registry 10.20.161.77:5000′

重启服务

systemctl restart docker

 


 

9、node上iptables的问题

[root@centos-minion01 shell]# iptables -nL –line-numbers

Chain INPUT (policy ACCEPT)

num  target     prot opt source               destination

1    ACCEPT     all  –  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED

2    ACCEPT     icmp —  0.0.0.0/0            0.0.0.0/0

3    ACCEPT     all  –  0.0.0.0/0            0.0.0.0/0

4    ACCEPT     tcp  –  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22

5    REJECT     all  –  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)

num  target     prot opt source               destination

1    DOCKER     all  –  0.0.0.0/0            0.0.0.0/0

2    ACCEPT     all  –  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED

3    ACCEPT     all  –  0.0.0.0/0            0.0.0.0/0

4    ACCEPT     all  –  0.0.0.0/0            0.0.0.0/0

5    REJECT     all  –  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

如果在node上的iptables规则如上所示。

解决办法:

  • 测试环境:iptables -D INPUT 5  && iptables -D FORWARD 5
  • 生产环境:允许三个网段通过
  • node的IP段
  • 容器的Ip段
  • 内部service的IP段

 


 

10、Docker官网的留言板例子:guestbook页面 出错,原因可能是js地址被墙

解决办法:

1、进入容器

PID=$(docker inspect –format {{.State.Pid}} <容器id>)

nsenter –target $PID –mount –uts –ipc –net –pid

2、Debian安装nano编辑器

apt-get install nano -y

3、修改/var/www/html/index.html

将//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css

修改为//cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css

将https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js

修改为//cdn.bootcss.com/angular.js/1.2.12/angular.min.js

PS:CTRL+O回车保存,CTRL+X退出

4、重启服务

apache2-foreground

 


 

11、在利用yaml文件创建Pod过程中,报“Error from server:the server could not find the requested resource”

这个问题最坑,原因是Kubernetes版本太低,虽然node节点的状态显示是Ready,但无法创建Pod。

伴随现象:在描述节点状态时,显示如下,正常的是没有红色方框部分。

而且显示的版本信息如下:

注意:该版本信息却与Kubernetes官方提供的yum源中的版本信息吻合:http://cbs.centos.org/repos/virt7-testing/x86_64/os/Packages/

而最新的版本信息为:

Kubelet Version: v1.0.3.34+b9a88a7d0e357b

问题原因:

用了CentOS自带光盘作为本地yum源,而删除了CentOS自带的网络yum源的配置文件

解决方法:

使用CentOS自带的网络yum源的配置文件。

 


 

12、kube-apiserver.service启动异常,查看错误日志,发现类似如下报错

Failed to list *api.Namespace: Get http://0.0.0.0:8080/api/v1/namespaces: dial tcp 0.0.0.0:8080: connection refused

Failed to list *api.LimitRange: Get http://0.0.0.0:8080/api/v1/limitranges: dial tcp 0.0.0.0:8080: connection refused

解决办法:

尝试单独多重启etcd试试,直至各个服务都正常。

 


 

13、无法创建任何资源,如发现如下报错

failed to find fit for pod redis-master-1nd8y on node centos-minion01: MatchNodeSelector

解决办法:

检查yaml文件是否包含nodeSelector字段,而这个字段标签是否正确设置。

 

六、附录

附1:解析kube-proxy之iptables

本文出自:http://blog.liuker.cn/index.php/docker/32.html

当创建了service之后,就可以对内/外提供服务。那么其具体是通过什么原理来实现的呢?仔细观察node上的iptables会发现其中的奥妙。

会在nat表里生成4个chain

KUBE-PORTALS-CONTAINER:主要是处理所有service对象的cluster IP和port到kube-proxy本地端口的映射

KUBE-PORTALS-HOST:同上类似,只不过此为针对node本地进程,上条为针对容器进程。

KUBE-NODEPORT-CONTAINER:主要是处理所有service对象的NodePort类型的cluster IP和port到kube-proxy本地端口的映射

KUBE-NODEPORT-HOST:同上类似,只不过此为针对node本地进程,上条为针对容器进程。

 

以service默认的ClusterIP方式为例:

创建service以后,kube-proxy会自动在集群里的node上创建以下两条规则:

 

-A KUBE-PORTALS-CONTAINER -d 10.254.217.168/32 -p tcp -m comment –comment “default/frontend:” -m tcp –dport 80 -j REDIRECT –to-ports 45587

解释:10.254.217.168是kubernetes分配给当前service的全局唯一地址,80为service定义的端口,45587为kube-proxy分配到本机的随机端口。意思是本地容器到10.254.217.168:8080的流量重定向到45587端口

-A KUBE-PORTALS-HOST -d 10.254.217.168/32 -p tcp -m comment –comment “default/frontend:” -m tcp –dport 80 -j DNAT –to-destination 192.168.1.124:45587

解释:本机到10.254.217.168:8080的流量重定向到45587端口

 

如果是NodePort方式,还会额外生成两条:

-A KUBE-NODEPORT-CONTAINER -p tcp -m comment –comment “default/frontend:” -m tcp –dport 30002 -j REDIRECT –to-ports 45587

解释:本地容器访问本地30002端口的流量重定向到45587端口

-A KUBE-NODEPORT-HOST -p tcp -m comment –comment “default/frontend:” -m tcp –dport 30002 -j DNAT –to-destination 192.168.1.124:45587

解释:本地进程访问本地30002端口的流量重定向到45587端口

见下图:

流程解析:(以NodePort为例)

1、外部访问service 192.168.1.124:30002,然后根据iptables的规则,重定向到45587。外部client启动随机端口与45587连接。

tcp6       0      0 192.168.1.124:45587     192.168.1.121:35845     ESTABLISHED 13101/kube-proxy

2、kube-proxy会在本机启动一个随机端口,与service分配的pod完成连接。

tcp        0      0 192.168.1.124:40614     172.18.0.9:80           ESTABLISHED 13101/kube-proxy

 

node相当于一个反向代理的意思

外部client<———>node<———>service(pod)

转载请注明:靠谱运维 » Docker集群管理之Kubernetes

喜欢 (3)or分享 (0)
发表我的评论
取消评论

表情