kubernetes

kubernetes

Kubernetes简介

文档

  • https://kubernetes.io/zh-cn/docs/home/
  • https://kubernetes.io/docs/home/

介绍

  • Kubernetes是自动化容器操作的开源平台,这些操作包括部署、调度和节点集群间扩展
  • Borg是谷歌内部使用的大规模集群管理系统,基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。Kubernetes是Google Omega的开源版本

功能

  • 自动化容器的部署和复制
  • 随时扩展或收缩容器规模
  • 将容器组织成组,并且提供容器间的负载均衡
  • 很容易地升级应用程序容器的新版本
  • 提供容器弹性,如果容器失效就替换它,等等…

解决的问题

  • 调度 - 容器应该在哪个机器上运行
  • 生命周期和健康状况 - 容器在无错的条件下运行
  • 服务发现 - 容器在哪,怎样与它通信
  • 监控 - 容器是否运行正常
  • 认证 - 谁能访问容器
  • 容器聚合 - 如何将多个容器合并成一个工程

组件组成

  • kubectl

    • 客户端命令行工具,将接受的命令格式化后发送给kube-apiserver,作为整个系统的操作入口
  • kube-apiserver

    • 作为整个系统的控制入口,以REST API服务提供接口,提供认证、授权、访问控制、API 注册和发现等机制
  • kube-controller-manager

    • 用来执行整个系统中的后台任务,包括节点状态状况、Pod个数、Pods和Service的关联等
  • kube-scheduler

    • 负责节点资源管理,接受来自kube-apiserver的创建Pods任务,并分配到某个节点
  • kube-proxy

    • 运行在每个计算节点上,负责Pod网络代理。定时从etcd获取到service信息来做相应的策略
  • kubelet

    • 运行在每个计算节点上,作为agent,接受分配该节点的Pods任务及管理容器,周期性获取容器状态,反馈给kube-apiserver
  • etcd

    • 负责节点间的服务发现和配置共享,保存了整个集群的状态
  • 网络组件

    • flannel
  • DNS

    • 可选服务,用于为每个Service对象创建DNS记录,这样所有的Pod就可以通过DNS访问服务了

核心概念

集群

  • 集群是一组节点,这些节点可以是物理服务器或者虚拟机,之上安装了Kubernetes平台

  • Kubernetes简化架构图

Master

  • 集群控制节点,负责整个集群的管理和控制。基本上所有控制命令都是在master上运行

  • master通常会占据一个独立的服务器(高可用部署建议用3台服务器)

  • 运行的关键进程

    • kube-apiserver

      • 提供了Http Rest接口的关键服务进程,是 Kubernetes里所有资源的增、删、改、查等操作的唯一入口,是集群控制的入口进程
    • kube-controller-manager

      • Kubernetes里所有资源对象的自动化控制中心
    • kube-scheduler

      • 负责资源调度(Pod调度)的进程
  • etcd

    • etcd是一个高可用的键值存储系统,kubernetes使用它来存储各个资源的状态,从而实现了Restful的API
  • kubectl

    • kubernetes提供的客户端工具,该工具内部是对kubernetes API的调用,是直接和apiserver交互的

Node

  • Kubernetes集群中除了master的其他机器被称为Node,在较早的版本中也被称为Minion

  • Node是Kubernetes集群中的工作负载节点,每个Node都会被Master分配一些工作负载(Docker容器),当某个Node宕机时,其上的工作负载会被Master自动转移到其他节点上

  • 运行的关键进程

    • kubelet

      • 负责Pod对应的容器的创建、启停等任务,同时与Master密切协作,实现集群管理的基本功能
    • kube-proxy

      • 实现Kubernetes Service的通信与负载均衡机制的重要组件
    • Docker Engine(docker)

      • Docker引擎, 负责本机的容器创建和管理工作
  • Node可以在运行期间动态增加到Kubernetes集群中, 前提是在这个节点上已经正确安装、配置和启动了上述关键进程

  • 默认情况下kubelet会向Master注册自己,这也是Kubernetes推荐的Node管理方式

  • 一旦Node被纳入集群管理范围, kubelet进程就会定时向Master汇报自身的情报(操作系统、 Docker版本、机器的CPU和内存情况,以及当前有哪些Pod在运行等)

  • 这样 Master就可以获知每个Node的资源使用情况,并实现高效均衡的资源调度策略

  • 当某个Node在超过指定时间不上报信息时,会被Master判定为“失联”, Node的状态被标记为不可用( Not Ready)。随后Master会触发“工作负载大转移”的自动流程

Pod

  • Pod包含一组紧密相关的容器,每个Pod中都运行着一个特殊的Pause容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和Volume挂载卷,实现localhost通信和文件共享。Pod是短暂的,不是持续性实体

  • 怎么持久化容器数据

    • Kubernetes支持卷的概念,因此可以使用持久化的卷类型
  • 创建同一个容器的多份拷贝

    • 可以手动创建单个Pod,也可以使用Replication Controller使用Pod模板创建出多份拷贝
  • 怎么从前端容器正确可靠地指向后台容器

    • 使用Service

Lable

  • 一个Label是attach到Pod的一对键/值对,用来传递用户定义的属性,可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象

  • 常用Labe

    • 版本标签

      • “release”:“stable”,“release”:“canary”…
    • 环境标签

      • “environment”:“dev”,“environment”:“qa”,“environment”:“production”
    • 架构标签

      • “tier”:“frontend”,“tier”:“backend”,“tier”:“middleware”
    • 分区标签

      • “partition”:“customerA”,“partition”:“customerB”
    • 质量管控标签

      • “track”:“daily”,“track”:“weekly”

Replication Controller

  • Replication Controller确保任意时间都有指定数量的Pod"副本"在运行

  • 如果为某个Pod创建了Replication Controller并且指定3个副本,它会创建3个Pod,并且持续监控它们

  • 某个pod不响应就替换掉,恢复了就干掉一个,运行过程中总数发生变化,则相应地启动或终止差额数量的pod

  • 创建Replication Controller时需指定Pod副本模板和要监控的Label标签

  • pod副本上如何负载均衡

    • Service

Deployment

  • 通过在Deployment中描述所期望的集群状态,Deployment Controller会将现在的集群状态在一个可控的速度下逐步更新成所期望的集群状态

  • 在某种程度上,Deployment可以实现无人值守的上线,大大降低上线过程的复杂沟通、操作风险

  • 功能

    • RC全部功能

      • Deployment继承了RC全部功能
    • 事件和状态查看

      • 可以查看Deployment的升级详细进度和状态
    • 回滚

      • 回滚到上一个稳定的版本或者指定的版本
    • 版本记录

      • 每次对Deployment的操作,都能保存下来,给予后续可能的回滚使用
    • 暂停和启动

      • 对于每一次升级,都能够随时暂停和启动
    • 多种升级方案

      • Recreate

        • 删除所有已存在的pod,重新创建新的
      • RollingUpdate

        • 滚动升级,逐步替换的策略,同时滚动升级时,支持更多的附加参数,例如设置最大不可用pod数量,最小升级间隔时间等等
  • 比RC优势

    • RC只支持基于等式的selector(env=dev或environment!=qa),但RS还支持新的,基于集合的selector(version in (v1.0, v2.0)或env notin (dev, qa))
    • 使用Deployment升级Pod,只需要定义Pod的最终状态,K8S会自动执行。命令kubectl rolling-update需要客户端与服务端多次交互控制RC来完成的
    • Deployment拥有更加灵活强大的升级、回滚功能
  • 工作流程图

Service

  • Service是定义一系列Pod以及访问这些Pod的策略的一层抽象概念。Service通过Label找到Pod组

  • 通信

    • 假定有2个后台Pod,后台Service的名称为’backend-service’,lable选择器为(tier=backend, app=myapp)
    • Service会创建一个本地集群的DNS入口,因此前端Pod只需要DNS查找主机名为 ‘backend-service’,就能够解析出前端应用程序可用的IP地址
    • Service在这2个后台Pod之间提供透明的负载均衡,会将请求分发给其中的任意一个。通过每个Node上运行的代理(kube-proxy)完成
  • LoadBalancer

    • 特别类型的Kubernetes Service,作为外部负载均衡器使用,在一定数量的Pod之间均衡流量
  • 访问Service

    • Node IP

      • Kubernetes集群中节点的物理网卡IP地址,集群之外的节点访问必须通过Node IP进行通信
    • Pod IP

      • 每个Pod的IP地址,Docker Engine根据docker0网桥的IP地址段进行分配的
    • Cluster IP

      • 仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址
      • 虚拟IP,无法被ping,他没有一个"实体网络对象"来响应
      • 只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并且他们属于Kubernetes集群这样一个封闭的空间
    • Kubernetes集群之内,Node IP网、Pod IP网与Cluster IP网之间的通信,采用的是Kubernetes自己设计的一种编程方式的特殊路由规则

架构和组件

  • 架构

  • Kubernetes Master

    • 控制组件,调度管理整个系统(集群)

    • Kubernetes API Server

      • Kubernetes系统的入口,封装了核心对象的增删改查操作,以RESTful API接口方式提供给外部客户和内部组件调用。维护的REST对象持久化到Etcd中存储
    • Kubernetes Scheduler

      • 为新建立的Pod进行节点(node)选择(即分配机器),负责集群的资源调度。组件抽离,可以方便替换成其他调度器
    • Kubernetes Controller

      • 负责执行各种控制器,目前已经提供了很多控制器来保证Kubernetes的正常运行
    • Replication Controller

      • 管理维护Replication Controller,关联Replication Controller和Pod,保证Replication Controller定义的副本数量与实际运行Pod数量一致
    • Node Controller

      • 管理维护Node,定期检查Node的健康状态,标识出(失效|未失效)的Node节点
    • Namespace Controller

      • 管理维护Namespace,定期清理无效的Namespace,包括Namesapce下的API对象,比如Pod、Service等
    • Service Controller

      • 管理维护Service,提供负载以及服务代理
    • EndPoints Controller

      • 管理维护Endpoints(Pod IP+ContainerPort),关联Service和Pod,创建Endpoints为Service的后端,当Pod发生变化时,实时更新Endpoints
    • Service Account Controller

      • 管理维护Service Account,为每个Namespace创建默认的Service Account,同时为Service Account创建Service Account Secret
    • Persistent Volume Controller

      • 管理维护Persistent Volume和Persistent Volume Claim,为新的Persistent Volume Claim分配Persistent Volume进行绑定,为释放的Persistent Volume执行清理回收
    • Daemon Set Controller

      • 管理维护Daemon Set,负责创建Daemon Pod,保证指定的Node上正常的运行Daemon Pod
    • Deployment Controller

      • 管理维护Deployment,关联Deployment和Replication Controller,保证运行指定数量的Pod。当Deployment更新时,控制实现Replication Controller和 Pod的更新
    • Job Controller

      • 管理维护Job,为Jod创建一次性任务Pod,保证完成Job指定完成的任务数目
    • Pod Autoscaler Controller

      • 实现Pod的自动伸缩,定时获取监控数据,进行策略匹配,当满足条件时执行Pod的伸缩动作
  • Kubernetes Node

    • 运行节点,运行管理业务容器

    • Kubelet

      • 负责管控容器,Kubelet会从Kubernetes API Server接收Pod的创建请求,启动和停止容器,监控容器运行状态并汇报给Kubernetes API Server
    • Kubernetes Proxy

      • 为Pod创建代理服务。从API Server获取所有的Service信息,并根据Service的信息创建代理服务,实现Service到Pod的请求路由和转发,从而实现Kubernetes层级的虚拟转发网络
    • Docker

      • Node上需要运行容器服务

二进制部署k8s集群

环境准备

  • 系统环境

    • 软件环境

      • 系统: CentOS7
        Docker: docker-ce.18.06
        Kubernetes: v1.13.2
        Etcd Version: 3.3.11
        Flanneld: v0.11.0
    • 服务器规划
      2U2G

      • 1.1.1.21 master apiserver,controller-manager,scheduler,etcd,kubectl
        1.1.1.22 node1 kubelet,kube-proxy,docker,flannel,etcd
        1.1.1.23 node2 kubelet,kube-proxy,docker,flannel,etcd
    • 关闭防火墙、selinux,互相解析,配置集群时间同步

    • 关闭swap

      • swapoff -a
        sed -i.bak ‘s/^.*swap/#&/’ /etc/fstab
    • 配置内核参数

      • vim /etc/sysctl.d/kubernetes.conf

net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1

#sysctl -p /etc/sysctl.d/kubernetes.conf

- 更新内核(7.6以下的系统)

	- yum update kernel -y

shutdown -r now

  • 安装配置docker
    (所有node节点)

    • [root@node ~]# curl http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
      [root@node ~]# yum -y install docker-ce-18.06.0.ce
      [root@node ~]# mkdir /etc/docker
      [root@node ~]# vim /etc/docker/daemon.json
      {
      “registry-mirrors”: [“https://pf5f57i3.mirror.aliyuncs.com”]
      }

[root@node ~]# systemctl enable docker;systemctl start docker

  • 下载二进制包
    (master节点)

    • [root@master ~]# wget https://dl.k8s.io/v1.13.2/kubernetes-server-linux-amd64.tar.gz
      [root@master ~]# wget https://github.com/etcd-io/etcd/releases/download/v3.2.26/etcd-v3.2.26-linux-amd64.tar.gz
      [root@master ~]# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
      [root@master ~]# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
      [root@master ~]# wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
      [root@master ~]# wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
    • kubernetes-server-linux-amd64.tar.gz - 包括了kubernetes的主要组件,无需下载其他包
      etcd-v3.2.26-linux-amd64.tar.gz - 是部署etcd需要用到的包
      cfssl相关软件 - 用于制作证书

部署etcd集群

  • Etcd简介

    • etcd是 CoreOS 推出的一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现。

    • 特点

      • 简单

        • 安装配置简单,而且提供了HTTP API进行交互,使用也很简单
      • 安全

        • 支持SSL证书验证
      • 快速

        • 根据官方提供的benchmark数据,单实例支持每秒2k+读操作
      • 可靠

        • 采用raft算法,实现分布式系统数据的可用性和一致性
    • 服务发现

      • etcd是一个服务发现系统,发现同一个分布式集群中的进程或服务并建立连接

      • 必备属性

        • 一个强一致性、高可用的服务存储目录。etcd本身就是
        • 一种注册服务和健康服务健康状况的机制。etcd中可以注册服务并配置key TTL,定时保持服务的心跳以监控健康状态
        • 一种查找和连接服务的机制。在每个主机上都部署一个proxy模式的etcd,可以确保访问etcd集群的服务都能够互相连接
    • 构建自身高可用集群方式

      • 静态发现

        • 预先已知 Etcd 集群中有哪些节点,在启动时直接指定好 Etcd 的各个 node 节点地址
      • Etcd动态发现

        • 通过已有的Etcd集群作为数据交互点,在扩展新的集群时实现通过已有集群进行服务发现的机制
      • DNS动态发现

        • 通过 DNS 查询方式获取其他节点地址信息
    • 端口

      • 2379

        • 提供HTTP API服务
      • 2380

        • 和peer通信
    • 集群

      • etcd支持单点部署,但生产环境推荐集群方式部署,etcd节点数3、5、7…
      • etcd会保证所有的节点都会保存数据,并保证数据的一致性和正确性
    • 服务组件

      • 二进制程序

        • etcd(主程序)、etcdctl(命令行工具)
      • 配置文件

        • /etc/etcd/etcd.conf #主配置文件, 自定义
          /etc/etcd/ssl/.pem #证书及私钥文件, 由cfssl命令及自定义json文件生成
          /usr/lib/systemd/system/etcd.service #systemd启动文件, 自定义
  • 创建CA证书

    • 设置系统命令

      • [root@master ~]# mv cfssl* /usr/local/bin/
        [root@master ~]# chmod +x /usr/local/bin/cfssl*
    • 创建CA配置文件

      • 配置证书生成策略,规定CA可以颁发哪种类型的证书

      • [root@master ~]# mkdir -p /etc/etcd/ssl
        [root@master ~]# cd /etc/etcd/ssl

      • [root@master ssl]# vim ca-config.json
        {
        “signing”: {
        “default”: {
        “expiry”: “87600h”
        },
        “profiles”: {
        “www”: {
        “expiry”: “87600h”,
        “usages”: [
        “signing”,
        “key encipherment”,
        “server auth”,
        “client auth”
        ]
        }
        }
        }
        }

        • [root@master ssl]# vim ca-csr.json
          {
          “CN”: “etcd CA”,
          “key”: {
          “algo”: “rsa”,
          “size”: 2048
          },
          “names”: [
          {
          “C”: “CN”,
          “L”: “GuangDong”,
          “ST”: “GuangZhou”
          }
          ]
          }

          • [root@master ssl]# vim server-csr.json
            {
            “CN”: “etcd”,
            “hosts”: [
            “1.1.1.21”,
            “1.1.1.22”,
            “1.1.1.23”
            ],
            “key”: {
            “algo”: “rsa”,
            “size”: 2048
            },
            “names”: [
            {
            “C”: “CN”,
            “L”: “GuangDong”,
            “ST”: “GuangZhou”
            }
            ]
            }
    • 生成CA和私钥

      • [root@master ssl]# cfssl_linux-amd64 gencert -initca ca-csr.json | cfssljson_linux-amd64 -bare ca #生成CA文件:ca-key.pem(私钥),ca.pem(证书),ca.csr(证书签名请求,用于交叉签名或重新签名)
      • [root@master ssl]# cfssl_linux-amd64 gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson_linux-amd64 -bare server #生成证书
  • 配置集群

    • [root@master ~]# tar xf etcd-v3.3.11-linux-amd64.tar.gz #解压etcd二进制包
      [root@master ~]# cp -p etcd-v3.3.11-linux-amd64/etc* /usr/local/bin/ #设置系统命令
    • [root@master ~]# vim /etc/etcd/etcd.conf #创建配置文件,配置时去掉注释
      #[Member] # 成员信息
      ETCD_NAME=“etcd-01” # 节点名称, 所有节点不一样
      ETCD_DATA_DIR=“/var/lib/etcd/default.etcd” #缓存目录, 如果修改配置, 需要清理. 否则还是会使用旧缓存
      ETCD_LISTEN_PEER_URLS=“https://1.1.1.21:2380” # 集群内部通信
      ETCD_LISTEN_CLIENT_URLS=“https://1.1.1.21:2379” # 客户端访问

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS=“https://1.1.1.21:2380”
ETCD_ADVERTISE_CLIENT_URLS=“https://1.1.1.21:2379”
ETCD_INITIAL_CLUSTER=“etcd-01=https://1.1.1.21:2380,etcd-02=https://1.1.1.22:2380,etcd-03=https://1.1.1.23:2380”
ETCD_INITIAL_CLUSTER_TOKEN=“etcd-cluster”
ETCD_INITIAL_CLUSTER_STATE=“new”
- [root@master ~]# vim /usr/lib/systemd/system/etcd.service #创建systemd启动文件
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=/etc/etcd/etcd.conf
ExecStart=/usr/local/bin/etcd
–name= E T C D N A M E   − − d a t a − d i r = {ETCD_NAME} \ --data-dir= ETCDNAME datadir={ETCD_DATA_DIR}
–listen-peer-urls= E T C D L I S T E N P E E R U R L S   − − l i s t e n − c l i e n t − u r l s = {ETCD_LISTEN_PEER_URLS} \ --listen-client-urls= ETCDLISTENPEERURLS listenclienturls={ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379
–advertise-client-urls= E T C D A D V E R T I S E C L I E N T U R L S   − − i n i t i a l − a d v e r t i s e − p e e r − u r l s = {ETCD_ADVERTISE_CLIENT_URLS} \ --initial-advertise-peer-urls= ETCDADVERTISECLIENTURLS initialadvertisepeerurls={ETCD_INITIAL_ADVERTISE_PEER_URLS}
–initial-cluster= E T C D I N I T I A L C L U S T E R   − − i n i t i a l − c l u s t e r − t o k e n = {ETCD_INITIAL_CLUSTER} \ --initial-cluster-token= ETCDINITIALCLUSTER initialclustertoken={ETCD_INITIAL_CLUSTER_TOKEN}
–initial-cluster-state=new
–cert-file=/etc/etcd/ssl/server.pem
–key-file=/etc/etcd/ssl/server-key.pem
–peer-cert-file=/etc/etcd/ssl/server.pem
–peer-key-file=/etc/etcd/ssl/server-key.pem
–trusted-ca-file=/etc/etcd/ssl/ca.pem
–peer-trusted-ca-file=/etc/etcd/ssl/ca.pem
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
- [root@master ~]# scp /usr/local/bin/etcd* node1:/usr/local/bin/ # 二进制命令
[root@master ~]# scp /usr/local/bin/etcd* node2:/usr/local/bin/
[root@master ~]# scp -r /etc/etcd/ node1:/etc/ # 配置文件, 包括证书文件
[root@master ~]# scp -r /etc/etcd/ node2:/etc/
[root@master ~]# scp /usr/lib/systemd/system/etcd.service node1:/usr/lib/systemd/system/
[root@master ~]# scp /usr/lib/systemd/system/etcd.service node2:/usr/lib/systemd/system/
- [root@node1&2 ~]# vim /etc/etcd/etcd.conf

	- 修改节点名称及IP
  • 启动集群

    • [root@all ~]# systemctl start etcd;systemctl enable etcd
      [root@all ~]# systemctl status etcd
    • 3节点的etcd集群至少两节点正常才能正常运行
  • 查看集群状态

    • [root@master ~]# etcdctl --cert-file=/etc/etcd/ssl/server.pem --key-file=/etc/etcd/ssl/server-key.pem --ca-file=/etc/etcd/ssl/ca.pem --endpoint=https://1.1.1.21:2379,https://1.1.1.22:2379,https://1.1.1.23:2379 cluster-health
      输出:
      member 245f0eaff21d8741 is healthy: got healthy result from https://1.1.1.21:2379
      member 6571fb7574e87dba is healthy: got healthy result from https://1.1.1.22:2379
      member 9b449b0ff1d4c375 is healthy: got healthy result from https://1.1.1.23:2379
      cluster is healthy
      说明集群正常运行, 所有节点都正常
    • [root@all ~]# alias etcdctl=‘etcdctl --ca-file=ca.pem --cert-file=server.pem --key-file=server-key.pem --endpoint=https://1.1.1.21:2379,https://1.1.1.22:2379,https://1.1.1.23:2379’
      echo alias etcdctl=‘etcdctl --ca-file=ca.pem --cert-file=server.pem --key-file=server-key.pem --endpoint=https://1.1.1.21:2379,https://1.1.1.22:2379,https://1.1.1.23:2379’ >> ~/.bashrc

部署flannel网络

  • Flannel简介

    • 可执行程序

      • mk-docker-opts.sh #将分配给flanneld的Pod子网网段信息写入 /run/flannel/docker,docker使用此文件中的环境变量配置 docker0 网桥
      • flanneld #使用默认网关所在的接口与其它节点通信,多个网络接口(如内网和公网)的节点可以用-iface 参数指定通信接口,如 eth0
    • 配置文件

      • /etc/flannel.conf # 主配置文件, 自定义
        /usr/lib/systemd/system/flanneld.service #systemd启动文件, 自定义
    • 功能

      • 让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址,并让属于不同节点上的容器能够直接通过虚拟IP通信
    • 原理图

    • 过程

      • 数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P的虚拟网卡,flanneld服务监听在网卡的另外一端

      • Flannel通过Etcd服务维护了一张节点间的路由表,分配了每个节点可用的IP地址段(不重复),再修改Docker的启动参数(设置地址段),确保集群中所有容器IP不会重复

      • 源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一样由docker0路由到达目标容器

      • UDP封装

        • 在UDP的数据内容部分其实是另一个ICMP的数据包。原始数据是在起始节点的Flannel服务上进行UDP封装的,投递到目的节点后就被另一端的Flannel服务还原成了原始的数据包,两边的Docker服务都感觉不到这个过程的存在
      • 路由

        • docker0地址段为24位掩码,路由为16位掩码。比如两个不同节点的容器IP分别为172.17.18.2、172.17.46.2,则flannel的路由为172.17.0.0/16
  • 向etcd写入集群Pod网段信息
    (任意etcd节点)

    • [root@master ~]# cd /etc/etcd/ssl/
      [root@master ssl]# etcdctl set /coreos.com/network/config ‘{ “Network”: “10.244.0.0/16”, “Backend”: {“Type”: “vxlan”}}’
      输出:
      { “Network”: “10.244.0.0/16”, “Backend”: {“Type”: “vxlan”}}
    • 写入的Pod网段${CLUSTER_CIDR}必须是/16段地址,必须与kube-controller-manager的–-cluster-cidr参数值一致
  • 安装Flannel

    • [root@all ~]# tar xf flannel-v0.11.0-linux-amd64.tar.gz
      [root@all ~]# mv flanneld mk-docker-opts.sh /usr/local/bin/
      [root@all ~]# vim /etc/flannel.conf
      FLANNEL_OPTIONS=“–etcd-endpoints=https://1.1.1.21:2379,https://1.1.1.22:2379,https://1.1.1.23:2379 -etcd-cafile=/etc/etcd/ssl/ca.pem -etcd-certfile=/etc/etcd/ssl/server.pem -etcd-keyfile=/etc/etcd/ssl/server-key.pem”

[root@all ~]# vim /usr/lib/systemd/system/flanneld.service
[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service

[Service]
Type=notify
EnvironmentFile=/etc/flannel.conf
ExecStart=/usr/local/bin/flanneld --ip-masq $FLANNEL_OPTIONS
ExecStartPost=/usr/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
Restart=on-failure

[Install]
WantedBy=multi-user.target

  • 配置Docker启动指定子网段

    • [root@all ~]# vim /usr/lib/systemd/system/docker.service
      EnvironmentFile=/run/flannel/subnet.env
      ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS
  • 启动flannel, 重启docker

    • [root@all ~]# systemctl daemon-reload
      [root@all ~]# systemctl start flanneld;systemctl enable flanneld
      [root@all ~]# systemctl restart docker
  • 验证是否生效

    • ip a

      • 所有节点上的子网都不一样,docker0的IP一定要在flannel的网段
    • [root@master ~]# cd /etc/etcd/ssl/
      [root@master ssl]# etcdctl ls /coreos.com/network/subnets
      输出所有节点的子网信息:
      /coreos.com/network/subnets/10.244.92.0-24
      /coreos.com/network/subnets/10.244.69.0-24
      /coreos.com/network/subnets/10.244.71.0-24

部署master节点

  • 简介

    • 运行的组件

      • kube-apiserver、kube-scheduler、kube-controller-manager
      • kube-scheduler和kube-controller-manager可以以集群模式运行,通过 leader 选举产生一个工作进程,其它进程处于阻塞模式
    • 目录

      • 主目录: /etc/kubernetes
        证书目录: /etc/kubernetes/ssl
        kube-apiserver 配置文件: /etc/kubernetes/apiserver.conf
        kube-scheduler 配置文件: /etc/kubernetes/kube-scheduler.conf
        kube-controller-manager 配置文件: /etc/kubernetes/kube-controller-manager.conf
  • 创建CA证书

    • [root@master ~]# mkdir -p /etc/kubernetes/ssl
      [root@master ~]# cd /etc/kubernetes/ssl

    • [root@master ssl]# vim ca-config.json
      {
      “signing”: {
      “default”: {
      “expiry”: “87600h”
      },
      “profiles”: {
      “kubernetes”: {
      “expiry”: “87600h”,
      “usages”: [
      “signing”,
      “key encipherment”,
      “server auth”,
      “client auth”
      ]
      }
      }
      }
      }

      • [root@master ssl]# vim ca-csr.json
        {
        “CN”: “kubernetes”,
        “key”: {
        “algo”: “rsa”,
        “size”: 2048
        },
        “names”: [
        {
        “C”: “CN”,
        “L”: “GuangDong”,
        “ST”: “GuangZhou”,
        “O”: “k8s”,
        “OU”: “System”
        }
        ]
        }

        • [root@master ssl]# vim server-csr.json
          {
          “CN”: “kubernetes”,
          “hosts”: [
          “10.0.0.1”,
          “127.0.0.1”,
          “1.1.1.21”,
          “kubernetes”,
          “kubernetes.default”,
          “kubernetes.default.svc”,
          “kubernetes.default.svc.cluster”,
          “kubernetes.default.svc.cluster.local”
          ],
          “key”: {
          “algo”: “rsa”,
          “size”: 2048
          },
          “names”: [
          {
          “C”: “CN”,
          “L”: “GuangDong”,
          “ST”: “GuangZhou”,
          “O”: “k8s”,
          “OU”: “System”
          }
          ]
          }
    • [root@master ssl]# cfssl_linux-amd64 gencert -initca ca-csr.json | cfssljson_linux-amd64 -bare ca
      [root@master ssl]# cfssl_linux-amd64 gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson_linux-amd64 -bare server

  • 部署kube-apiserver

    • 配置主程序

      • [root@master ~]# tar xf kubernetes-server-linux-amd64.tar.gz
        [root@master ~]# cp -p kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl} /usr/local/bin/
    • 创建Token文件

      • [root@master ~]# head -c 16 /dev/urandom | od -An -t x | tr -d ’ ’ #生成Token
        deb6a3bafd8cc92447793255acc45e87
        [root@master ~]# vim /etc/kubernetes/token.csv #TLS Bootstrapping Token文件
        deb6a3bafd8cc92447793255acc45e87,kubelet-bootstrap,10001,“system:kubelet-bootstrap”
    • 创建配置文件

      • [root@master ~]# vim /etc/kubernetes/apiserver
        KUBE_APISERVER_OPTS=“–logtostderr=true
        –v=4
        –etcd-servers=https://1.1.1.21:2379,https://1.1.1.22:2379,https://1.1.1.23:2379
        –bind-address=192.168.10.10
        –secure-port=6443
        –advertise-address=192.168.10.10
        –allow-privileged=true
        –service-cluster-ip-range=10.0.0.0/24
        –enable-admission-plugins=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota,NodeRestriction
        –authorization-mode=RBAC,Node
        –enable-bootstrap-token-auth
        –token-auth-file=/etc/kubernetes/token.csv
        –service-node-port-range=30000-50000
        –tls-cert-file=/etc/kubernetes/ssl/server.pem
        –tls-private-key-file=/etc/kubernetes/ssl/server-key.pem
        –client-ca-file=/etc/kubernetes/ssl/ca.pem
        –service-account-key-file=/etc/kubernetes/ssl/ca-key.pem
        –etcd-cafile=/etc/etcd/ssl/ca.pem
        –etcd-certfile=/etc/etcd/ssl/server.pem
        –etcd-keyfile=/etc/etcd/ssl/server-key.pem”
    • 创建启动文件

      • [root@master ~]# vim /usr/lib/systemd/system/kube-apiserver.service
        [Unit]
        Description=Kubernetes API Server
        Documentation=https://github.com/kubernetes/kubernetes
        After=etcd.service
        Wants=etcd.service

[Service]
EnvironmentFile=-/etc/kubernetes/apiserver
ExecStart=/usr/local/bin/kube-apiserver $KUBE_APISERVER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

- 启动服务

	- [root@master ~]# systemctl daemon-reload

[root@master ~]# systemctl start kube-apiserver;systemctl enable kube-apiserver
[root@master ~]# systemctl status kube-apiserver

  • 部署kube-scheduler

    • 创建配置文件

      • [root@master ~]# vim /etc/kubernetes/kube-scheduler.conf
        KUBE_SCHEDULER_OPTS=“–logtostderr=true --v=4 --master=127.0.0.1:8080 --leader-elect”
      • 参数说明:
        • --master:连接apiserver
        • --leader-elect:当该组件启动多个时,自动选举(HA),被选为 leader的节点负责处理工作,其它节点为阻塞状态
    • 创建启动文件

      • [root@master ~]# vim /usr/lib/systemd/system/kube-scheduler.service
        [Unit]
        Description=Kubernetes Scheduler
        Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/etc/kubernetes/kube-scheduler.conf
ExecStart=/usr/local/bin/kube-scheduler $KUBE_SCHEDULER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

- 启动服务

	- [root@master ~]# systemctl daemon-reload

[root@master ~]# systemctl start kube-scheduler;systemctl enable kube-scheduler
[root@master ~]# systemctl status kube-scheduler

  • 部署kube-controller-manager

    • 创建配置文件

      • [root@master ~]# vim /etc/kubernetes/kube-controller-manager.conf
        KUBE_CONTROLLER_MANAGER_OPTS=“–logtostderr=true
        –v=4
        –master=127.0.0.1:8080
        –leader-elect=true
        –address=127.0.0.1
        –service-cluster-ip-range=10.0.0.0/24
        –cluster-name=kubernetes
        –cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem
        –cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem
        –root-ca-file=/etc/kubernetes/ssl/ca.pem
        –service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem”
    • 创建启动文件

      • [root@master ~]# vim /usr/lib/systemd/system/kube-controller-manager.service
        [unit]
        Description=Kubernetes Controller Manager
        Documentation=https://github.com/kubernetes/kubernetes

[Service]
EnvironmentFile=-/etc/kubernetes/kube-controller-manager.conf
ExecStart=/usr/local/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

- 启动服务

	- [root@master ~]# systemctl daemon-reload

[root@master ~]# systemctl start kube-controller-manager
[root@master ~]# systemctl enable kube-controller-manager
[root@master ~]# systemctl status kube-controller-manager

- 检查各服务状态及Master集群状态

	- [root@master ~]# kubectl get cs

NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-2 Healthy {“health”:“true”}
etcd-1 Healthy {“health”:“true”}
etcd-0 Healthy {“health”:“true”}
You have new mail in /var/spool/mail/root

部署node节点

  • 简介

    • Master apiserver启用TLS认证后,Node节点kubelet组件想要加入集群,必须使用CA签发的有效证书才能与apiserver通信,节点很多时需用到TLS Bootstrapping机制

    • Kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署

    • 运行组件

      • docker、kubelet、kube-proxy
    • 目录

      • 主目录: /etc/kubernetes
        证书目录: /etc/kubernetes/ssl
  • 部署kubelet

    • 创建目录

      • [root@node1&2 ~]# mkdir -p /etc/kubernetes/ssl
    • 创建kube-proxy证书

      • [root@master ~]# cd /etc/kubernetes/ssl/
        [root@master ssl]# vim kube-proxy-csr.json
        {
        “CN”: “system:kube-proxy”,
        “hosts”: [],
        “key”: {
        “algo”: “rsa”,
        “size”: 2048
        },
        “names”: [
        {
        “C”: “CN”,
        “L”: “GuangDong”,
        “ST”: “GuangZhou”,
        “O”: “k8s”,
        “OU”: “System”
        }
        ]
        }
      • [root@master ssl]# cfssl_linux-amd64 gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json --profile=kubernetes kube-proxy-csr.json | cfssljson_linux-amd64 -bare kube-proxy
    • 创建kubelet bootstrap kubeconfig文件

      • [root@master ~]# vim bs_kubeconfig.sh
        #!/bin/bash
        BOOTSTRAP_TOKEN=$(awk -F “,” ‘{print $1}’ /etc/kubernetes/token.csv)
        KUBE_SSL=/etc/kubernetes/ssl/
        KUBE_APISERVER=“https://192.168.10.10:6443”

cd $KUBE_SSL

设置集群参数

kubectl config set-cluster kubernetes
–certificate-authority=./ca.pem
–embed-certs=true
–server=${KUBE_APISERVER}
–kubeconfig=bootstrap.kubeconfig

设置客户端认证参数

kubectl config set-credentials kubelet-bootstrap
–token=${BOOTSTRAP_TOKEN}
–kubeconfig=bootstrap.kubeconfig

设置上下文参数

kubectl config set-context default
–cluster=kubernetes
–user=kubelet-bootstrap
–kubeconfig=bootstrap.kubeconfig

设置上下文

kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

创建 kube-proxy kubeconfig 文件

kubectl config set-cluster kubernetes
–certificate-authority=./ca.pem
–embed-certs=true
–server=${KUBE_APISERVER}
–kubeconfig=kube-proxy.kubeconfig

kubectl config set-credentials kube-proxy
–client-certificate=./kube-proxy.pem
–client-key=./kube-proxy-key.pem
–embed-certs=true
–kubeconfig=kube-proxy.kubeconfig

kubectl config set-context default
–cluster=kubernetes
–user=kube-proxy
–kubeconfig=kube-proxy.kubeconfig

kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
- [root@master ~]# sh bs_kubeconfig.sh
- [root@master ~]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap # 将 kubelet-bootstrap 用户绑定到系统集群角色

- 拷贝

	- [root@master ~]# scp kubernetes/server/bin/{kubelet,kube-proxy} node1:/usr/local/bin/

[root@master ~]# scp kubernetes/server/bin/{kubelet,kube-proxy} node2:/usr/local/bin/
[root@master ~]# scp /etc/kubernetes/ssl/.kubeconfig node1:/etc/kubernetes/
[root@master ~]# scp /etc/kubernetes/ssl/
.kubeconfig node2:/etc/kubernetes/

- 创建kubelet配置文件

	- [root@node1&2 ~]# cd /etc/kubernetes/

[root@node1&2 kubernetes]# vim kubelet.conf
KUBELET_OPTS=“–logtostderr=true
–v=4
–hostname-override=1.1.1.22
–kubeconfig=/etc/kubernetes/kubelet.kubeconfig
–bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig
–config=/etc/kubernetes/kubelet.yaml
–cert-dir=/etc/kubernetes/ssl
–pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0”

- 创建kubelet参数配置模板文件

	- [root@node1&2 kubernetes]# vim kubelet.yaml

kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 1.1.1.22
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS: [“10.0.0.2”]
clusterDomain: cluster.local.
failSwapOn: false
authentication:
anonymous:
enabled: true

- 创建启动文件

	- [root@node1&2 kubernetes]# vim /usr/lib/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service

[Service]
EnvironmentFile=/etc/kubernetes/kubelet.conf
ExecStart=/usr/local/bin/kubelet $KUBELET_OPTS
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target

- 启动服务

	- [root@node1&2 kubernetes]# systemctl daemon-reload

[root@node1&2 kubernetes]# systemctl start kubelet
[root@node1&2 kubernetes]# systemctl enable kubelet
[root@node1&2 kubernetes]# systemctl status kubelet

  • 部署kube-proxy

    • 创建配置文件

      • [root@node1&2 kubernetes]# vim kube-proxy.conf
        KUBE_PROXY_OPTS=“–logtostderr=true
        –v=4
        –hostname-override=1.1.1.22
        –cluster-cidr=10.0.0.0/24
        –kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig”
    • 创建启动文件

      • [root@node1&2 kubernetes]# vim /usr/lib/systemd/system/kube-proxy.service
        [Unit]
        Description=Kubernetes Proxy
        After=network.target

[Service]
EnvironmentFile=-/etc/kubernetes/kube-proxy.conf
ExecStart=/usr/local/bin/kube-proxy $KUBE_PROXY_OPTS
Restart=on-failure

[Install]
WantedBy=multi-user.target

- 启动服务

	- [root@node1&2 kubernetes]# systemctl daemon-reload

[root@node1&2 kubernetes]# systemctl start kube-proxy
[root@node1&2 kubernetes]# systemctl enable kube-proxy
[root@node1&2 kubernetes]# systemctl status kube-proxy

  • 同意CSR请求

    • 介绍

      • Kubelet 启动后使用 --bootstrap-kubeconfig 向 kube-apiserver 发送 CSR 请求
      • 当CSR被approve后,kube-controller-manager(需要配置–cluster-signing-cert-file 和–cluster-signing-key-file参数)为kubelet创建TLS客户端证书、私钥和–kubeletconfig文件
    • 查看请求CSR列表

      • [root@master ~]# kubectl get csr
      • approve前处于pending状态,approve后变为Approved,Issused状态
    • 手动approve CSR

      • [root@master ~]# kubectl certificate approve
      • 请求列表中查看NAME
    • 查看集群状态

      • [root@master ~]# kubectl get cs
      • [root@master ~]# kubectl get node

systemd管理服务

开机启动

  • 支持Systemd的软件在安装的时候,会自动在/usr/lib/systemd/system目录添加一个配置文件
  • systemctl enable httpd相当于在/etc/systemd/system目录添加一个符号链接,指向/usr/lib/systemd/system里面的httpd.service文件
  • 开机时,Systemd只执行/etc/systemd/system目录里面的配置文件

启动服务

  • 设置开机启动以后,软件并不会立即启动,必须等到下一次开机。想要立即启动执行systemctl start httpd

  • 执行启动命令后有可能启动失败,需要执行systemctl status httpd命令查看服务的状态

  • 服务状态输出结果含义

    • Loaded行: 配置文件的位置,是否设为开机启动
    • Active行: 表示运行状态
    • Docs行: 帮助文档
    • Main PID行: 主进程ID
    • Status行: 由应用本身提供的软件当前状态
    • Tasks行: 任务
    • Memory: 内存使用
    • CGroup块: 应用的所有子进程
    • 日志块: 应用的日志

停止服务

  • 终止正在运行的服务,需要执行systemctl stop httpd命令
  • 如果stop命令无响应则需要杀进程systemctl kill httpd
  • 重启服务执行systemctl restart httpd命令

启动文件

  • 一个服务怎么启动,完全由它的启动文件决定,文件主要放在/usr/lib/systemd/system目录,也可能在/etc/systemd/system目录

  • 例:sshd

    • [root@master1 ~]# cat /usr/lib/systemd/system/sshd.service
      [Unit]
      Description=OpenSSH server daemon
      Documentation=man:sshd(8) man:sshd_config(5)
      After=network.target sshd-keygen.service
      Wants=sshd-keygen.service

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

  • 模块

    • [Unit]

      • 启动顺序与依赖关系

      • Description: 当前服务描述信息

      • Documentation: 文档位置

      • 启动顺序

        • After: 本服务应该在哪些服务之后启动
        • Before: 本服务应该在哪些服务之前启动
          • 注: After和Before字段只涉及启动顺序,不涉及依赖关系
      • 依赖关系

        • Wants:表示"弱依赖"关系,依赖的服务启动失败或停止运行,不影响sshd.service继续执行
        • Requires: 表示"强依赖"关系,如果所依赖的服务启动失败或异常退出,那么当前服务也要退出
          • 注: Wants字段与Requires字段只涉及依赖关系,与启动顺序无关,默认情况下是同时启动的
    • [Service]

      • 启动行为,定义如何启动当前服务

      • 启动命令

        • EnvironmentFile: 指定当前服务的环境参数文件。该文件内部的key=value键值对,可以用$key的形式,在当前配置文件中获取
        • ExecStart: 定义启动进程时执行的命令
        • ExecReload: 重启服务时执行的命令
        • ExecStop: 停止服务时执行的命令
        • ExecStartPre: 启动服务之前执行的命令
        • ExecStartPost: 启动服务之后执行的命令
        • ExecStopPost: 停止服务之后执行的命令
        • 所有的启动设置之前,都可以加上一个连词号(-),表示"抑制错误",即发生错误的时候,不影响其他命令的执行
      • Type-启动类型

        • simple(默认值):ExecStart字段启动的进程为主进程
        • forking:ExecStart字段将以fork()方式启动,此时父进程将会退出,子进程将成为主进程
        • oneshot:类似于simple,但只执行一次,Systemd 会等它执行完,才启动其他服务
        • dbus:类似于simple,但会等待 D-Bus 信号后启动
        • notify:类似于simple,启动结束后会发出通知信号,然后 Systemd 再启动其他服务
        • idle:类似于simple,但是要等到其他任务都执行完,才会启动该服务。一种使用场合是为让该服务的输出,不与其他服务的输出相混合
      • 重启行为

        • KillMode

          • control-group(默认值):杀掉当前控制组里面的所有子进程
          • process:只杀主进程
          • mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
          • none:没有进程会被杀掉,只是执行服务的 stop 命令
        • Restart

          • no(默认值):退出后不会重启
          • on-success:只有正常退出时(退出状态码为0),才会重启
          • on-failure:非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启
          • on-abnormal:只有被信号终止和超时,才会重启
          • on-abort:只有在收到没有捕捉到的信号终止时,才会重启
          • on-watchdog:超时退出,才会重启
          • always:不管是什么退出原因,总是重启
          • 对于守护进程,推荐设为on-failure。对于那些允许发生错误退出的服务,可以设为on-abnormal
        • RestartSec

          • 表示 Systemd 重启服务之前,需要等待的秒数
    • [Install]

      • 定义如何安装这个配置文件,即怎样做到开机启动

      • WantedBy

        • 表示该服务所在的Target(服务组,表示一组服务)
      • systemctl get-default

        • 默认的启动 Target,该服务组中的所有服务都开机启动
      • systemctl list-dependencies multi-user.target

        • 查看 multi-user.target 包含的所有服务
      • 常用的 Target

        • multi-user.target

          • 表示多用户命令行状态
        • graphical.target

          • 表示图形用户状态,它依赖于multi-user.target

Target 的配置文件

  • systemctl cat multi-user.target

    • 查看Target的配置文件
  • Requires: 要求basic.target一起运行

  • Conflicts: 冲突字段。如果rescue.service或rescue.target正在运行,multi-user.target就不能运行,反之亦然

  • After:表示multi-user.target在basic.target 、 rescue.service、 rescue.target之后启动,如果它们有启动的话

  • AllowIsolate:允许使用systemctl isolate命令切换到multi-user.targe

修改配置文件后重启

  • 修改配置文件以后,需要重新加载配置文件,然后重新启动相关服务
  • systemctl daemon-reload

  • systemctl restart XXX

kubeadm部署k8s集群

部署方式

  • 单Master部署

    • https://zhuanlan.zhihu.com/p/121098101 (Version:1.17.4)
  • 高可用集群部署

    • https://zhuanlan.zhihu.com/p/121100475 (Version:1.20.15)

kubeadm简介

  • 背景

    • kubelet 是 Kubernetes 项目用来操作 Docker 等容器运行时的核心组件,除了跟容器运行时打交道外,kubelet 在配置容器网络、管理容器数据卷时,都需要直接操作宿主机。如果将 kubelet 本身运行在一个容器里,那么直接操作宿主机就会变得很麻烦
  • 方案

    • 把 kubelet 直接运行在宿主机上,然后使用容器部署其他的 Kubernetes 组件
  • 步骤

    • 1).在机器上手动安装 kubeadm、kubelet 和 kubectl
    • 2).布署好一个 Master 节点 – init
    • 3).将其他节点加入到集群中来 --join

高可用集群部署的etcd拓扑方案

  • 堆叠

    • etcd提供的分布式数据存储集群与由kubeadm管理的运行master组件的集群节点堆叠部署

    • 每个master节点运行kube-apiserver,kube-scheduler和kube-controller-manager的一个实例。kube-apiserver使用负载平衡器暴露给工作节点

    • 每个master节点创建一个本地etcd成员,该etcd成员仅与本节点kube-apiserver通信。这同样适用于本地kube-controller-manager 和kube-scheduler实例

    • 优势

      • 该拓扑将master和etcd成员耦合在相同节点上。比设置具有外部etcd节点的集群更简单,并且更易于管理复制
    • 劣势

      • 如果一个节点发生故障,则etcd成员和master实例都将丢失,并且冗余会受到影响
  • 外部

    • 由etcd提供的分布式数据存储集群部署在运行master组件的节点形成的集群外部

    • 在外部ETCD拓扑中的每个master节点运行一个kube-apiserver,kube-scheduler和kube-controller-manager实例。并且kube-apiserver使用负载平衡器暴露给工作节点。但是,etcd成员在不同的主机上运行,每个etcd主机与kube-apiserver每个master节点进行通信

    • 优势

      • 提供了HA设置,其中丢失master实例或etcd成员具有较小的影响并且不像堆叠的HA拓扑那样影响集群冗余
    • 劣势

      • 需要两倍于堆叠HA拓扑的主机数。具有此拓扑的HA群集至少需要三个用于master节点的主机和三个用于etcd节点的主机

高可用集群负载均衡

  • 部署集群前首选需要为kube-apiserver创建负载均衡器,负载平衡器将流量分配到其目标列表中的所有健康master节点。apiserver的运行状况检查是对kube-apiserver侦听的端口的TCP检查(默认值:6443)
  • 负载均衡器必须能够与apiserver端口上的所有master节点通信。它还必须允许其侦听端口上的传入流量。另外确保负载均衡器的地址始终与kubeadm的ControlPlaneEndpoint地址匹配
  • haproxy/nignx+keepalived是其中可选的负载均衡方案,针对公有云环境可以直接使用运营商提供的负载均衡产品
  • 健康检测可使用nc命令:# nc -v -w 2 -z host port #-v:显示详细信息 -w:指定超时时间 -z:Zero-I/O模式, 仅报告连接状态

高可用集群部署

  • 参考文档

    • https://zhuanlan.zhihu.com/p/121100475 (Version:1.18.0)
  • 环境准备

    • 服务器2U2G

      • 192.168.10.11 master1
        192.168.10.12 master2
        192.168.10.13 master3
        192.168.10.14 node
        vip: 192.168.10.100
    • 关闭防火墙、selinux,互相解析,时间同步,禁用swap分区,配置内核参数,升级内核

    • 加载ipvs模块

      • [root@master1 ~]# yum install ipset ipvsadm -y

        • 安装相关管理工具
      • [root@master1 ~]# vim /etc/sysconfig/modules/ipvs.modules
        #!/bin/bash
        modprobe – ip_vs
        modprobe – ip_vs_rr
        modprobe – ip_vs_wrr
        modprobe – ip_vs_sh
        modprobe – nf_conntrack_ipv4

[root@master1 ~]# chmod +x /etc/sysconfig/modules/ipvs.modules
[root@master1 ~]# /etc/sysconfig/modules/ipvs.modules
[root@master1 ~]# lsmod |egrep ‘ip_vs|nf_conntrack’

  • 安装配置docker

    • 安装docker(略)- 建议安装19.03版

    • 配置docker

      • [root@all ~]# mkdir /etc/docker
        [root@all ~]# vim /etc/docker/daemon.json
        {
        “exec-opts”: [“native.cgroupdriver=systemd”],
        “log-driver”: “json-file”,
        “log-opts”: {
        “max-size”: “100m”
        },
        “storage-driver”: “overlay2”,
        “storage-opts”: [
        “overlay2.override_kernel_check=true”
        ],
        “registry-mirrors”: [“https://pf5f57i3.mirror.aliyuncs.com”]
        }
    • 启动docker

      • [root@all ~]# systemctl start docker;systemctl enable docker
  • 安装负载均衡

    • 介绍

      • kubernetes master节点运行kube-apiserver、kube-scheduler、kube-controller-manager组件
      • kube-scheduler 和 kube-controller-manager 可以以集群模式运行,通过 leader 选举产生一个工作进程,其它进程处于阻塞模式
      • kube-apiserver可以运行多个实例,但对其它组件需要提供统一的访问地址,该地址需要高可用
      • 本次部署使用 keepalived+haproxy 实现 kube-apiserver VIP 高可用和负载均衡
      • keepalived 提供 kube-apiserver 对外服务的 VIP高可用。haproxy 监听 VIP,后端连接所有 kube-apiserver 实例,提供健康检查和负载均衡功能
      • 本次部署复用 master 节点的三台机器,在所有3个master节点部署haproxy和keepalived组件,以达到更高的可用性
      • kube-apiserver的端口为6443, 为避免冲突, haproxy 监听的端口要与之不同,此实验中为6444
      • keepalived 在运行过程中周期检查本机的 haproxy 进程状态,如果检测到 haproxy 进程异常,则触发VIP 飘移
      • 所有组件(如 kubeclt、apiserver、controller-manager、scheduler 等)都通过 VIP 监听的6444端口访问 kube-apiserver 服务
      • 在3个master节点以容器方式部署haproxy,容器暴露6444端口,负载均衡到后端3个apiserver的6443端口,3个节点haproxy配置文件相同
    • 创建haproxy启动脚本

      • [root@master ~]# vim haproxy.sh
        #!/bin/bash
        MasterIP1=192.168.10.11
        MasterIP2=192.168.10.12
        MasterIP3=192.168.10.13
        MasterPort=6443 # apiserver端口

        docker run -d --restart=always --name haproxy-k8s -p 6444:6444
        -e MasterIP1= M a s t e r I P 1   − e M a s t e r I P 2 = MasterIP1 \ -e MasterIP2= MasterIP1 eMasterIP2=MasterIP2
        -e MasterIP3= M a s t e r I P 3   − e M a s t e r P o r t = MasterIP3 \ -e MasterPort= MasterIP3 eMasterPort=MasterPort wise2c/haproxy-k8s
    • 创建keepalived启动脚本

      • [root@master ~]# vim keepalived.sh
        #!/bin/bash
        VIRTUAL_IP=192.168.10.100 # VIP
        INTERFACE=ens33 # 网卡名称
        NETMASK_BIT=24
        CHECK_PORT=6444 # Haproxy端口
        RID=10
        VRID=160
        MCAST_GROUP=224.0.0.18
        docker run -itd --restart=always --name=keepalived-k8s
        –net=host --cap-add=NET_ADMIN
        -e VIRTUAL_IP= V I R T U A L I P   − e I N T E R F A C E = VIRTUAL_IP \ -e INTERFACE= VIRTUALIP eINTERFACE=INTERFACE
        -e NETMASK_BIT= N E T M A S K B I T   − e C H E C K P O R T = NETMASK_BIT \ -e CHECK_PORT= NETMASKBIT eCHECKPORT=CHECK_PORT
        -e RID= R I D − e V R I D = RID -e VRID= RIDeVRID=VRID
        -e MCAST_GROUP=$MCAST_GROUP wise2c/keepalived-k8s
    • 运行测试

      • [root@master ~]# sh haproxy.sh
        [root@master ~]# sh keepalived.sh
      • 1).在每台机器上查看容器(haproxy, keepalived)是否都正常运行
        2).在每台机器上查看6444端口是否监听
        3).在有VIP的机器关闭haproxy容器或keepalived容器看看VIP能否正常飘移
  • 安装kubeadm

    • 配置yum源

      • [root@all ~]# curl https://gitee.com/leedon21/k8s/raw/master/kubernetes.repo -o /etc/yum.repos.d/kubernetes.repo
    • 查询版本

      • [root@all ~]# yum list --showduplicates|egrep kubeadm
      • 用不了的话关闭gpgcheck
    • 安装软件

      • [root@all ~]# yum install -y kubeadm-1.20.15-0 kubelet-1.20.15-0 kubectl-1.20.15-0 ipvsadm #注意所有的软件版本要一致
    • 设置开机启动kubelet

      • [root@all ~]# systemctl enable kubelet
  • 初始化master1

    • 创建初始化配置文件

      • [root@master1 ~]# mkdir k8s
        [root@master1 ~]# cd k8s/
        [root@master1 k8s]# kubeadm config print init-defaults > init.yml
    • 修改初始化配置文件

      • [root@master1 k8s]# vim init.yml

        localAPIEndpoint:
        advertiseAddress: 192.168.10.11 # 此处改为本机IP

        clusterName: kubernetes
        controlPlaneEndpoint: “192.168.10.100:6444” # 高可用集群增加VIP:PORT

        imageRepository: registry.aliyuncs.com/google_containers # 国内镜像仓库
        kind: ClusterConfiguration
        kubernetesVersion: v1.20.15 # 版本号

        podSubnet: 10.244.0.0/16 # pod子网,和Flannel中要一致

        scheduler: {}
        — #增加这一部分
        apiVersion: kubeproxy.config.k8s.io/v1alpha1
        kind: KubeProxyConfiguration
        mode: ipvs
    • 初始化

      • [root@master1 k8s]# kubeadm init --config=init.yml --upload-certs |tee kubeadm-init.log

      • 成功后注意查看输出信息,包含配置kubectl命令、加入master节点命令、加入worker节点命令

      • 如果中途失败,执行 kubeadm reset 命令清理,再次初始化,然后再执行init或join操作

      • init主要操作

        • [init]:指定版本进行初始化操作
          [preflight] :初始化前的检查和下载所需要的Docker镜像文件
          [kubelet-start]:生成kubelet的配置文件”“var/lib/kubelet/config.yaml”,没有这个文件kubelet无法启动,所以初始化之前的kubelet实际上启动不会成功。
          [certificates]:生成Kubernetes使用的证书,存放在/etc/kubernetes/pki目录中
          [kubeconfig] :生成 KubeConfig 文件,存放在/etc/kubernetes目录中,组件之间通信需要使用对应文件。
          [control-plane]:使用/etc/kubernetes/manifest目录下的YAML文件,安装 Master 组件
          [etcd]:使用/etc/kubernetes/manifest/etcd.yaml安装Etcd服务
          [wait-control-plane]:等待control-plan部署的Master组件启动
          [apiclient]:检查Master组件服务状态
          [uploadconfig]:更新配置
          [kubelet]:使用configMap配置kubelet
          [patchnode]:更新CNI信息到Node上,通过注释的方式记录
          [mark-control-plane]:为当前节点打标签,打了角色Master,和不可调度标签,这样默认就不会使用Master节点来运行Pod
          [bootstrap-token]:生成token记录下来,后边使用kubeadm join往集群中添加节点时会用到
          [addons]:安装附加组件CoreDNS和kube-proxy
  • 修改yaml文件

    • [root@master1 k8s]# /etc/kubernetes/manifests/kube-controller-manager.yaml
      [root@master1 k8s]# /etc/kubernetes/manifests/kube-scheduler.yaml
      注释掉:–port=0
  • 配置kubectl命令

    • 通过配置文件

      • [root@master ~]# mkdir -p $HOME/.kube
        [root@master ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
        [root@master ~]# sudo chown ( i d − u ) : (id -u): (idu):(id -g) $HOME/.kube/config
    • 通过环境变量

      • [root@master ~]# echo ‘export KUBECONFIG=/etc/kubernetes/admin.conf’ >> ~/.bashrc
        [root@master ~]# source ~/.bashrc
    • 查看Pod

      • [root@master ~]# kubectl get po -n kube-system
    • 查看组件状态

      • [root@master ~]# kubectl get cs
    • 查看node

      • [root@master1 k8s]# kubectl get no
  • 安装网络插件

    • [root@master1 ~]# kubectl apply -f https://gitee.com/leedon21/k8s/raw/master/kube-flannel.yml

    • 仅在Master1节点操作

    • 查看Pod

      • [root@master ~]# kubectl get po -n kube-system
    • 查看node

      • [root@master1 k8s]# kubectl get no
  • 加入master节点

    • 从初始化输出或kubeadm-init.log中获取命令将master2和master3加入到集群中来

      • root@master2 ~]# kubeadm join 192.168.10.100:6444 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:673d71fd341c79d3a013993c546bbf529f8626506f8d14fc69f0be376956e56f \
--control-plane --certificate-key b696a3afc89a8c60e130028d66be172c348ee80c789fcec6f79f759142eea6b8
- 分别在master2和master3上配置好命令行工具kubectl
  • 加入node节点

    • Kubernetes 的 Worker 节点跟 Master 节点几乎是相同的,它们运行着的都是一个 kubelet 组件

    • 唯一的区别在于,Master 节点上还会自动运行 kube-apiserver、kube-scheduler、kube-controller-manger 这三个系统 Pod

    • 从init的输出或kubeadm-init.log文件中获取命令将node节点加入到集群中来

      • [root@node1 ~]# kubeadm join 192.168.10.100:6444 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:673d71fd341c79d3a013993c546bbf529f8626506f8d14fc69f0be376956e56f
- 验证

	- 查看Pod

		- [root@master ~]# kubectl get po -n kube-system

	- 查看node

		- [root@master ~]# kubectl get no

	- 查看代理规则

		- [root@master ~]# ipvsadm -Ln

单master部署

  • 参考文档

    • https://zhuanlan.zhihu.com/p/121098101 (Version:1.17.4)
  • 清理高可用集群环境

    • 重置

      • kubeadm reset [–v=5]
    • 删除节点

      • kubectl delete no master worker
    • 清理cni配置

      • rm -rf /etc/cni/net.d
    • 清理ipvs

      • ipvsadm -C
    • 清理iptables

      • iptables -F
      • iptables -t nat -F
    • 删除kubeconfig文件

      • rm -rf $HOME/.kube/config file
    • 删除容器

      • docker rm -f docker ps -a -q
    • 重启

      • shutdown -r now
  • 修改配置

    • 初始化文件

      • [root@master1 ~]#vim k8s/init.yml
        删除controlPlaneEndpoint: “192.168.10.100:6444”
    • 解析文件

      • vim /etc/hosts
    • 主机名

      • hostnamectl set-hostname
  • 初始化

    • [root@master1 ~]# cd k8s
    • [root@master1 k8s]# kubeadm init --config=init.yml --upload-certs |tee kubeadm-init.log
  • 配置kubectl命令

    • [root@master ~]# echo ‘export KUBECONFIG=/etc/kubernetes/admin.conf’ >> ~/.bashrc
      [root@master ~]# source ~/.bashrc
  • 修改文件

    • [root@master1 k8s]# /etc/kubernetes/manifests/kube-controller-manager.yaml
      [root@master1 k8s]# /etc/kubernetes/manifests/kube-scheduler.yaml
      注释掉:–port=0
  • 安装网络插件

    • [root@master1 ~]# kubectl apply -f https://gitee.com/leedon21/k8s/raw/master/kube-flannel.yml
  • 加入node节点

    • 从init的输出或kubeadm-init.log文件中获取命令将node节点加入到集群中来

    • 验证

      • 查看Pod

        • [root@master ~]# kubectl get po -n kube-system
      • 查看node

        • [root@master ~]# kubectl get no
      • 查看代理规则

        • [root@master ~]# ipvsadm -Ln

重新join节点

  • token

    • 默认生成的 token 有效期为 24 小时,如果希望生成一个永久生效的,可加选项 --ttl=0

    • 查看token状态

      • [root@master1 ~]# kubeadm token list

        • TTL: token的有效期

    • 生成token

      • [root@master1 ~]# kubeadm token generate
        8sezkh.lx1xz3jodwehsacg
  • discovery-token-ca-cert-hash

    • 获取–discovery-token-ca-cert-hash值,需要有有效的token
    • [root@master1 ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed ‘s/^.* //’
      ffd4c7bf5848c17e8ad975aebf84c8a3ae018eab3497cef8d5cdf04d1e433b7b
  • certificate-key

    • master节点需要额外生成certificate-key,默认有效期2小时
    • [root@master1 ~]# kubeadm init phase upload-certs --upload-certs
      058edf3c985603eeecfa0818583955787c0e51494736ae931226da3445747d5f
  • 生成join命令

    • [root@master1 ~]# kubeadm token create 8sezkh.lx1xz3jodwehsacg --print-join-command
  • worker节点join

    • [root@worker2 ~]# kubeadm join 192.168.10.20:6443 --token 8sezkh.lx1xz3jodwehsacg
      –discovery-token-ca-cert-hash sha256:ffd4c7bf5848c17e8ad975aebf84c8a3ae018eab3497cef8d5cdf04d1e433b7b
  • master节点join

    • [root@master2 ~]# kubeadm join 192.168.10.30:6443 --token 8sezkh.lx1xz3jodwehsacg
      –discovery-token-ca-cert-hash sha256:ffd4c7bf5848c17e8ad975aebf84c8a3ae018eab3497cef8d5cdf04d1e433b7b
      –control-plane --certificate-key 058edf3c985603eeecfa0818583955787c0e51494736ae931226da3445747d5f

集群证书升级

  • 参考

    • https://blog.csdn.net/zhaopeng_yu/article/details/123104509
  • 原因

    • 使用kubeadm安装k8s时,默认生成的client certificate的有效期是1年
  • 查看证书信息

    • [root@master1 ~]# kubeadm certs check-expiration
    • [root@master1 ~]# kubeadm alpha certs check-expiration
  • 解决方法

    • 方案1-升级集群

      • 升级集群的过程中,kubeadm会更新所有的证书
      • https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
    • 方案2-手动更新证书

      • 所有master节点上执行

      • 备份

        • [root@master ~]# tar caf /backup/kubernetes/kubernetes.tar.xz /etc/kubernetes/
          [root@master ~]# tar caf /backup/kubernetes/etcd.tar.xz /var/lib/etcd/
      • 更新证书

        • [root@master ~]# kubeadm alpha certs new all
      • 查看

        • [root@master1 ~]# kubeadm certs check-expiration
      • 重启各组件

        • 重启所有的静态pod,可通过重启kubelet服务实现
      • 更新 kubectl 的 token

        • [root@k8s-master ~]# cp -f /etc/kubernetes/admin.conf ~/.kube/config

kubernetes资源类型

在kubernetes中,提供了很多的资源对象,开发和运维人员可以通过这些对象对容器进行编排

查看当前版本支持的资源类型

  • [root@master1 ~]# kubectl api-resources

常用

  • 名称

    • 缩写

      • NAMESPACED(可被隔离)

        • KIND(资源类别)
  • pods

    • po

      • true

        • Pod
  • nodes

    • no

      • false

        • Node
  • namespaces

    • ns

      • Namespace
  • deployments

    • deploy

      • true

        • Deployment
  • services

    • svc

      • true

        • Service

部署dashboard

功能

  • Kubernetes的Web用户界面

部署

  • kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml
  • kubectl apply -f https://addons.kuboard.cn/metrics-server/0.3.6/metrics-server.yaml

访问

  • http://NodeIP:32567

    • 集群任意节点ip

获取token

  • 超管

    • echo $(kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-user | awk ‘{print $1}’) -o go-template=‘{{.data.token}}’ | base64 -d)
  • 只读

    • echo $(kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-viewer | awk ‘{print $1}’) -o go-template=‘{{.data.token}}’ | base64 -d)

kubectl命令

文档

  • http://docs.kubernetes.org.cn/683.html

语法

  • kubectl [command] [TYPE] [NAME]

command

  • get

    • 显示一个或多个资源
  • apply

    • 通过文件名或标准输入对资源应用配置
    • kubectl apply -f YAML_FILE
  • describe

    • 显示特定资源或一组资源的描述信息
    • events字段显示详细的事件过程,常用于pod排错
    • kubectl describe SOURCE_TYPE SOURCE_NAME
  • logs

    • 打印pod内容器的日志
    • kubectl logs POD_NAME
  • delete

    • 按文件名、标准输入、资源和名称或按资源和标签选择器删除资源
    • kubectl delete -f YAML_FILE
    • kubectl delete SOURCE_TYPE SOURCE_NAME [-n NAMESPACE]
  • create

    • 从文件或stdin创建资源
  • certificate

    • 修改证书资源
  • api-resources

    • 打印支持的api资源
  • api-versions

    • 打印支持的api版本
  • explain

    • 接资源名称查看资源打印

get

  • 语法

    • kubectl get SOURCE_TYPE [SOURCE_NAME ] [options]
  • SOURCE_TYPE

    • 资源类型,如:nodes、pods、namespaces…

    • kubectl get namespace

      • 列出所有namespace
    • kubectl get po -A

      • 列出所有pods
    • kubectl get no

      • 列出所有nodes
  • SOURCE_NAME

    • 具体资源名称,不指定则列出所有
  • 选项

    • -o

      • 指定输出格式,json|yaml|wide|name…

      • -o wide

        • 以ps格式显示更详细的信息(调度的节点)
      • -o yaml

        • 以yaml格式显示详细信息
    • -n NAMESPACE

      • 指定namespace,不指定则默认显示default空间
    • -A

      • 所有namespace

自动补全

  • https://kubernetes.io/zh-cn/docs/tasks/tools/included/optional-kubectl-configs-bash-linux/
  • [root@master ~]# source /usr/share/bash-completion/bash_completion
    [root@master ~]# source <(kubectl completion bash)
    [root@master ~]# echo “source <(kubectl completion bash)” >> ~/.bashrc

kubernetes-yaml文件

介绍

  • Kubernetes 跟 Docker 等很多项目最大的不同,就在于它不推荐你使用命令行的方式直接运行容器

  • 而是希望你用 YAML 文件的方式,即:把资源对象的定义、参数、配置,统统记录在一个 YAML 文件中,然后用’kubectl apply -f 配置文件’指令把它运行起来

  • 好处

    • 便捷性:不必添加大量的参数到命令行中执行命令
    • 可维护性:YAML文件可以通过源头控制,跟踪每次操作
    • 灵活性:AML可以创建比命令行更加复杂的结构

yaml基础

  • 语法规则

    • 大小写敏感
    • 使用缩进表示层级关系
    • 缩进时不建议使用Tab键,只使用空格,(不要混用,移植性差)
    • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
    • “#” 表示注释,从这个字符一直到行尾,都会被解析器忽略
  • 结构类型

    • Maps

      • 字典,即key:value键值对信,如:apiVersion: v1
      • Maps的值既可以是一个字符串,也可以是一个Map,还可以是一个List
    • Lists

      • 列表,类似于数组.如
        args:
      • beijing
      • shanghai
        • 可以指定任何数量的项在列表中,每个项的定义以’-'开头,并且与父元素之间存在缩进
        • 在JSON格式中,表示为
          {
          “args”: [“beijing”, “shanghai”]
          }
        • Lists的子项也可以是Maps

创建pod

  • 介绍

    • 在生产环境中,推荐使用Deployment、StatefulSet、Job、CronJob等控制器来创建 Pod,不推荐直接创建 Pod
    • Pod创建过程中如果出现错误,可以使用kubectl describe 进行排查(events)
    • https://kubernetes.io/docs/reference/kubernetes-api/
  • 编写yaml


apiVersion: v1 #资源版本号,kubectl api-resources查看
kind: Pod #资源类型,kubectl api-resources查看
metadata: #meta信息,比如名称、namespace、标签等信息
name: my-nginx #pod名称
namespace: default #命名空间,不指定默认使用default
labels: #标签
app: nginx
spec: #详细描述
containers: #容器(多个)

  • name: front-end #容器名称
    image: nginx #镜像
    ports:
    • containerPort: 80 #容器端口
      volumeMounts: #volume挂载
    • name: volume #volume卷名称
      mountPath: /usr/share/nginx/html #容器路径
      volumes: #定义volume卷,pod级别资源(pod内所有容器共享)
  • name: volume #volume卷名称
    hostPath: #主机路径
    path: /www

创建deployment

  • 如果Pod出现了故障的话,对应的服务也就挂掉了,因此Kubernetes提供了一个Deployment的概念 ,目的是让Kubernetes去管理一组Pod的副本,也就是副本集 ,这样就能够保证一定数量的副本一直可用

  • 编写yaml

    • apiVersion: apps/v1
      kind: Deployment
      metadata:
      name: ips
      namespace: default
      spec: #pod的详细信息
      selector: #标签选择器,匹配所管理的pod
      mathLabels: #匹配的标签
      app: ips #pod标签
      replicas: 2 #定义副本的数量
      template: #创建pod的模板
      metadata:
      labels:
      app: ips #pod标签
      spec: #容器的详细信息
      containers:
      • name: ips
        image: registry.cn-shenzhen.aliyuncs.com/leedon/nginx-alpine
        ports:
        • containerPort: 80
          protocol: TCP #协议类型,默认TCP

创建service

  • service介绍

    • 简述

      • Service 是对一组提供相同功能的 Pods 的抽象,并为它们提供一个统一的入口
      • 借助 Service,应用可以方便的实现服务发现与负载均衡,并实现应用的零宕机升级
      • Service 通过标签来选取服务后端,一般配合 Replication Controller 或者 Deployment 来保证后端容器的正常运行
      • 这些匹配标签的 Pod IP 和端口列表组成 endpoints,由 kube-proxy 负责将服务 IP 负载均衡到这些 endpoints 上
    • 类型

      • ClusterIP

        • 默认类型,自动分配一个仅 cluster 内部可以访问的虚拟 IP
      • NodePort

        • 在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 NodeIP:NodePort 来访问该服务
        • 如果 kube-proxy 设置了 --nodeport-addresses=10.240.0.0/16(v1.10 支持),那么该 NodePort 仅对设置在范围内的 IP 有效
      • LoadBalancer

        • 在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 :NodePort
      • ExternalName

        • 将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)。需要 kube-dns 版本在 1.7 以上
      • 另外,也可以将已有的服务以 Service 的形式加入到 Kubernetes 集群中来,只需要在创建 Service 的时候不指定 Label selector,而是在 Service 创建好后手动为其添加 endpoint

    • 网络代理模式

      • kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)而非ExternalName的形式,Kubernetes v1.0代理完全在userspace,v1.1新增iptables,v1.2默认iptables代理

      • userspace

        • client先请求serviceip,经由iptables转发到kube-proxy上之后再转发到pod上去。这种方式效率比较低
      • iptables

        • client请求serviceip后会直接转发到pod上。kube-proxy就会负责将pod地址生成在node节点iptables规则中。这种模式性能会高很多
      • ipvs

        • v1.8新增,与iptables模式基本相同, 只是转发通过内核模块ipvs来实现,效率更高
    • 如何工作

      • Service 是由 kube-proxy 组件,加上 iptables(或ipvs) 来共同实现的
      • 创建一个Service,一旦它被提交给 Kubernetes,那么kube-proxy就可以通过 Service的Informer感知到这样一个Service对象的添加。而作为对这个事件的响应,它就会在宿主机上创建这样一条iptables规则
  • 编写yaml

    • apiVersion: v1
      kind: Service
      metadata:
      name: ips #service名称
      spec:
      selector:
      app: ips #pod标签
      type: NodePort #service类型
      ports:
    • name: nginx #service名称
      protocol: TCP
      port: 80 #clusterIP(集群内部通信)访问端口
      targetPort: 80 #容器应用端口
      nodePort: 3001 #nodeIP访问端口,未定义则随机生成30000-32767

API版本

  • 文档

    • k8s v1.20 API

      • https://v1-20.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/
    • 其他版本直接修改版本号即可

  • API 版本

    • 为了使删除字段或者重构资源表示更加容易,Kubernetes 支持 多个API版本。每一个版本都在不同API路径下,例如 /api/v1 或者 /apis/extensions/v1beta1

    • Alpha 测试版本

      • 版本名称包含了 alpha (例如:v1alpha1)
      • 可能是有缺陷的。启用该功能可能会带来隐含的问题,默认情况是关闭的
      • 支持的功能可能在没有通知的情况下随时删除
      • API的更改可能会带来兼容性问题,但是在后续的软件发布中不会有任何通知
      • 由于bugs风险的增加和缺乏长期的支持,推荐在短暂的集群测试中使用
    • Beta 测试版本

      • 版本名称包含了 beta (例如: v2beta3)
      • 代码已经测试过。启用该功能被认为是安全的,功能默认已启用
      • 所有已支持的功能不会被删除,细节可能会发生变化
      • 对象的模式和/或语义可能会在后续的beta测试版或稳定版中以不兼容的方式进行更改。 发生这种情况时,我们将提供迁移到下一个版本的说明。 这可能需要删除、编辑和重新创建API对象。执行编辑操作时需要谨慎行事,这可能需要停用依赖该功能的应用程序
      • 建议仅用于非业务关键型用途,因为后续版本中可能存在不兼容的更改。 如果您有多个可以独立升级的集群,则可以放宽此限制
      • 请尝试我们的 beta 版本功能并且给出反馈!一旦他们退出 beta 测试版,我们可能不会做出更多的改变
    • 稳定版本

      • 版本名称是 vX,其中 X 是整数。
      • 功能的稳定版本将出现在许多后续版本的发行软件中
  • API 组

    • API组在REST路径和序列化对象的 apiVersion 字段中指定
    • 核心组(通常被称为遗留组)位于REST路径 /api/v1 并使用 apiVersion:v1
  • 命令

    • kubectl api-versions

      • 列出当前所支持的所有apiVersion
    • kubectl api-resources

      • 列出当前所有资源信息
    • kubectl explain RESOURCE-NAME

      • 列出指定资源的文档

深入理解k8s

namespace

  • 介绍

    • Namespace是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组
    • 常见的pods, services, replication controllers和deployments等都是属于某一个namespace的(默认是default),而node, persistentVolumes等则不属于任何namespace
    • Namespace常用来隔离不同的项目,比如Kubernetes自带的服务一般运行在kube-system namespace中
    • 在一个 Kubernetes 集群中可以拥有多个命名空间,它们在逻辑上彼此隔离
    • 创建多个命名空间来把服务service分割成更容易管理的块,利于提升服务性能
  • 默认Namespace

    • default

      • 资源创建的默认namespace,不能删除
    • kube-node-lease

    • kube-public

      • 公共资源使用, 不常用
    • kube-system

      • kubernetes系统组件使用
  • namespace操作

    • 查看

      • kubectl get ns
    • 创建

      • kubectl create ns test-ns
      • vim myns.yaml

apiVersion: v1
kind: Namespace
metadata:
name: myns

kubectl apply -f myns.yaml

- 删除

	- kubectl delete ns test-ns
	- kubectl delete -f myns.yaml

权限管理RBAC

  • 介绍

    • RBAC

      • 基于角色的访问控制Role-Based Access Control,Kubernetes项目中负责完成授权(Authorization)工作的机制
    • ABAC

      • 基于属性的访问控制Attribute-based Access Control
    • 区别

      • RBAC引入了 角色(Role) 和 角色绑定(RoleBinding) 的概念
      • 在ABAC中,K8s集群中的访问策略只能跟用户直接关联;而在RBAC中,访问策略可以跟某个角色关联,具体的用户再跟一个或多个角色相关联
      • RBAC 引入了4个新的顶级资源对象:Role 、ClusterRole 、RoleBinding和ClusterRoleBinding
    • RBAC优势

      • 对集群中的资源和非资源权限均有完整的覆盖
      • 整个RBAC完全由几个API对象完成,同其他API对象一样,可以用 kubectl 或API进行操作
      • 可以在运行时进行调整,无须重新启动 API Server
    • 基本概念

      • Role

        • 角色,它其实是一组规则,定义了一组对 Kubernetes API 对象的操作权限
      • Subject

        • 被作用者,既可以是“人”,也可以是“机器”,也可以是你在 Kubernetes 里定义的“用户”
      • RoleBinding

        • 定义了“被作用者”和“角色”的绑定关系
      • 若使用二进制安装k8s集群,要使用 RBAC 授权模式 ,需要在 API Server 的启动 参数中 加上 --authorization-mode=RBAC
  • Role

    • 角色,一个角色包含了一套表示一组权限的规则,权限以累加形式累积(没有”否定”的规则)。Role的权限规则仅在指定的namespace内有效

    • 定义

      • #允许“被作用者”,对default下面的Pod对象,进行get、watch和list操作
        kind: Role
        apiVersion: rbac.authorization.k8s.io/v1
        metadata:
        name: pod-reader #自定义role名字
        namespace: default #指定namespace
        rules: #规则列表
  • apiGroups: [“”] #限定的API组列表,""空表示核心组api/v1
    resources: [“pods”] #限定的资源对象列表,如pods、 deployments等
    verbs: [“get”,“watch”,“list”] #权限列表,这些表示只读权限
    resourceNames: [“xxx”] #指定具体的一个或多个资源

  • RoleBinding

    • 角色绑定,引用在同一namespace内定义的Role对象将权限授予一个或者一组主体subject

    • 定义

      • kind: RoleBinding
        apiVersion: rbac.authorization.k8s.io/v1
        metadata:
        name: read-pods
        namespace: default
        subjects:
  • kind: User #被引用对象的种类:“User”, “Group”, “ServiceAccount”
    name: jane
    apiGroup: rbac.authorization.k8s.io
    roleRef: #只能引用当前 Namespace 里的 Role 对象
    kind: Role
    name: pod-reader #前面定义的pod只读权限
    apiGroup: rbac.authorization.k8s.io

    • RoleBinding对象的作用就是建立roleRef和subject之间的绑定关系,仅限于当前namespace
  • ClusterRole和ClusterRoleBinding

    • 用法跟 Role 和 RoleBinding 完全一样。只不过它们的定义里没有Namespace字段,作用范围为整个集群

    • 授权对象

      • 集群范围资源(例如节点,即node)
      • 非资源类型endpoint(例如”/healthz”)
      • 跨所有命名空间的命名空间范围资源(例如pod)
    • 所有权限

      • get,list,watch,create,update,patch,delete
      • 可用 * 表示
    • 预置ClusterRole

      • cluster-admin

        • 集群超级管理,verbs=*
      • admin

        • 管理
      • edit

        • 读写
      • view

        • 只读
  • ServiceAccount

    • 由 Kubernetes 负责管理的“内置用户”,简写sa

    • 定义sa

      • apiVersion: v1
        kind: ServerAccount
        metadata:
        name: test-sa
        namespace: default
    • secret

      • Kubernetes 会为一个 ServiceAccount 自动创建并分配一个 Secret 对象

      • 这个Secret,就是这个 ServiceAccount 对应的、用来跟 APIServer 进行交互的授权文件,我们一般称它为:Token

      • kubectl describe sa test-sa

        • sa描述信息包含secret
    • tocken

      • Token 文件的内容一般是证书或者密码,它以一个 Secret 对象的方式保存在 Etcd 当中

      • kubectl describe secret test-sa-token-xxxxx

        • secret描述信息包含token
    • pod声明

      • 定义pod时在spec字段加上“serviceAccountName: test-sa”即可声明使用该sa的身份(拥有该sa对应的权限)
      • pod运行时kubernetes会自动将该sa的token挂载到容器的/var/run/secrets/kubernetes.io/serviceaccount目录下
      • 目录中包含ca.crt文件,容器里的应用使用它来访问APIServer
    • default

      • 每个Namespace 下有个名叫 default 的默认 ServiceAccount
      • 如果Pod没有声明serviceAccountName,则默认为default
      • sa default没有关联任何Role,但是它有访问APIServer的绝大多数权限
      • 生产环境中强烈建议为所有namespace下的默认sa绑定一个只读权限的Role

深入理解k8s-pod

pod介绍

  • Pod是Kubernetes中最重要也最基本的概念

  • 每个Pod都有一个特殊的被称为“根容器”的Pause容器。除此之外,每个Pod还包含一到多个紧密相关的用户业务容器

  • 根容器Pause占用内存极少且不易死亡,以它的状态代表整个容器组的状态

  • Pod里的多个业务容器共享 Pause容器的IP, 共享 Pause容器挂载的 Volume

  • 静态Pod

    • 比较特殊, 它并不存放在Kubernetes的etcd存储里, 而是存放在某个具体的Node上的一个具体文件中,并且只在此Node上启动运行
  • 普通Pod

    • 一旦被创建,就会被放入到etcd中存储,随后会被 Kubernetes master调度到某个具体的Node上并进行绑定(Binding),随后该Pod被对应的Node上的 kubelet进程实例化成一组相关的 Docker容器并启动起来。在默认情况下,当Pod里的某个容器停止时Kubernetes会自动检测到这个问题并且重新启动这个Pod(重启Pod里的所有容器),如果Pod所在的Node宕机,则会将这个Node上的所有Pod重新调度到其他节点上

pod详细定义

  • explain命令查询

    • 例如:查询 pods 资源的 spec.containers.imagePullPolicy 的文档
    • kubectl explain pods.spec.containers.imagePullPolicy
  • 文档查询

    • https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/
  • 较完整内容

    • apiVersion: v1 # 必选,版本号,例如v1
      kind: Pod # 必选,Pod
      metadata: # 必选,元数据
      name: string # 必选,Pod名称
      namespace: string # 必选,Pod所属的命名空间,默认default
      labels: # 自定义标签
      fieldName: string
      annotations: # 自定义注解
      fieldName: string
      spec: # 必选,Pod中容器的详细定义
      containers: # 必选,Pod中容器列表
    • name: string # 必选,容器名称
      image: string # 必选,容器的镜像名称
      imagePullPolicy: [Always|Never|IfNotPresent] #镜像版本为latest则默认Always,否则IfNotPresent
      command: [string] # 容器的启动命令列表,如不指定,使用打包时使用的启动命令
      args: [string] # 容器的启动命令参数列表
      workingDir: string # 容器的工作目录
      volumeMounts: # 挂载到容器内部的存储卷配置
      • name: string # 引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
        mountPath: string # 存储卷在容器内mount的绝对路径,应少于512字符
        readOnly: boolean # 是否为只读模式
        ports: # 需要暴露的端口库号列表
      • name: string # 端口号名称
        containerPort: int # 容器需要监听的端口号
        hostPort: int # 容器所在主机需要监听的端口号,默认与Container相同
        protocol: string # 端口协议,支持TCP和UDP,默认TCP
        env: # 容器运行前需设置的环境变量列表
      • name: string # 环境变量名称
        value: string # 环境变量的值
        resources: # 资源限制和请求的设置
        limits: # 资源限制的设置
        cpu: string # Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string # 内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
        requests: # 资源请求的设置
        cpu: string # Cpu请求,容器启动的初始可用数量
        memory: string # 内存清求,容器启动的初始可用数量
        livenessProbe: # 健康检查,检查方法有exec、httpGet和tcpSocket,只需设置其中一种方法即可
        exec: # 对Pod检查方式设置为exec方式
        command: [string] # exec方式需要指定的命令或脚本
        httpGet: # 对Pod健康检查方法设置为HttpGet,需要指定Path、port
        path: string
        port: number
        host: string
        scheme: string
        httpHeaders:
        • name: string
          value: string
          tcpSocket: # 对Pod健康检查方式设置为tcpSocket方式
          port: number
          initialDelaySeconds: 0 # 容器启动完成后首次探测的时间,单位为秒
          timeoutSeconds: 0 # 对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
          periodSeconds: 0 # 对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
          successThreshold: 0
          failureThreshold: 0
          securityContext:
          privileged:false
          restartPolicy: [Always | Never | OnFailure] # 总是重启|不重启|仅以非0退出码退出才重启
          nodeSelector: obeject # 设置NodeSelector表示将该Pod调度到包含这个label的node上
          imagePullSecrets: # Pull镜像时使用的secret名称,以key:secretkey格式指定
      • name: string
        hostNetwork: false # 是否使用主机网络模式,默认为false
        volumes: # 在该pod上定义共享存储卷列表
      • name: string # 共享存储卷名称 (volumes类型有很多种)
        emptyDir: {} # 类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      • name: string
        hostPath: string # 类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string # Pod所在宿主机的目录,将被用于同期中mount的目录
      • name: string
        secret: # 类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        secretName: string
        items:
        • key: string
          path: string
      • name: string
        configMap: # 类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
        name: string
        items:
        • key: string
          path: string

pod原理

  • 问题

    • Pod 是 Kubernetes 项目中最小的 API 对象
    • 容器的本质是进程,容器没有管理多个进程的能力
    • 一些程序往往需要多个进程间协作来完成,进程间可能需要进行网络通信以及文件调用,容器间实现困难
    • 如果以容器为基本调度单位,无法保证这些进程能够运行在同一台机器,如果跨机器实现则更为复杂
  • 解决

    • 将需要协作的多个进程组合成一个进程组,也就是容器组pod,将容器组看组一个整体
    • Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume

你可能感兴趣的:(kubernetes,docker,容器)