【Linux】【Services】【SaaS】Docker+kubernetes(8. 安装和配置Kubernetes)

1. 概念

1.1. 比较主流的任务编排系统有mesos+marathon,swarm,openshift(红帽内部叫atom服务器)和最著名的kubernetes,居然说yarn也行,不过没见过谁用

1.2. 官方网站 https://kubernetes.io/(需要科学上网)

1.3. 软件架构图

1.4. 每个组件的作用:https://kubernetes.io/docs/concepts/overview/components/

Master Components:主节点组件提供集群的控制功能。他从整体的角度去决定集群应该怎么运行(例如计划任务),并且探测和回应集群的要求(当一个复制节点的“复制请求”失败的时候,他会去启动一个新的pod)
主节点组建可以运行在集群中的任意一台机器。但是,简单来说,创建脚本只能在一台机器上启动所有的主要组件,但是不能在这台机器上启动用户容器。

  kube-apiserver:运行在主节点上,用来暴露Kubernetes接口的组建。他在Kubernetes控制面板的前端。他被用来设计成水平扩展,这就是说,他可以扩展成更多的实例。

  etcd:一致性和高可用键值存储,用来作为kubernetes集群的后端存储,为你的kubernetes集群准备一个备份计划,用来备份etcd的数据。

  kube-scheduler:主节点上的组件,用来观察新创建的,还没有被分配节点的pods,为他们选择一个节点并运行他们。

  这需要考虑到个人计划和整体资源的需求,硬件/软件/策略约束,松耦合和解耦,数据本地化,内部负载均衡和结束时间等因素


  kube-controller-manager:在主节点上用来运行控制器的。逻辑上来说,每个控制器都是一个独立的进程,但是为了减少复杂性,他们都被编译进了一个二进制文件并且以独立的进程来运行。

    Node Controller: 用来通知和响应哪个节点挂掉了
    Replication Controller: 为每个副本控制对象服务,负责维护正确的pods数量
    Endpoints Controller: 寄宿在终端对象,例如加入service以及pods
    Service Account & Token Controllers: 为新的用户空间创建默认用户和接口访问令牌

  cloud-controller-manager:云控制器作用在云服务的底层。云控制器在kubernetes1.6中是一个测试版本。云控制器只能跑在特定云服务控制器循环上。
  我们可以在 kube-controller-manager.禁止这些控制的循环。我们可以通过在启动 kube-controller-manager设置--cloud-provider选项来关闭它
  云控制器允许云供应商二次开发,并且kubernetes核心可以发展成为彼此独立的版本。
  在早期的版本,kubernetes核心代码是依赖于cloud-provider-specific的,在未来的版本,特定的为云供应商提供的服务的代码应该都有云供应商自己服务,并且在运行kubernetes的时候连接到cloud-controller-manager

  以下的控制器有独立的云提供者
    Node Controller: 查询云服务提供者,决定一个节点是否停止响应之后是否还能够被检测到
    Route Controller: 在云架构的底层建立起路由
    Service Controller: 建立,升级和删除云服务提供者的负载均衡
    Volume Controller: 创建,附加和挂载卷组,并且和云服务提供者交互去编排卷组

Node Components:节点组建需要在每个节点上运行,维护工作中的pod并且提供Kubernetes的运行环境

  kubelet:在集群上的每个节点都要运行。他能保证每个pod上都有一个container运行,kubelet接管各种机器提供的PodSpecs并且确保这些在PodSpecs中注册的容器健康运行。kubelet不负责那些不是Kubernetes创建的容器

  kube-proxy:kube-proxy保证宿主机Kubernetes服务被网络规则抽象管理并且实行连接转发

  Container Runtime:运行时容器是负责运行中的容器。kubernetes支持多种运行时容器:Docker,rkt(CoreOS),runc和任何符合OCI(Open Container Initiative)运行时标准的容器

Addons:其他插件是实现集群功能的pods和services。pods可能被部署,副本管理器等组件管理。名称空间插件在kube-system名称空间被创建

  DNS:其他的插件都不是严格需要的,但是所有kubenetes集群都必须拥有一个集群的DNS,因为集群非常依赖他
  集群DNS是一个dns服务器,作为您其他DNS服务器中的附加服务器,为kubernetes服务器提供DNS记录
  containers是由kubenetes搜索DNS之后自动启动的,包括这个DNS服务

  Web UI (Dashboard):Dashboard是一个统一管理,为了kubernets集群而准备的网络界面,他运行用户对集群的应用管理和排错,就好像在操作集群一样

  Container Resource Monitoring:容器资源监控继续在中心数据库记录创建容器的时间序列,并且提供UI以供浏览这些数据

  Cluster-level Logging:集群级别的日志机制是负责保存容器日志的,他可以集中存储日志,并提供搜索和浏览的接口

1.5.  Policy Layer: API Server:

API server是一个策略组件,提供对Etcd的过滤访问。它的作用本质上是相对通用的,目前正在被分解处理。因此,API Server也可以用于其他系统的控制平面。

API server的主要货物是资源,通过暴露简单的REST API 向外提供服务。这些资源有一个标准结构可以实现一些扩展功能。无论如何,API Server,允许各类组件创建,读取,写入,更新,和监视资源。
API  Server的具体的功能:
  •认证和授权。Kubernetes有一个可插拔的认证系统。有一些内置的用户认证机制和授权这些用户访问资源。此外,还有一些方法可用于向外部服务提供这些服务。这种可扩展性是Kubernetes构建的核心功能。
  •API Server运行一组可以拒绝或修改请求的准入控制器。 这些允许策略被应用并设置默认值。 这是确保在API Server客户端仍在等待请求确认时进入系统的数据有效性的关键。 虽然这些准入控制器目前正在编译到API Server中,但目前正在进行的工作是使其成为另一种可扩展性机制。
  •API Server 有助于API 版本控制。API 版本的一个关键问题是允许资源的字段的改变,字段添加,弃用,重新组织和以其他方式转换。 API Server在Etcd中存储资源的"true"表示,并根据满足的API版本转换/呈现该资源。 自项目早期开始,规划版本控制和API的发展一直是Kubernetes的一项重要工作。
  •API Server 一个重要特性是支持watch机制。这意味着API Server的客户端可以使用与Etcd相同的协调模式。Kubernetes中的大多数协调包括写入另一个组件正在监视的API服务器资源的组件。 第二个组件将对几乎立即发生的变化做出反应。

1.6. 业务逻辑:Controller Manager and Scheduler

这些是通过API Server 进行协调的组件。这些称为Controller Manager和Scheduler的组件绑定到单独的服务器Master上
Scheduler组件将做许多事情让系统工作:
  1.查找未分配给节点的Pod(未绑定的Pod);
  2.检查集群的状态(缓存在内存中);
  3.选择具有空闲空间并满足其他约束条件的节点;
  4.将pod绑定到该节点。
Controller Manager 组件,实现ReplicaSet的行为。(ReplicaSet可以确保任何时候都可以运行一个Pod模板的副本数量)。控制器将根据资源中的选择器 监控ReplicaSet 资源和一组Pod。为了保持在ReplicaSet中稳定的一组Pod,控制器将创建、销毁Pod。

1.7. 一次请求:

这个时序图展示了创建pod的流程,基本的流程如下:
  1. 用户提交创建Pod的请求,可以通过API Server的REST API ,也可用Kubectl命令行工具,支持Json和Yaml两种格式;
  2. API Server 处理用户请求,存储Pod数据到Etcd;
  3. Schedule通过和 API Server的watch机制,查看到新的pod,尝试为Pod绑定Node;
  4. 过滤主机:调度器用一组规则过滤掉不符合要求的主机,比如Pod指定了所需要的资源,那么就要过滤掉资源不够的主机;
  5. 主机打分:对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等;
  6. 选择主机:选择打分最高的主机,进行binding操作,结果存储到Etcd中;

  7.      kubelet根据调度结果执行Pod创建操作: 绑定成功后,会启动container, docker run, scheduler会调用API Server的API在etcd中创建一个bound pod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步bound pod信息,一旦发现应该在该工作节点上运行的bound pod对象没有更新,则调用Docker API创建并启动pod内的容器。

2. 环境

2.1. Kubernetes:1.5.2

3. 安装与配置:参考文章:http://www.cnblogs.com/breezey/p/6545307.html

3.1. 在所有节点上都安装docker

yum install docker

3.2. 配置docker信任我们前面做的仓库,修改/usr/lib/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=network.target
Wants=docker-storage-setup.service
Requires=rhel-push-plugin.socket registries.service
Requires=docker-cleanup.timer

[Service]
Type=notify
NotifyAccess=all
EnvironmentFile=-/run/containers/registries.conf
EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
EnvironmentFile=-/etc/sysconfig/docker-network
Environment=GOTRACEBACK=crash
Environment=DOCKER_HTTP_HOST_COMPAT=1
Environment=PATH=/usr/libexec/docker:/usr/bin:/usr/sbin
ExecStart=/usr/bin/dockerd-current 
          --insecure-registry hctjosadm01.hccos.cn:5000
          --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current 
          --default-runtime=docker-runc 
          --authorization-plugin=rhel-push-plugin 
          --exec-opt native.cgroupdriver=systemd 
          --userland-proxy-path=/usr/libexec/docker/docker-proxy-current 
          $OPTIONS 
          $DOCKER_STORAGE_OPTIONS 
          $DOCKER_NETWORK_OPTIONS 
          $ADD_REGISTRY 
          $BLOCK_REGISTRY 
          $INSECURE_REGISTRY
      $REGISTRIES
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0
Restart=on-abnormal
MountFlags=slave
KillMode=process

[Install]
WantedBy=multi-user.target

3.3. 设置服务随机启动

systemctl daemon-reload && systemctl enable docker && systemctl start docker

3.4. 在master节点上安装kuber master

yum install -y kubernetes-master kubernetes-client

3.5. 在master节点上修改配置文件 /etc/kubernetes/config

###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
#   kube-apiserver.service
#   kube-controller-manager.service
#   kube-scheduler.service
#   kubelet.service
#   kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"

# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"

# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"

# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://172.16.0.90:8080"

3.6. 记得创建一个key文件,要不在创建pod的时候会报错

openssl genrsa -out /etc/kubernetes/serviceaccount.key 2048

3.7. 在master节点上修改配置文件 /etc/kubernetes/apiserver

###
# kubernetes system config
#
# The following values are used to configure the kube-apiserver
#

# The address on the local server to listen to.
#KUBE_API_ADDRESS="--insecure-bind-address=127.0.0.1"
KUBE_API_ADDRESS="--address=0.0.0.0"

# The port on the local server to listen on.
# KUBE_API_PORT="--port=8080"
KUBE_API_PORT="--port=8080 --secure-port=443"
KUBE_MASTER="--master=http://172.16.0.90:8080"

# Port minions listen on
# KUBELET_PORT="--kubelet-port=10250"
KUBELET_PORT="--kubelet-port=10250"

# Comma separated list of nodes in the etcd cluster
#KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379"
KUBE_ETCD_SERVERS="--etcd-servers=http://172.16.0.83:2379,http://172.16.0.84:2379,http://172.16.0.85:2379"

# Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"

# default admission control policies
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"

# Add your own!
#KUBE_API_ARGS="--service_account_key_file=/etc/kubernetes/serviceaccount.key"

3.8. 修改/etc/kubernetes/controller-manager

###
# The following values are used to configure the kubernetes controller-manager

# defaults from config and apiserver should be adequate

# Add your own!
KUBE_CONTROLLER_MANAGER_ARGS="--service_account_private_key_file=/etc/kubernetes/serviceaccount.key"

3.9. 启动master上的服务

systemctl start kube-apiserver kube-controller-manager kube-scheduler
systemctl enable kube-apiserver kube-controller-manager kube-scheduler

3.10. 在所有node节点上安装服务

yum install -y kubernetes-node

3.11. 修改node上的配置文件 /etc/kubernetes/config

###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
#   kube-apiserver.service
#   kube-controller-manager.service
#   kube-scheduler.service
#   kubelet.service
#   kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"

# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"

# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"

# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://172.16.0.90:8080"

3.12. 修改node节点上的配置文件/etc/kubernetes/kubelet

###
# kubernetes kubelet (minion) config

# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
#KUBELET_ADDRESS="--address=127.0.0.1"
KUBELET_ADDRESS="--address=0.0.0.0"

# The port for the info server to serve on
# KUBELET_PORT="--port=10250"

# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=hctjosk8snode01"

# location of the api-server
KUBELET_API_SERVER="--api-servers=http://172.16.0.90:8080"

# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"

# Add your own!
KUBELET_ARGS=""

3.13. 启动node节点上的服务

systemctl start kubelet kube-proxy
systemctl enable kubelet kube-proxy

3.14. 在主节点上查看集群状态

~]# kubectl get nodes
NAME              STATUS    AGE
hctjosk8snode01   Ready     1h
hctjosk8snode02   Ready     18s
hctjosk8snode03   Ready     15s
hctjosk8snode04   Ready     11s

 3.15. 在所有node节点上吧flannel安装上

yum install flannel

3.16. 在etcd服务器上(10.30.2.83/84/85任意一台即可),增加一条记录

etcdctl set /hccos.cn/network/config '{"network": "172.17.0.0/16"}'

3.17. 修改flannel配置文件 /etc/sysconfig/flanneld

# Flanneld configuration options  

# etcd url location.  Point this to the server where etcd runs
FLANNEL_ETCD_ENDPOINTS="http://172.16.0.83:2379,http://172.16.0.84:2379,http://172.16.0.85:2379"

# etcd config key.  This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/hccos.cn/network"

# Any additional options that you want to pass
#FLANNEL_OPTIONS=""

3.18. 启动服务

systemctl start flanneld
systemctl enable flanneld

3.19. 由于docker依赖于flanneld,需要重启docker服务

systemctl restart docker

4. YAML文件示例

#test-pod
apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中  
kind: Pod #指定创建资源的角色/类型  
metadata: #资源的元数据/属性  
  name: test-pod #资源的名字,在同一个namespace中必须唯一  
  labels: #设定资源的标签
    k8s-app: apache  
    version: v1  
    kubernetes.io/cluster-service: "true"  
  annotations:            #自定义注解列表  
    - name: String        #自定义注解名字  
spec: #specification of the resource content 指定该资源的内容  
  restartPolicy: Always #表明该容器一直运行,默认k8s的策略,在此容器退出后,会立即创建一个相同的容器  
  nodeSelector:     #节点选择,先给主机打标签kubectl label nodes kube-node1 zone=node1  
    zone: node1  
  containers:  
  - name: test-pod #容器的名字  
    image: 10.192.21.18:5000/test/chat:latest #容器使用的镜像地址  
    imagePullPolicy: Never #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registery)images的策略,
                           # Always,每次都检查
                           # Never,每次都不检查(不管本地是否有)
                           # IfNotPresent,如果本地有就不检查,如果没有就拉取
    command: ['sh'] #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT  
    args: ["$(str)"] #启动容器的命令参数,对应Dockerfile中CMD参数  
    env: #指定容器中的环境变量  
    - name: str #变量的名字  
      value: "/etc/run.sh" #变量的值  
    resources: #资源管理
      requests: #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行  
        cpu: 0.1 #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m)
        memory: 32Mi #内存使用量  
      limits: #资源限制  
        cpu: 0.5  
        memory: 1000Mi  
    ports:  
    - containerPort: 80 #容器开发对外的端口
      name: httpd  #名称
      protocol: TCP  
    livenessProbe: #pod内容器健康检查的设置
      httpGet: #通过httpget检查健康,返回200-399之间,则认为容器正常  
        path: / #URI地址  
        port: 80  
        #host: 127.0.0.1 #主机地址  
        scheme: HTTP  
      initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始  
      timeoutSeconds: 5 #检测的超时时间  
      periodSeconds: 15  #检查间隔时间  
      #也可以用这种方法  
      #exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常  
      #  command:  
      #    - cat  
      #    - /tmp/health  
      #也可以用这种方法  
      #tcpSocket: //通过tcpSocket检查健康   
      #  port: number   
    lifecycle: #生命周期管理  
      postStart: #容器运行之前运行的任务  
        exec:  
          command:  
            - 'sh'  
            - 'yum upgrade -y'  
      preStop:#容器关闭之前运行的任务  
        exec:  
          command: ['service httpd stop']  
    volumeMounts:  #挂载持久存储卷
    - name: volume #挂载设备的名字,与volumes[*].name 需要对应    
      mountPath: /data #挂载到容器的某个路径下  
      readOnly: True  
  volumes: #定义一组挂载设备  
  - name: volume #定义一个挂载设备的名字  
    #meptyDir: {}  
    hostPath:  
      path: /opt #挂载设备类型为hostPath,路径为宿主机下的/opt,这里设备类型支持很多种
    #nfs
原文地址:https://www.cnblogs.com/demonzk/p/8301087.html