Kubernete搭建手记(基于1.6和Jimmy的博客)

K8S搭建笔记

Kubernete搭建手记(基于1.6和Jimmy的博客)_第1张图片
目录

一、搭建过程

1.1 总体说明

本文主要记录kubernetesV1.6版本的搭建、并在其中部署一个Nginx和监控台的过程。仅简单介绍kubernetes的部分概念,不作展开,详细内容自行下来了解。主要参考网络上“宋静超”搭建K8S,对其文章中可能混淆的地方加以注解。完整过程请参考他的博客。

在CentOS上部署kubernetes集群
https://jimmysong.io/kubernetes-handbook/practice/install-kubernetes-on-centos.html

1.2虚拟机准备

总共需要3台虚拟机,如下表所示

主机 IP 角色 需要安装的软件
master 192.168.0.241 K8S master节点 docker Flannel etcd apiserver controller-manager scheduler
node1 192.168.0.242 K8S node节点 docker Flannel etcd kubelet kube-proxy
node2 192.168.0.243 K8S node节点 docker Flannel etcd kubelet kube-proxy

节点角色说明

  • master
    Master节点负责对外提供一系列管理集群的API接口,并且通过和 node 节点交互来实现对集群的操作管理
  • node
    node节点为运行 Docker容器的节点,负责和节点上运行的 Docker 进行交互,并且提供了代理功能

公共组件说明

  • docker
    运行在所有节点,容器基础服务
  • flannel
    运行在所有节点,一个专为kubernetes定制的三层网络解决方案,主要用于解决容器的跨主机通信问题
  • etcd
    集群方式运行在所有节点,key-value键值存储数据库,用来存储kubernetes的信息的
  • apiserver
    运行在master节点,用户和 kubernetes 交互的入口,封装了核心对象的增删改查操作,提供了 RESTFul 风格的 API 接口,通过etcd来实现持久化并维护对象的一致性
  • controller-manager
    运行在master节点,主要是用于保证 replication Controller 定义的复制数量和实际运行的 pod 数量一致,另外还保证了从 service 到 pod 的映射关系总是最新的
  • scheduler
    运行在master节点,负责集群资源的调度和管理,例如当有 pod 异常退出需要重新分配机器时,scheduler 通过一定的调度算法从而找到最合适的节点。
  • kubelet
    运行在 node节点,负责和节点上的Docker交互,例如启停容器,监控运行状态等。
  • proxy
    运行在 node节点,负责为 pod 提供代理功能,会定期从 etcd 获取 service 信息,并根据 service 信息通过修改 iptables 来实现流量转发(最初的版本是直接通过程序提供转发功能,效率较低。),将流量转发到要访问的 pod 所在的节点上去。
  • kubectl kube命令行工具
    这是一个运行kube的脚本程序,可以理解为空K8S的cmd脚本工具,是用户和k8s在命令级别微观沟通桥梁

1.3 常规组件安装

1.3.1组件安装顺序

Kubernete搭建手记(基于1.6和Jimmy的博客)_第2张图片
QQ截图20180711230610.png

1.3.2 Docker安装

每台主机都要安装Docker,不建议直接在Centos中使用yum install docker。否则安装的版本比较老
安装docker,下载链接如下所示。目前使用18.03版本。==建议下载rpm包,使用以下方法安装==

https://docs.docker.com/install/linux/docker-ce/centos/
yum install 绝对路径/docker-ce-1803.rpm

1.3.3-A 证书制作

kubernetes 系统的各组件需要使用 TLS 证书对通信进行加密,Jimmy的博客中使用 CloudFlare 的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 和其它证书;关于Kubernetes和证书的关系可以参考书目或者以下链接

《如何理解Kubernetes认证和授权》
这边文章是翻译的官方文档,解释的比较通透,不过只翻译了部分,关于认证和授权的详细信息没有翻译到,链接如下:

《Kubernetes 认证》
这是kubernetes中文社区的文档,介绍的比较全,但是刚看的时候可能有点懵,实际上对于认证和授权,如果没有认识,建议还是跟着jimmy的教程配置一次,再反过来看,可能更容易接受,链接如下:

安装方法:

  1. 建议直接跟随《5.2.1. 创建TLS证书和秘钥》所述方法配置。
  2. CFSSL建议就不用文中的go语言方式安装了,可直接用文中二进制方法安装。
  3. 创建 kubernetes 证书 一节中127.0.0.1和10.254.0.1保留,其余换成自己的主机地址

1.3.3-B kubectl工具

kubectl是k8s集群的命令行工具,其概念可以参考Windows的cmd、Linux上的shell。master节点因为要执行众多命令,肯定是需要安装的。node节点按需安装,即如果有需要在node节点上也要执行创建pod、service等操作,就需要在pod上安装此工具。

安装方法:

  1. 建议直接跟随《5.2.4. 安装kubectl命令行工具》所述方法配置
  2. KUBE_APISERVER配置说明
KUBE_APISERVER="https://172.20.0.113:6443"

KUBE_APISERVER即master所在主机的地址,无论是在node配置kubectl还是master都是安装KUBE_APISERVER的地址(这里暂时未考虑master节点的高可用)。

1.3.4 Etcd集群安装

K8S依赖Etcd作为服务发现等功能,所以需要搭建Etcd组件。Etcd可以搭建单机,也可以搭建集群。目前按照集群方式搭建。在每台主机上安装。
安装方法

  1. Jimmy博客《5.2.3创建高可用 etcd 集群》
  2. 直接按照博客方法安装即可

1.3.5 master节点部署

这部分主要是在master节点上部署APIserver、scheduler和controller
部署安装方法

  1. 可以直接按照《5.2.5. 部署master节点》 部分内容直接部署
  2. 针对博客的补充说明
  • kubernetes-server-linux-amd64.tar.gz 这个文件较大,wget如果失败,建议直接下载手工上传到主机
  • 每个组件安装完成后,建议验证一下功能再向前。

1.3.6 node节点部署

这部分主要是在node节点上部署kube和kube-proxy
部署安装方法

  1. 可以直接按照《5.2.7. 部署node节点》 部分内容直接部署
  2. 针对博客的补充说明
  • Jimmy的博客在本节开篇讲解了flannel接手docker网络的配置,这部分的参照作者的配置,并未达到目的————也即在后续使用代理访问dashboard时候,提示没有到node-docker地址的路由,这部分解决方法,放到了二、问题集2.3代理方式无法访问dashboard说明,请移步该节查看解决方案。
  • /etc/kubernetes/kubelet 关于配置文件的问题,请直接看注释(针对192.168.0.242)
##我的注释:KUBELET_ADDRESS这个配置,参看网络很多配置这里都写的是0.0.0.0 或者"",所以我这里也留了空没有写。不妨碍成功启动。
## The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
##原文配置KUBELET_ADDRESS="--address=172.20.0.113"
KUBELET_ADDRESS=""
#
## The port for the info server to serve on
#KUBELET_PORT="--port=10250"
#
##我的注释:这里如果要覆盖,请直接写正在配置的node的地址,原文给人造成歧义,写的是master的地址。
## You may leave this blank to use the actual hostname
##原文配置KUBELET_HOSTNAME="--hostname-override=172.20.0.113"
KUBELET_HOSTNAME="--hostname-override=192.168.0.242"
#
## location of the api-server
## COMMENT THIS ON KUBERNETES 1.8+
KUBELET_API_SERVER="--api-servers=http://192.168.0.241:8080"
#
##我的注释:如果没有私有仓库,请直接保留为"""即可
## pod infrastructure container
##原文配置KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=harbor-001.jimmysong.io/library/pod-infrastructure:rhel7"
#
## Add your own!
KUBELET_ARGS="--cgroup-driver=systemd --cluster-dns=10.254.0.2 --experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig --kubeconfig=/etc/kubernetes/kubelet.kubeconfig --require-kubeconfig --cert-dir=/etc/kubernetes/ssl --cluster-domain=cluster.local --hairpin-mode promiscuous-bridge --serialize-image-pulls=false"
  • 代理配置文件问题(针对192.168.0.242)
###
# kubernetes proxy config

# default config should be adequate

# Add your own!
##我的配置,bind-address也是正在配置的node的地址,hostname-override和上面kubelet的配置需要一直
##原文配置KUBE_PROXY_ARGS="--bind-address=172.20.0.113 --hostname-override=172.20.0.113 --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig --cluster-cidr=10.254.0.0/16"
KUBE_PROXY_ARGS="--bind-address=192.168.0.242 --hostname-override=192.168.0.242 --kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig --cluster-cidr=10.254.0.0/16"

1.3.7 Flannel网络插件安装

默认情况,docker安装后,使用的是bridge桥接在宿主机上,意味着在不同主机上的docker通信设置复杂。所以诞生了第三方插件,帮助docker内的容器通信。flannel就是这样的组件。他是一个专为kubernetes定制的三层网络解决方案,主要用于解决容器的跨主机通信问题。
安装方法

  1. 参照《5.2.6. 安装flannel网络插件》
  2. 对博客配置方法的说明
  • flannel的配置文件:/etc/sysconfig/flanneld的==FLANNEL_ETCD_PREFIX==配置要和后面的==etcdctl命令中的键值==对应;
  • 代码段【2】中的命令,其实很简单 即 etcdctl mkdir /kube-centos/network;相当于使用etcdctl命令行创建了一个目录(键值对);
  • 上面这段命令,如果配置错误,是不能覆盖的,需要使用 etcdctl rmdir [目录]先删除,然后再重建即可。
  • 而代码中 --ca-file等代码块主要是认证用的
代码段【1】
# etcd config key.  This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/kube-centos/network"
代码段【2】
etcdctl --endpoints=https://172.20.0.113:2379,https://172.20.0.114:2379,https://172.20.0.115:2379 \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/kubernetes/ssl/kubernetes.pem \
  --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \
  mkdir /kube-centos/network
etcdctl --endpoints=https://172.20.0.113:2379,https://172.20.0.114:2379,https://172.20.0.115:2379 \
  --ca-file=/etc/kubernetes/ssl/ca.pem \
  --cert-file=/etc/kubernetes/ssl/kubernetes.pem \
  --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \
  mk /kube-centos/network/config '{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}'

二、部署项目

2.1项目部署概论

在纯docker中,我们通过docker run直接启动一个应用。

那么,K8S中,我们通过YAML文件来告诉集群应该怎么创建应用,这些内容描述了启动应用的images(以及下载地址)、需要创建的应用的数、应用类型、应用意外终止后的处理方式等。典型的一个hello-world.yaml文件如下所示:

apiVersion: v1
  kind: Pod
  metadata:
    name: hello-world
 spec: # specification of the pod’s contents
   restartPolicy: Never
   containers:
   - name: hello
 image: "ubuntu:14.04"
 command: ["/bin/echo","hello”,”world"]

以上内容是启动一个Ubuntu:14.04,容器名hello-world,然后启动后执行 /bin/echo hello world .
然后使用 以下命令创建 Pods:kubectl create -f ./hello-world.yaml
然后查看Pod状态

## 我的注释:初始化的时候,新创建的pod还未被调度,也就是还没有节点被选中去运行它。
$ kubectl get pods
NAME         READY  STATUS    RESTARTS   AGE
hello-world  0/1    Pending   0          0s
## 我的注释:这个是已经成功运行的状态
$ kubectl get pods
NAME            READY  STATUS    RESTARTS  AGE
hello-world   1/1       Running  0        s

2.2部署nginx

2.1.1创建nginx-rc.yaml和nginx-svc.yaml

#nginx-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-test
  labels:
    name: nginx-test
spec:
  replicas: 2
  selector:
    name: nginx-test
  template:
    metadata:
      labels: 
       name: nginx-test
    spec:
      containers:
      - name: nginx-test
        image: docker.io/nginx
        ports:
        - containerPort: 80

#nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-test
  labels: 
   name: nginx-test
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    name: http
    nodePort: 30088
  selector:
name: nginx-test

以上命令是创建一组nginx服务器,创建2个副本,将80端口映射到nodePort:30088

然后运行下面两条命令创建pod
kubectl create -f ./nginx-rc.yaml
kubectl create -f ./nginx-svc.yaml

2.1.2创建过程中可能出现的问题

A、Kubernetes在创建Pod的时候,需要从gcr.io下载一个helper镜像,这个镜像在Google下面,国内无法拉取可参考3.1解决。gcr.io镜像的实际拉取实际上在node上,也就是需要在node机器上的docker要有这个镜像,所以不能只在master操作。
B、 过了gcr.io这个坎后,有可能要拉取的nginx镜像也拉不出而一直处于creating状态。这部分排查需要不断查看系统日志和 tail -f /var/log/messages 以及kubectl describe pod nginx-controller-tr5zr 查看pod状态。如果日志显示是拉不到镜像需要检查yaml里面的images是否是可拉取的,如果可以通过docker run [images]可拉取,那么yaml应该也是可以的。如果拉取时间过慢,可以通过添加加速器等方式加速;

2.2部署dashboard

2.2.1部署方法

可以参照博客直接部署K8S的dashboard,需要注意的是要自己去找可用的1.6版本的dashboard镜像,可通过hub.docker.com搜索,然后使用加速器拉下来。

2.2.2部署问题

如遇到dashboard不可访问,路由问题,可参照下文3.3解决。

三、问题集

3.1 kubectl pod 一致处于ContainerCreating状态

3.1.1故障现象

[root@localhost nginx]# kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-controller-tr5zr   1/1       ContainerCreating 0          47s
nginx-controller-z3cbw   1/1       ContainerCreating 0          47s

3.1.2排查:查看具体pod状态

kubectl describe pod nginx-controller-tr5zr
unable to pull sandbox image \"gcr.io/google_containers/pause-amd64:3.0\": Error response from daemon: {\"message\":\"Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\"}

3.1.3确认问题

无法拉取 gcr.io/google_containers/pause-amd64:3.0 镜像

3.1.4解决方案:手动拉取、然后本地打tag.在每个POD(node)都执行此操作

[root@localhost ~]# docker pull cloudnil/pause-amd64:3.0
[root@localhost ~]# docker tag cloudnil/pause-amd64:3.0     gcr.io/google_containers/pause-amd64:3.0
[root@localhost ~]# docker  images
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
gcr.io/google_containers/pause-amd64   3.0                 66c684b679d2        12 months ago       747kB
cloudnil/pause-amd64                   3.0                 66c684b679d2        12 months ago       747kB

3.2 可以查看到csr,但是查看node为no resource

3.2.1现象

fannel、etcd 工作正常,但是就是看不到nodes(即get nodes为空)

[root@localhost nginx]# kubectl get csr
NAME        AGE       REQUESTOR           CONDITION
csr-j4gbr   15h       kubelet-bootstrap   Approved,Issued
csr-mm575   15h       kubelet-bootstrap   Approved,Issued
[root@localhost nginx]# kubectl get nodes
NAME            STATUS    AGE       VERSION
192.168.0.242   Ready     14h       v1.6.0
192.168.0.243   Ready     14h       v1.6.0

3.2.2排查 :需要查看系统日志

[root@localhost nginx]#  tail -300f /var/log/messages

3.2.3确认问题:

没有关联角色,kubelet 启动时向 kube-apiserver 发送 TLS bootstrapping 请求,需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予 system:node-bootstrapper 角色,然后 kubelet 才有权限创建认证请求(certificatesigningrequests):

3.2.4解决方案:在master执行以下语句 关联角色

kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

3.3 代理方式无法访问dashboard

3.3.1 现象

dashboard部署成功后,开启kube-proxy代理访问控制台,显示路由不通

[root@localhost ~]# kubectl proxy --address='192.168.0.241' --port=8086 --accept-hosts='^*$'
Starting to serve on 192.168.0.241:8086

访问http://masterip:8086/ui后显示如下:

dial tcp 172.17.0.3:9090: getsockopt: no route to host'

然后可跟踪到pod去,发现某pod如果docker是172.17.0.3可以通过此主机访问

Kubernete搭建手记(基于1.6和Jimmy的博客)_第3张图片
只能在某一node中使用内部地址访问控制台

3.3.2 排查-确定网络问题

经查考虑是docker网络问题

根据以下两篇文章及fannel网络原理

https://www.cnblogs.com/kevingrace/p/6859114.html
https://blog.csdn.net/yelllowcong/article/details/78303626

Kubernete搭建手记(基于1.6和Jimmy的博客)_第4张图片
Flannel网络结构

可知,网络转发通过fannel进行,正确安装fannel并且配置Docker后。docker0和fannel.1会是同一个网段,数据包到达fannel所在的网络的之后,也即到了docker。从而完成了数据的转发。

而最开始,我的网络路由不对

[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.0.1     0.0.0.0         UG    0      0        0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.30.0.0      0.0.0.0         255.255.0.0     U     0      0        0 flannel.1
192.168.0.0     0.0.0.0         255.255.248.0   U     0      0        0 ens33
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0

注意docker0的网段和flannel的网段不在同一个上面,所以是docker和flanned没有对接起来。

3.3.3解决方案:配置docker

情况一:根据上面第二个文章,配置docker的网络跟随flannel配置,如下文最后一行所示;

EnvironmentFile=-/run/flannel/docker
ExecStart=/usr/bin/dockerd \
         $DOCKER_NETWORK_OPTIONS

情况二:博客中说的配置docker网络的Environment要放在情况一那部分代码的前面,否则不生效

      
EnvironmentFile=-/run/flannel/docker
EnvironmentFile=-/run/docker_opts.env
EnvironmentFile=-/run/flannel/subnet.env
EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
EnvironmentFile=-/etc/sysconfig/docker-network
EnvironmentFile=-/run/docker_opts.env

即:这部分代码要放在
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS的前面

3.3.4最终确认

flannel.1和docker0 在同一网段了

[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.0.1     0.0.0.0         UG    0      0        0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 ens33
172.30.0.0      0.0.0.0         255.255.0.0     U     0      0        0 flannel.1
172.30.98.0     0.0.0.0         255.255.255.0   U     0      0        0 docker0
192.168.0.0     0.0.0.0         255.255.248.0   U     0      0        0 ens33
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0

你可能感兴趣的:(Kubernete搭建手记(基于1.6和Jimmy的博客))