Skip to content

Latest commit

 

History

History
1488 lines (1066 loc) · 56.5 KB

微服务容器化实践(二).md

File metadata and controls

1488 lines (1066 loc) · 56.5 KB

微服务容器化实践(二)

Kubernetes基础

Kubernetes介绍

首先,Kubernetes是一个全新的基于容器技术的分布式架构领先方案。Kubernetes是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用,其主要功能如下:

  • 使用Docker对应用程序包装(package)、实例化(instantiate)、运行(run)。
  • 以集群的方式运行、管理跨机器的容器。
  • 解决Docker跨机器容器之间的通讯问题。
  • Kubernetes的自我修复机制使得容器集群总是运行在用户期望的状态。

为什么使用Kubernetes?

如果你曾经用过Docker容器技术部署容器,那么可以将Docker看成Kubernetes内部使用的低级别组件。Kubernetes不仅仅支持Docker,还支持Rocket,这是另一种容器技术。

  • 全面拥抱微服务架构
  • 使用Kubernetes我们系统可以随时的整体迁移
  • Kubernetes系统具备了超强的横向扩容能力
  • Kubernetes提供完善的管理工具,涵盖了包括开发、部署测试、运维监控在内的各个环节。

Kubernetes的核心概念

集群

集群是一组节点,这些节点可以是物理服务器或者虚拟机,之上安装了Kubernetes平台。下图展示这样的集群。注意该图为了强调核心概念有所简化。这里可以看到一个典型的Kubernetes架构图。

上图可以看到如下组件,使用特别的图标表示Service和Label:

  • Pod
  • Container(容器)
  • Replication Controller(复制控制器)
  • Service(服务)
  • Node(节点)
  • Kubernetes Master(Kubernetes主节点)

Kubernetes Master

集群拥有一个Kubernetes Master(紫色方框)。Kubernetes Master提供集群的独特视角,并且拥有一系列组件,比如Kubernetes API Server。API Server提供可以用来和集群交互的REST端点。master节点包括用来创建和复制Pod的Replication Controller。

Pod

Pod(上图绿色方框)安排在节点上,包含一组容器和卷。同一个Pod里的容器共享同一个网络命名空间,可以使用localhost互相通信。Pod是短暂的,不是持续性实体。你可能会有这些问题:

  • 如果Pod是短暂的,那么我怎么才能持久化容器数据使其能够跨重启而存在呢? 是的,Kubernetes支持的概念,因此可以使用持久化的卷类型。
  • 是否手动创建Pod,如果想要创建同一个容器的多份拷贝,需要一个个分别创建出来么?可以手动创建单个Pod,但是也可以使用Replication Controller使用Pod模板创建出多份拷贝,下文会详细介绍。
  • 如果Pod是短暂的,那么重启时IP地址可能会改变,那么怎么才能从前端容器正确可靠地指向后台容器呢?这时可以使用Service,下文会详细介绍。

Lable

正如图所示,一些Pod有Label。一个Label是attach到Pod的一对键/值对,用来传递用户定义的属性。比如,你可能创建了一个"tier"和“app”标签,通过Label(tier=frontend, app=myapp)来标记前端Pod容器,使用Label(tier=backend, app=myapp)标记后台Pod。然后可以使用Selectors选择带有特定Label的Pod,并且将Service或者Replication Controller应用到上面。

Replication Controller

是否手动创建Pod,如果想要创建同一个容器的多份拷贝,需要一个个分别创建出来么,能否将Pods划到逻辑组里?

Replication Controller确保任意时间都有指定数量的Pod“副本”在运行。如果为某个Pod创建了Replication Controller并且指定3个副本,它会创建3个Pod,并且持续监控它们。如果某个Pod不响应,那么Replication Controller会替换它,保持总数为3.如下面的动画所示:

如果之前不响应的Pod恢复了,现在就有4个Pod了,那么Replication Controller会将其中一个终止保持总数为3。如果在运行中将副本总数改为5,Replication Controller会立刻启动2个新Pod,保证总数为5。还可以按照这样的方式缩小Pod,这个特性在执行滚动升级时很有用。

当创建Replication Controller时,需要指定两个东西:

  1. Pod模板:用来创建Pod副本的模板
  2. Label:Replication Controller需要监控的Pod的标签。

现在已经创建了Pod的一些副本,那么在这些副本上如何均衡负载呢?我们需要的是Service。

Service

如果Pods是短暂的,那么重启时IP地址可能会改变,怎么才能从前端容器正确可靠地指向后台容器呢?

Service是定义一系列Pod以及访问这些Pod的策略的一层抽象。Service通过Label找到Pod组。因为Service是抽象的,所以在图表里通常看不到它们的存在,这也就让这一概念更难以理解。

现在,假定有2个后台Pod,并且定义后台Service的名称为‘backend-service’,lable选择器为(tier=backend, app=myapp)。backend-service的Service会完成如下两件重要的事情:

  • 会为Service创建一个本地集群的DNS入口,因此前端Pod只需要DNS查找主机名为 ‘backend-service’,就能够解析出前端应用程序可用的IP地址。
  • 现在前端已经得到了后台服务的IP地址,但是它应该访问2个后台Pod的哪一个呢?Service在这2个后台Pod之间提供透明的负载均衡,会将请求分发给其中的任意一个(如下面的动画所示)。通过每个Node上运行的代理(kube-proxy)完成。这里有更多技术细节。

下述动画展示了Service的功能。注意该图作了很多简化。如果不进入网络配置,那么达到透明的负载均衡目标所涉及的底层网络和路由相对先进。

有一个特别类型的Kubernetes Service,称为'LoadBalancer',作为外部负载均衡器使用,在一定数量的Pod之间均衡流量。比如,对于负载均衡Web流量很有用。

Node

节点(上图橘色方框)是物理或者虚拟机器,作为Kubernetes worker,通常称为Minion。每个节点都运行如下Kubernetes关键组件:

  • Kubelet:是主节点代理。
  • Kube-proxy:Service使用其将链接路由到Pod,如上文所述。
  • Docker或Rocket:Kubernetes使用的容器技术来创建容器。

Kubernetes的体系结构

Kubernetes集群搭建(环境准备)

环境说明

这里准备了三台ubuntu虚拟机,每台4核cpu和4G内存,配置好root账户,并安装好了docker,后续的所有操作都是使用root账户。虚拟机具体信息如下表:

系统类型 IP地址 节点角色 CPU Memory Hostname
ubuntu16.04 192.168.1.101 worker 1 2G server01
ubuntu16.04 192.168.1.102 master 1 2G server02
ubuntu16.04 192.168.1.103 worker 1 2G server03

由于笔记本资源有限,使用openstack虚拟机来进行创建三个节点,其中三台机器的浮动ip为:172.171.5.202/172.171.5.201/172.171.5.203

安装docker(所有节点)

一般情况使用下面的方法安装即可

1 卸载旧版本(如果有的话)

apt-get remove docker docker-engine docker.io

2 更新apt-get源

add-apt-repository  "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

apt-get update #如果失败执行2.3步之后再来执行

3 安装apt的https支持包并添加gpg秘钥

apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -

4 安装docker-ce

  • 安装最新的稳定版
apt-get install -y docker-ce
  • 安装指定版本
#获取版本列表
apt-cache madison docker-ce
 
#指定版本安装(比如版本是17.09.1~ce-0~ubuntu)
apt-get install -y docker-ce=17.09.1~ce-0~ubuntu
  • 接受所有ip的数据包转发
vi /lib/systemd/system/docker.service
   
#找到ExecStart=xxx,在这行上面加入一行,内容如下:(k8s的网络需要)
ExecStartPost=/sbin/iptables -I FORWARD -s 0.0.0.0/0 -j ACCEPT
  • 启动服务
systemctl daemon-reload
service docker start

系统设置(所有节点)

1 关闭、禁用防火墙(让所有机器之间都可以通过任意端口建立连接)

$ ufw disable
#查看状态
$ ufw status

2 设置系统参数 - 允许路由转发,不对bridge的数据进行处理

#写入配置文件
cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
 
#生效配置文件
sysctl -p /etc/sysctl.d/k8s.conf

3 配置host文件

#配置host,使每个Node都可以通过名字解析到ip地址
vi /etc/hosts
#加入如下片段(ip地址和servername替换成自己的)
192.168.1.101 server01
192.168.1.102 server02
192.168.1.103 server03

准备二进制文件(所有节点)

kubernetes的安装有几种方式,不管是kube-admin还是社区贡献的部署方案都离不开这几种方式:

  • 使用现成的二进制文件

直接从官方或其他第三方下载,就是kubernetes各个组件的可执行文件。拿来就可以直接运行了。不管是centos,ubuntu还是其他的linux发行版本,只要gcc编译环境没有太大的区别就可以直接运行的。使用较新的系统一般不会有什么跨平台的问题。

  • 使用源码编译安装

编译结果也是各个组件的二进制文件,所以如果能直接下载到需要的二进制文件基本没有什么编译的必要性了。

  • 使用镜像的方式运行

同样一个功能使用二进制文件提供的服务,也可以选择使用镜像的方式。就像nginx,像mysql,我们可以使用安装版,搞一个可执行文件运行起来,也可以使用它们的镜像运行起来,提供同样的服务。kubernetes也是一样的道理,二进制文件提供的服务镜像也一样可以提供。

从上面的三种方式中其实使用镜像是比较优雅的方案,容器的好处自然不用多说。但从初学者的角度来说容器的方案会显得有些复杂,不那么纯粹,会有很多容器的配置文件以及关于类似二进制文件提供的服务如何在容器中提供的问题,容易跑偏。 所以我们这里使用二进制的方式来部署。二进制文件已经这里备好,大家可以打包下载,把下载好的文件放到每个节点上,放在哪个目录随你喜欢,放好后最好设置一下环境变量$PATH,方便后面可以直接使用命令。(科学上网的同学也可以自己去官网找找)

下载地址(kubernetes 1.9.0版本)

准备配置文件(所有节点)

上一步我们下载了kubernetes各个组件的二进制文件,这些可执行文件的运行也是需要添加很多参数的,包括有的还会依赖一些配置文件。现在我们就把运行它们需要的参数和配置文件都准备好。

1 下载配置文件

#到home目录下载项目
cd /home/openlab
git clone https://github.com/liuyi01/kubernetes-starter.git
#看看git内容
cd /home/openlab/kubernetes-starter && ls

2 文件说明

  • gen-config.sh

shell脚本,用来根据每个同学自己的集群环境(ip,hostname等),根据下面的模板,生成适合大家各自环境的配置文件。生成的文件会放到target文件夹下。

  • kubernetes-simple

简易版kubernetes配置模板(剥离了认证授权)。 适合刚接触kubernetes的同学,首先会让大家在和kubernetes初次见面不会印象太差(太复杂啦~~),再有就是让大家更容易抓住kubernetes的核心部分,把注意力集中到核心组件及组件的联系,从整体上把握kubernetes的运行机制。

  • kubernetes-with-ca

在simple基础上增加认证授权部分。大家可以自行对比生成的配置文件,看看跟simple版的差异,更容易理解认证授权的(认证授权也是kubernetes学习曲线较高的重要原因)

  • service-config

这个先不用关注,它是我们曾经开发的那些微服务配置。 等我们熟悉了kubernetes后,实践用的,通过这些配置,把我们的微服务都运行到kubernetes集群中。

3 生成配置

这里会根据大家各自的环境生成kubernetes部署过程需要的配置文件。 在每个节点上都生成一遍,把所有配置都生成好,后面会根据节点类型去使用相关的配置。

#cd到之前下载的git代码目录
cd /home/openlab/kubernetes-starter
#编辑属性配置(根据文件注释中的说明填写好每个key-value)
vi config.properties
#生成配置文件,确保执行过程没有异常信息
./gen-config.sh simple
#查看生成的配置文件,确保脚本执行成功
find target/ -type f
target/all-node/kube-calico.service
target/master-node/kube-controller-manager.service
target/master-node/kube-apiserver.service
target/master-node/etcd.service
target/master-node/kube-scheduler.service
target/worker-node/kube-proxy.kubeconfig
target/worker-node/kubelet.service
target/worker-node/10-calico.conf
target/worker-node/kubelet.kubeconfig
target/worker-node/kube-proxy.service
target/services/kube-dns.yaml

执行gen-config.sh常见问题:

  1. gen-config.sh: 3: gen-config.sh: Syntax error: "(" unexpected
  • bash版本过低,运行:bash -version查看版本,如果小于4需要升级
  • 不要使用 sh gen-config.sh的方式运行(sh和bash可能不一样哦)
  1. config.properties文件填写错误,需要重新生成 再执行一次./gen-config.sh simple即可,不需要手动删除target

Kubernetes集群搭建(基础功能安装)

部署ETCD(主节点)

简介

kubernetes需要存储很多东西,像它本身的节点信息,组件信息,还有通过kubernetes运行的pod,deployment,service等等。都需要持久化。etcd就是它的数据中心。生产环境中为了保证数据中心的高可用和数据的一致性,一般会部署最少三个节点。我们这里以学习为主就只在主节点部署一个实例。

部署

etcd的二进制文件和服务的配置我们都已经准备好,现在的目的就是把它做成系统服务并启动。

#把服务配置文件copy到系统服务目录
cp /home/openlab/kubernetes-starter/target/master-node/etcd.service /lib/systemd/system/
#enable服务
systemctl enable etcd.service
#创建工作目录(保存数据的地方)
mkdir -p /var/lib/etcd
# 启动服务
service etcd start
# 查看服务日志,看是否有错误信息,确保服务正常
journalctl -f -u etcd.service

etcd.service内容为:

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/home/openlab/bin/etcd \
  --name=192.168.1.102 \
  --listen-client-urls=http://192.168.1.102:2379,http://127.0.0.1:2379 \
  --advertise-client-urls=http://192.168.1.102:2379 \
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

部署APIServer(主节点)

1.简介

kube-apiserver是Kubernetes最重要的核心组件之一,主要提供以下的功能

  • 提供集群管理的REST API接口,包括认证授权(我们现在没有用到)数据校验以及集群状态变更等
  • 提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd)

生产环境为了保证apiserver的高可用一般会部署2+个节点,在上层做一个lb做负载均衡,比如haproxy。由于单节点和多节点在apiserver这一层说来没什么区别,所以我们学习部署一个节点就足够啦

2.部署

APIServer的部署方式也是通过系统服务。部署流程跟etcd完全一样,不再注释

cp target/master-node/kube-apiserver.service /lib/systemd/system/
systemctl enable kube-apiserver.service
service kube-apiserver start
journalctl -f -u kube-apiserver

target/master-node/kube-apiserver.service

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
#可执行文件的位置
ExecStart=/home/openlab/bin/kube-apiserver \
  --admission-control=NamespaceLifecycle,LimitRanger,DefaultStorageClass,ResourceQuota,NodeRestriction \
  #非安全端口(8080)绑定的监听地址 这里表示监听所有地址
  --insecure-bind-address=0.0.0.0 \
  #不使用https
  --kubelet-https=false \
  #kubernetes集群的虚拟ip的地址范围
  --service-cluster-ip-range=10.68.0.0/16 \
  #service的nodeport的端口范围限制
  --service-node-port-range=20000-40000 \
  #很多地方都需要和etcd打交道,也是唯一可以直接操作etcd的模块
  --etcd-servers=http://192.168.1.102:2379 \
  --enable-swagger-ui=true \
  --allow-privileged=true \
  --audit-log-maxage=30 \
  --audit-log-maxbackup=3 \
  --audit-log-maxsize=100 \
  --audit-log-path=/var/lib/audit.log \
  --event-ttl=1h \
  --v=2
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

部署ControllerManager(主节点)

简介

Controller Manager由kube-controller-manager和cloud-controller-manager组成,是Kubernetes的大脑,它通过apiserver监控整个集群的状态,并确保集群处于预期的工作状态。 kube-controller-manager由一系列的控制器组成,像Replication Controller控制副本,Node Controller节点控制,Deployment Controller管理deployment等等 cloud-controller-manager在Kubernetes启用Cloud Provider的时候才需要,用来配合云服务提供商的控制

controller-manager、scheduler和apiserver 三者的功能紧密相关,一般运行在同一个机器上,我们可以把它们当做一个整体来看,所以保证了apiserver的高可用即是保证了三个模块的高可用。也可以同时启动多个controller-manager进程,但只有一个会被选举为leader提供服务。

部署

cp target/master-node/kube-controller-manager.service /lib/systemd/system/
systemctl enable kube-controller-manager.service
service kube-controller-manager start
journalctl -f -u kube-controller-manager

kube-controller-manager.service

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart=/home/openlab/bin/kube-controller-manager \
#对外服务的监听地址,这里表示只有本机的程序可以访问它
  --address=127.0.0.1 \
  #apiserver的url
  --master=http://127.0.0.1:8080 \
  --allocate-node-cidrs=true \
  #服务虚拟ip范围,同apiserver的配置
  --service-cluster-ip-range=10.68.0.0/16 \
  #pod的ip地址范围
  --cluster-cidr=172.20.0.0/16 \
  --cluster-name=kubernetes \
  --leader-elect=true \
  #下面两个表示不使用证书,用空值覆盖默认值
  --cluster-signing-cert-file= \
  --cluster-signing-key-file= \
  --v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

部署Scheduler(主节点)

简介

kube-scheduler负责分配调度Pod到集群内的节点上,它监听kube-apiserver,查询还未分配Node的Pod,然后根据调度策略为这些Pod分配节点。我们前面讲到的kubernetes的各种调度策略就是它实现的。

部署

cp target/master-node/kube-scheduler.service /lib/systemd/system/
systemctl enable kube-scheduler.service
service kube-scheduler start
journalctl -f -u kube-scheduler

kube-scheduler.service

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/home/openlab/bin/kube-scheduler \
#对外服务的监听地址,这里表示只有本机的程序可以访问它
  --address=127.0.0.1 \
  --master=http://127.0.0.1:8080 \
  --leader-elect=true \
  --v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

部署CalicoNode(所有节点)

简介

Calico实现了CNI接口,是kubernetes网络方案的一种选择,它一个纯三层的数据中心网络方案(不需要Overlay),并且与OpenStack、Kubernetes、AWS、GCE等IaaS和容器平台都有良好的集成。 Calico在每一个计算节点利用Linux Kernel实现了一个高效的vRouter来负责数据转发,而每个vRouter通过BGP协议负责把自己上运行的workload的路由信息像整个Calico网络内传播——小规模部署可以直接互联,大规模下可通过指定的BGP route reflector来完成。 这样保证最终所有的workload之间的数据流量都是通过IP路由的方式完成互联的。

部署

calico是通过系统服务+docker方式完成的

cp target/all-node/kube-calico.service /lib/systemd/system/
systemctl enable kube-calico.service
service kube-calico start
journalctl -f -u kube-calico

kube-calico.service

[Unit]
Description=calico node
After=docker.service
Requires=docker.service

[Service]
User=root
PermissionsStartOnly=true
#以docker方式运行
ExecStart=/usr/bin/docker run --net=host --privileged --name=calico-node \
#指定etcd endpoints(这里主要负责网络元数据一致性,确保Calico网络状态的准确性)
  -e ETCD_ENDPOINTS=http://192.168.1.102:2379 \
  -e CALICO_LIBNETWORK_ENABLED=true \
  -e CALICO_NETWORKING_BACKEND=bird \
  -e CALICO_DISABLE_FILE_LOGGING=true \
  #网络地址范围(同上面ControllerManager)
  -e CALICO_IPV4POOL_CIDR=192.1.0.0/16 \
  -e CALICO_IPV4POOL_IPIP=off \
  -e FELIX_DEFAULTENDPOINTTOHOSTACTION=ACCEPT \
  -e FELIX_IPV6SUPPORT=false \
  -e FELIX_LOGSEVERITYSCREEN=info \
  -e FELIX_IPINIPMTU=1440 \
  -e FELIX_HEALTHENABLED=true \
  #镜像名,为了加快大家的下载速度,镜像都放到了阿里云上
  -e IP=192.168.1.102 \
  -v /var/run/calico:/var/run/calico \
  -v /lib/modules:/lib/modules \
  -v /run/docker/plugins:/run/docker/plugins \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/log/calico:/var/log/calico \
  registry.cn-hangzhou.aliyuncs.com/imooc/calico-node:v2.6.2
ExecStop=/usr/bin/docker rm -f calico-node
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

验证

查看容器运行情况

root@k8s-master:/home/openlab/kubernetes-starter# docker ps
CONTAINER ID        IMAGE                                                        COMMAND             CREATED             STATUS              PORTS               NAMES
72f8c6b16ec6        registry.cn-hangzhou.aliyuncs.com/imooc/calico-node:v2.6.2   "start_runit"       43 minutes ago      Up 43 minutes                           calico-node

查看节点运行情况(主节点)

root@k8s-master:/home/openlab/kubernetes-starter# calicoctl node status
Calico process is running.

IPv4 BGP status
+---------------+-------------------+-------+----------+-------------+
| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+---------------+-------------------+-------+----------+-------------+
| 192.168.1.103 | node-to-node mesh | up    | 13:24:30 | Established |
| 192.168.1.101 | node-to-node mesh | up    | 13:24:59 | Established |
+---------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

还可以查看docker日志

docker logs -f 72f8c6b16ec6

查看端口BGP 协议是通过TCP 连接来建立邻居的,因此可以用netstat 命令验证 BGP Peer

root@k8s-master:/home/openlab/kubernetes-starter# netstat -natp|grep ESTABLISHED|grep 179
tcp        0      0 192.168.1.102:33841     192.168.1.103:179       ESTABLISHED 9376/bird       
tcp        0      0 192.168.1.102:59895     192.168.1.101:179       ESTABLISHED 9376/bird    

查看集群ippool情况(主节点)

root@k8s-master:/home/openlab/kubernetes-starter# calicoctl get ipPool -o yaml
- apiVersion: v1
  kind: ipPool
  metadata:
    cidr: 172.20.0.0/16
  spec:
    nat-outgoing: true

配置kubectl命令(任意节点)

简介

kubectl是Kubernetes的命令行工具,是Kubernetes用户和管理员必备的管理工具。 kubectl提供了大量的子命令,方便管理Kubernetes集群中的各种功能。

初始化

使用kubectl的第一步是配置Kubernetes集群以及认证方式,包括:

  • cluster信息:api-server地址
  • 用户信息:用户名、密码或密钥
  • Context:cluster、用户信息以及Namespace的组合

我们这没有安全相关的东西,只需要设置好api-server和上下文就好啦:

#指定apiserver地址(ip替换为你自己的api-server地址)
kubectl config set-cluster kubernetes  --server=http://192.168.1.102:8080
#指定设置上下文,指定cluster
kubectl config set-context kubernetes --cluster=kubernetes
#选择默认的上下文
kubectl config use-context kubernetes

通过上面的设置最终目的是生成了一个配置文件:~/.kube/config,当然你也可以手写或复制一个文件放在那,就不需要上面的命令了。

测试是否成功(获取pod):

root@k8s-master:/home/openlab/kubernetes-starter# kubectl get pods
No resources found

配置kubelet(工作节点)

简介

每个工作节点上都运行一个kubelet服务进程,默认监听10250端口,接收并执行master发来的指令,管理Pod及Pod中的容器。每个kubelet进程会在API Server上注册节点自身信息,定期向master节点汇报节点的资源使用情况,并通过cAdvisor监控节点和容器的资源。

部署

通过系统服务方式部署,但步骤会多一些,具体如下:

#确保相关目录存在
mkdir -p /var/lib/kubelet
mkdir -p /etc/kubernetes
mkdir -p /etc/cni/net.d

#复制kubelet服务配置文件
cp target/worker-node/kubelet.service /lib/systemd/system/
#复制kubelet依赖的配置文件
cp target/worker-node/kubelet.kubeconfig /etc/kubernetes/
#复制kubelet用到的cni插件配置文件
cp target/worker-node/10-calico.conf /etc/cni/net.d/

systemctl enable kubelet.service
service kubelet start
journalctl -f -u kubelet

10-calico.conf

{
    "name": "calico-k8s-network",
    "cniVersion": "0.1.0",
    "type": "calico",
    <!--etcd的url-->
    "etcd_endpoints": "http://192.168.1.102:2379",
    "log_level": "info",
    "ipam": {
        "type": "calico-ipam"
    },
    "kubernetes": {
        <!--api-server的url-->        
        "k8s_api_root": "http://192.168.1.101:8080"
    }
}

kubelet.kubeconfig

apiVersion: v1
clusters:
- cluster:
	#跳过tls,即是kubernetes的认证
    insecure-skip-tls-verify: true
    #api-server地址
    server: http://192.168.1.102:8080
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: ""
  name: system:node:kube-master
current-context: system:node:kube-master
kind: Config
preferences: {}
users: []

kubelet.service

[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service

[Service]
#kubelet工作目录,存储当前节点容器,pod等信息
WorkingDirectory=/var/lib/kubelet
ExecStart= /home/openlab/bin/kubelet \
#对外服务的监听地址
  --address=192.168.1.101 \
  --hostname-override=192.168.1.101 \
  #指定基础容器的镜像,负责创建Pod 内部共享的网络、文件系统等,这个基础容器非常重要:K8S每一个运行的 POD里面必然包含这个基础容器,如果它没有运行起来那么你的POD 肯定创建不了
  --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/imooc/pause-amd64:3.0 \
  #访问集群方式的配置,如api-server地址等
  --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
  #声明cni网络插件
  --network-plugin=cni \
  #cni网络配置目录,kubelet会读取该目录下得网络配置
  --cni-conf-dir=/etc/cni/net.d \
  --cni-bin-dir= /root/bin \
  #指定 kubedns 的 Service IP(可以先分配,后续创建 kubedns 服务时指定该 IP),--cluster-domain 指定域名后缀,这两个参数同时指定后才会生效
  --cluster-dns=10.68.0.2 \
  --cluster-domain=cluster.local. \
  --allow-privileged=true \
  --fail-swap-on=false \
  --logtostderr=true \
  --v=2
#kubelet cAdvisor 默认在所有接口监听 4194 端口的请求, 以下iptables限制内网访问
ExecStartPost=/sbin/iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -s 172.16.0.0/12 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -s 192.168.0.0/16 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -p tcp --dport 4194 -j DROP
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

验证

root@k8s-master:/home/openlab/kubernetes-starter# kubectl get nodes
NAME            STATUS    ROLES     AGE       VERSION
192.168.1.101   Ready     <none>    9m        v1.9.0
192.168.1.103   Ready     <none>    16m       v1.9.0

基础集群测试

查看kubectl客户端和服务端版本:

root@k8s-master:/home/openlab/kubernetes-starter# kubectl version
Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.0", GitCommit:"925c127ec6b946659ad0fd596fa959be43f0cc05", GitTreeState:"clean", BuildDate:"2017-12-15T21:07:38Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.0", GitCommit:"925c127ec6b946659ad0fd596fa959be43f0cc05", GitTreeState:"clean", BuildDate:"2017-12-15T20:55:30Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}

获取节点信息和pods:

root@k8s-master:/home/openlab/kubernetes-starter# kubectl get nodes
NAME            STATUS    ROLES     AGE       VERSION
192.168.1.101   Ready     <none>    14m       v1.9.0
192.168.1.103   Ready     <none>    21m       v1.9.0
root@k8s-master:/home/openlab/kubernetes-starter# kubectl get pods
No resources found.
root@k8s-master:/home/openlab/kubernetes-starter# kubectl get --help

创建一个deployment

#创建deployment
root@k8s-master:/home/openlab/kubernetes-starter# kubectl run kubernetes-bootcamp --image=jocatalin/kubernetes-bootcamp:v1 --port=8080
deployment "kubernetes-bootcamp" created

#查看deployment
root@k8s-master:/home/openlab/kubernetes-starter#  kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            0           57s

#查看pods
root@k8s-master:/home/openlab/kubernetes-starter# kubectl get pods
NAME                                   READY     STATUS              RESTARTS   AGE
kubernetes-bootcamp-6b7849c495-mvmbm   0/1       ContainerCreating   0          2m

#查看pods详细信息
root@k8s-master:/home/openlab/kubernetes-starter# kubectl get pods -o wide
NAME                                   READY     STATUS              RESTARTS   AGE       IP        NODE
kubernetes-bootcamp-6b7849c495-mvmbm   0/1       ContainerCreating   0          2m        <none>    192.168.1.103

Kubernetes集群搭建(完整)

理解认证授权

1.为什么要认证

想理解认证,我们得从认证解决什么问题、防止什么问题的发生入手。 防止什么问题呢?是防止有人入侵你的集群,root你的机器后让我们集群依然安全吗?不是吧,root都到手了,那就为所欲为,防不胜防了。 其实网络安全本身就是为了解决在某些假设成立的条件下如何防范的问题。比如一个非常重要的假设就是两个节点或者ip之间的通讯网络是不可信任的,可能会被第三方窃取,也可能会被第三方篡改。就像我们上学时候给心仪的女孩传纸条,传送的过程可能会被别的同学偷看,甚至内容可能会从我喜欢你修改成我不喜欢你了。当然这种假设不是随便想出来的,而是从网络技术现状和实际发生的问题中发现、总结出来的。kubernetes的认证也是从这个问题出发来实现的。

2.概念梳理

为了解决上面说的问题,kubernetes并不需要自己想办法,毕竟是网络安全层面的问题,是每个服务都会遇到的问题,业内也有成熟的方案来解决。这里我们一起了解一下业内方案和相关的概念。

3.什么是授权

授权的概念就简单多了,就是什么人具有什么样的权限,一般通过角色作为纽带把他们组合在一起。也就是一个角色一边拥有多种权限,一边拥有多个人。这样就把人和权限建立了一个关系。

kubernetes的认证授权

Kubernetes集群的所有操作基本上都是通过kube-apiserver这个组件进行的,它提供HTTP RESTful形式的API供集群内外客户端调用。需要注意的是:认证授权过程只存在HTTPS形式的API中。也就是说,如果客户端使用HTTP连接到kube-apiserver,那么是不会进行认证授权的。所以说,可以这么设置,在集群内部组件间通信使用HTTP,集群外部就使用HTTPS,这样既增加了安全性,也不至于太复杂。 对APIServer的访问要经过的三个步骤,前面两个是认证和授权,第三个是 Admission Control,它也能在一定程度上提高安全性,不过更多是资源管理方面的作用。

1.kubernetes的认证

kubernetes提供了多种认证方式,比如客户端证书、静态token、静态密码文件、ServiceAccountTokens等等。你可以同时使用一种或多种认证方式。只要通过任何一个都被认作是认证通过。下面我们就认识几个常见的认证方式。

  • 客户端证书认证 客户端证书认证叫作TLS双向认证,也就是服务器客户端互相验证证书的正确性,在都正确的情况下协调通信加密方案。 为了使用这个方案,api-server需要用--client-ca-file选项来开启。
  • 引导Token 当我们有非常多的node节点时,手动为每个node节点配置TLS认证比较麻烦,这时就可以用到引导token的认证方式,前提是需要在api-server开启 experimental-bootstrap-token-auth 特性,客户端的token信息与预先定义的token匹配认证通过后,自动为node颁发证书。当然引导token是一种机制,可以用到各种场景中。
  • Service Account Tokens 认证 有些情况下,我们希望在pod内部访问api-server,获取集群的信息,甚至对集群进行改动。针对这种情况,kubernetes提供了一种特殊的认证方式:Service Account。 Service Account 和 pod、service、deployment 一样是 kubernetes 集群中的一种资源,用户也可以创建自己的 Service Account。 ServiceAccount 主要包含了三个内容:namespace、Token 和 CA。namespace 指定了 pod 所在的 namespace,CA 用于验证 apiserver 的证书,token 用作身份验证。它们都通过 mount 的方式保存在 pod 的文件系统中。

2.kubernetes的授权

在Kubernetes1.6版本中新增角色访问控制机制(Role-Based Access,RBAC)让集群管理员可以针对特定使用者或服务账号的角色,进行更精确的资源访问控制。在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。 目前 Kubernetes 中有一系列的鉴权机制,因为Kubernetes社区的投入和偏好,相对于其它鉴权机制而言,RBAC是更好的选择。具体RBAC是如何体现在kubernetes系统中的我们会在后面的部署中逐步的深入了解。

3.kubernetes的AdmissionControl

AdmissionControl - 准入控制本质上为一段准入代码,在对kubernetes api的请求过程中,顺序为:先经过认证 & 授权,然后执行准入操作,最后对目标对象进行操作。这个准入代码在api-server中,而且必须被编译到二进制文件中才能被执行。 在对集群进行请求时,每个准入控制代码都按照一定顺序执行。如果有一个准入控制拒绝了此次请求,那么整个请求的结果将会立即返回,并提示用户相应的error信息。 常用组件(控制代码)如下:

  • AlwaysAdmit:允许所有请求
  • AlwaysDeny:禁止所有请求,多用于测试环境
  • ServiceAccount:它将serviceAccounts实现了自动化,它会辅助serviceAccount做一些事情,比如如果pod没有serviceAccount属性,它会自动添加一个default,并确保pod的serviceAccount始终存在
  • LimitRanger:他会观察所有的请求,确保没有违反已经定义好的约束条件,这些条件定义在namespace中LimitRange对象中。如果在kubernetes中使用LimitRange对象,则必须使用这个插件。
  • NamespaceExists:它会观察所有的请求,如果请求尝试创建一个不存在的namespace,则这个请求被拒绝。

环境准备

1.停止原有kubernetes相关服务

开始之前我们要先把基础版本的集群停掉,包括service,deployments,pods以及运行的所有kubernetes组件

#删除services
$ kubectl delete services nginx-service

#删除deployments
$ kubectl delete deploy kubernetes-bootcamp
$ kubectl delete deploy nginx-deployment

#停掉worker节点的服务
$ service kubelet stop && rm -fr /var/lib/kubelet/*
$ service kube-proxy stop && rm -fr /var/lib/kube-proxy/*
$ service kube-calico stop

#停掉master节点的服务
$ service kube-calico stop
$ service kube-scheduler stop
$ service kube-controller-manager stop
$ service kube-apiserver stop
$ service etcd stop && rm -fr /var/lib/etcd/*

2.生成配置(所有节点)

跟基础环境搭建一样,我们需要生成kubernetes-with-ca的所有相关配置文件

$ cd ~/kubernetes-starter
#按照配置文件的提示编辑好配置
$ vi config.properties
#生成配置
$ ./gen-config.sh with-ca

3.安装cfssl(所有节点)

cfssl是非常好用的CA工具,我们用它来生成证书和秘钥文件 安装过程比较简单,如下:

#下载
$ wget -q --show-progress --https-only --timestamping \
  https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \
  https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
#修改为可执行权限
$ chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
#移动到bin目录
$ mv cfssl_linux-amd64 /usr/local/bin/cfssl
$ mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
#验证
$ cfssl version

4.生成根证书(主节点)

根证书是证书信任链的根,各个组件通讯的前提是有一份大家都信任的证书(根证书),每个人使用的证书都是由这个根证书签发的。

#所有证书相关的东西都放在这
$ mkdir -p /etc/kubernetes/ca
#准备生成证书的配置文件
$ cp ~/kubernetes-starter/target/ca/ca-config.json /etc/kubernetes/ca
$ cp ~/kubernetes-starter/target/ca/ca-csr.json /etc/kubernetes/ca
#生成证书和秘钥
$ cd /etc/kubernetes/ca
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
#生成完成后会有以下文件(我们最终想要的就是ca-key.pem和ca.pem,一个秘钥,一个证书)
$ ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem

改造etcd

1.准备证书

etcd节点需要提供给其他服务访问,就要验证其他服务的身份,所以需要一个标识自己监听服务的server证书,当有多个etcd节点的时候也需要client证书与etcd集群其他节点交互,当然也可以client和server使用同一个证书因为它们本质上没有区别。

#etcd证书放在这
$ mkdir -p /etc/kubernetes/ca/etcd
#准备etcd证书配置
$ cp ~/kubernetes-starter/target/ca/etcd/etcd-csr.json /etc/kubernetes/ca/etcd/
$ cd /etc/kubernetes/ca/etcd/
#使用根证书(ca.pem)签发etcd证书
$ cfssl gencert \
        -ca=/etc/kubernetes/ca/ca.pem \
        -ca-key=/etc/kubernetes/ca/ca-key.pem \
        -config=/etc/kubernetes/ca/ca-config.json \
        -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
#跟之前类似生成三个文件etcd.csr是个中间证书请求文件,我们最终要的是etcd-key.pem和etcd.pem
$ ls
etcd.csr  etcd-csr.json  etcd-key.pem  etcd.pem

2.改造etcd服务

建议大家先比较一下增加认证的etcd配置与原有配置的区别,做到心中有数。 可以使用命令比较:

$ cd ~/kubernetes-starter/
$ vimdiff kubernetes-simple/master-node/etcd.service kubernetes-with-ca/master-node/etcd.service

更新etcd服务:

$ cp ~/kubernetes-starter/target/master-node/etcd.service /lib/systemd/system/
$ systemctl daemon-reload
$ service etcd start
#验证etcd服务(endpoints自行替换)
$ ETCDCTL_API=3 etcdctl \
  --endpoints=https://192.168.1.102:2379  \
  --cacert=/etc/kubernetes/ca/ca.pem \
  --cert=/etc/kubernetes/ca/etcd/etcd.pem \
  --key=/etc/kubernetes/ca/etcd/etcd-key.pem \
  endpoint health

改造api-server

1.准备证书

#api-server证书放在这,api-server是核心,文件夹叫kubernetes吧,如果想叫apiserver也可以,不过相关的地方都需要修改哦
$ mkdir -p /etc/kubernetes/ca/kubernetes
#准备apiserver证书配置
$ cp ~/kubernetes-starter/target/ca/kubernetes/kubernetes-csr.json /etc/kubernetes/ca/kubernetes/
$ cd /etc/kubernetes/ca/kubernetes/
#使用根证书(ca.pem)签发kubernetes证书
$ cfssl gencert \
        -ca=/etc/kubernetes/ca/ca.pem \
        -ca-key=/etc/kubernetes/ca/ca-key.pem \
        -config=/etc/kubernetes/ca/ca-config.json \
        -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
#跟之前类似生成三个文件kubernetes.csr是个中间证书请求文件,我们最终要的是kubernetes-key.pem和kubernetes.pem
$ ls
kubernetes.csr  kubernetes-csr.json  kubernetes-key.pem  kubernetes.pem

2.改造api-server服务

查看diff

$ cd ~/kubernetes-starter
$ vimdiff kubernetes-simple/master-node/kube-apiserver.service kubernetes-with-ca/master-node/kube-apiserver.service

生成token认证文件

#生成随机token
$ head -c 16 /dev/urandom | od -An -t x | tr -d ' '
8afdf3c4eb7c74018452423c29433609

#按照固定格式写入token.csv,注意替换token内容
$ echo "8afdf3c4eb7c74018452423c29433609,kubelet-bootstrap,10001,\"system:kubelet-bootstrap\"" > /etc/kubernetes/ca/kubernetes/token.csv

更新api-server服务

$ cp ~/kubernetes-starter/target/master-node/kube-apiserver.service /lib/systemd/system/
$ systemctl daemon-reload
$ service kube-apiserver start

#检查日志
$ journalctl -f -u kube-apiserver

改造controller-manager

controller-manager一般与api-server在同一台机器上,所以可以使用非安全端口与api-server通讯,不需要生成证书和私钥。

1.改造controller-manager服务

查看diff

$ cd ~/kubernetes-starter/
$ vimdiff kubernetes-simple/master-node/kube-controller-manager.service kubernetes-with-ca/master-node/kube-controller-manager.service

更新controller-manager服务

$ cp ~/kubernetes-starter/target/master-node/kube-controller-manager.service /lib/systemd/system/
$ systemctl daemon-reload
$ service kube-controller-manager start

#检查日志
$ journalctl -f -u kube-controller-manager

改造scheduler

scheduler一般与apiserver在同一台机器上,所以可以使用非安全端口与apiserver通讯。不需要生成证书和私钥。

1.改造scheduler服务

查看diff 比较会发现两个文件并没有区别,不需要改造

$ cd ~/kubernetes-starter/
$ vimdiff kubernetes-simple/master-node/kube-scheduler.service kubernetes-with-ca/master-node/kube-scheduler.service

启动服务

$ service kube-scheduler start
#检查日志
$ journalctl -f -u kube-scheduler

改造kubectl

1.准备证书

#kubectl证书放在这,由于kubectl相当于系统管理员,我们使用admin命名
$ mkdir -p /etc/kubernetes/ca/admin
#准备admin证书配置 - kubectl只需客户端证书,因此证书请求中 hosts 字段可以为空
$ cp ~/kubernetes-starter/target/ca/admin/admin-csr.json /etc/kubernetes/ca/admin/
$ cd /etc/kubernetes/ca/admin/
#使用根证书(ca.pem)签发admin证书
$ cfssl gencert \
        -ca=/etc/kubernetes/ca/ca.pem \
        -ca-key=/etc/kubernetes/ca/ca-key.pem \
        -config=/etc/kubernetes/ca/ca-config.json \
        -profile=kubernetes admin-csr.json | cfssljson -bare admin
#我们最终要的是admin-key.pem和admin.pem
$ ls
admin.csr  admin-csr.json  admin-key.pem  admin.pem

2.配置kubectl

#指定apiserver的地址和证书位置(ip自行修改)
$ kubectl config set-cluster kubernetes \
        --certificate-authority=/etc/kubernetes/ca/ca.pem \
        --embed-certs=true \
        --server=https://192.168.1.102:6443
#设置客户端认证参数,指定admin证书和秘钥
$ kubectl config set-credentials admin \
        --client-certificate=/etc/kubernetes/ca/admin/admin.pem \
        --embed-certs=true \
        --client-key=/etc/kubernetes/ca/admin/admin-key.pem
#关联用户和集群
$ kubectl config set-context kubernetes \
        --cluster=kubernetes --user=admin
#设置当前上下文
$ kubectl config use-context kubernetes

#设置结果就是一个配置文件,可以看看内容
$ cat ~/.kube/config

验证master节点

#可以使用刚配置好的kubectl查看一下组件状态
$ kubectl get componentstatus
NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health": "true"}

改造calico-node

1.准备证书

后续可以看到calico证书用在四个地方:

  • calico/node 这个docker 容器运行时访问 etcd 使用证书
  • cni 配置文件中,cni 插件需要访问 etcd 使用证书
  • calicoctl 操作集群网络时访问 etcd 使用证书
  • calico/kube-controllers 同步集群网络策略时访问 etcd 使用证书
#calico证书放在这
$ mkdir -p /etc/kubernetes/ca/calico
#准备calico证书配置 - calico只需客户端证书,因此证书请求中 hosts 字段可以为空
$ cp ~/kubernetes-starter/target/ca/calico/calico-csr.json /etc/kubernetes/ca/calico/
$ cd /etc/kubernetes/ca/calico/
#使用根证书(ca.pem)签发calico证书
$ cfssl gencert \
        -ca=/etc/kubernetes/ca/ca.pem \
        -ca-key=/etc/kubernetes/ca/ca-key.pem \
        -config=/etc/kubernetes/ca/ca-config.json \
        -profile=kubernetes calico-csr.json | cfssljson -bare calico
#我们最终要的是calico-key.pem和calico.pem
$ ls
calico.csr  calico-csr.json  calico-key.pem  calico.pem

2.改造calico服务

查看diff

$ cd ~/kubernetes-starter
$ vimdiff kubernetes-simple/all-node/kube-calico.service kubernetes-with-ca/all-node/kube-calico.service

通过diff会发现,calico多了几个认证相关的文件: /etc/kubernetes/ca/ca.pem /etc/kubernetes/ca/calico/calico.pem /etc/kubernetes/ca/calico/calico-key.pem 由于calico服务是所有节点都需要启动的,大家需要把这几个文件拷贝到每台服务器上

更新calico服务

$ cp ~/kubernetes-starter/target/all-node/kube-calico.service /lib/systemd/system/
$ systemctl daemon-reload
$ service kube-calico start

#验证calico(能看到其他节点的列表就对啦)
$ calicoctl node status

改造kubelet

我们这里让kubelet使用引导token的方式认证,所以认证方式跟之前的组件不同,它的证书不是手动生成,而是由工作节点TLS BootStrap 向api-server请求,由主节点的controller-manager 自动签发。

1.创建角色绑定(主节点)

引导token的方式要求客户端向api-server发起请求时告诉他你的用户名和token,并且这个用户是具有一个特定的角色:system:node-bootstrapper,所以需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予这个特定角色,然后 kubelet 才有权限发起创建认证请求。 在主节点执行下面命令

#可以通过下面命令查询clusterrole列表
$ kubectl -n kube-system get clusterrole

#可以回顾一下token文件的内容
$ cat /etc/kubernetes/ca/kubernetes/token.csv
8afdf3c4eb7c74018452423c29433609,kubelet-bootstrap,10001,"system:kubelet-bootstrap"

#创建角色绑定(将用户kubelet-bootstrap与角色system:node-bootstrapper绑定)
$ kubectl create clusterrolebinding kubelet-bootstrap \
         --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

2.创建bootstrap.kubeconfig(工作节点)

这个配置是用来完成bootstrap token认证的,保存了像用户,token等重要的认证信息,这个文件可以借助kubectl命令生成:(也可以自己写配置)

#设置集群参数(注意替换ip)
$ kubectl config set-cluster kubernetes \
        --certificate-authority=/etc/kubernetes/ca/ca.pem \
        --embed-certs=true \
        --server=https://192.168.1.102:6443 \
        --kubeconfig=bootstrap.kubeconfig
#设置客户端认证参数(注意替换token)
$ kubectl config set-credentials kubelet-bootstrap \
        --token=8afdf3c4eb7c74018452423c29433609 \
        --kubeconfig=bootstrap.kubeconfig
#设置上下文
$ kubectl config set-context default \
        --cluster=kubernetes \
        --user=kubelet-bootstrap \
        --kubeconfig=bootstrap.kubeconfig
#选择上下文
$ kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
#将刚生成的文件移动到合适的位置
$ mv bootstrap.kubeconfig /etc/kubernetes/

3.准备cni配置

查看diff

$ cd ~/kubernetes-starter
$ vimdiff kubernetes-simple/worker-node/10-calico.conf kubernetes-with-ca/worker-node/10-calico.conf

copy配置

$ cp ~/kubernetes-starter/target/worker-node/10-calico.conf /etc/cni/net.d/

4.改造kubelet服务

查看diff

$ cd ~/kubernetes-starter
$ vimdiff kubernetes-simple/worker-node/kubelet.service kubernetes-with-ca/worker-node/kubelet.service

更新服务

$ cp ~/kubernetes-starter/target/worker-node/kubelet.service /lib/systemd/system/
$ systemctl daemon-reload
$ service kubelet start

#启动kubelet之后到master节点允许worker加入(批准worker的tls证书请求)
#--------*在主节点执行*---------
$ kubectl get csr|grep 'Pending' | awk '{print $1}'| xargs kubectl certificate approve
#-----------------------------

#检查日志
$ journalctl -f -u kubelet

改造kube-proxy

1.准备证书

#proxy证书放在这
$ mkdir -p /etc/kubernetes/ca/kube-proxy

#准备proxy证书配置 - proxy只需客户端证书,因此证书请求中 hosts 字段可以为空。
#CN 指定该证书的 User 为 system:kube-proxy,预定义的 ClusterRoleBinding system:node-proxy 将User system:kube-proxy 与 Role system:node-proxier 绑定,授予了调用 kube-api-server proxy的相关 API 的权限
$ cp ~/kubernetes-starter/target/ca/kube-proxy/kube-proxy-csr.json /etc/kubernetes/ca/kube-proxy/
$ cd /etc/kubernetes/ca/kube-proxy/

#使用根证书(ca.pem)签发calico证书
$ cfssl gencert \
        -ca=/etc/kubernetes/ca/ca.pem \
        -ca-key=/etc/kubernetes/ca/ca-key.pem \
        -config=/etc/kubernetes/ca/ca-config.json \
        -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
#我们最终要的是kube-proxy-key.pem和kube-proxy.pem
$ ls
kube-proxy.csr  kube-proxy-csr.json  kube-proxy-key.pem  kube-proxy.pem

2.生成kube-proxy.kubeconfig配置

#设置集群参数(注意替换ip)
$ kubectl config set-cluster kubernetes \
        --certificate-authority=/etc/kubernetes/ca/ca.pem \
        --embed-certs=true \
        --server=https://192.168.1.102:6443 \
        --kubeconfig=kube-proxy.kubeconfig
#置客户端认证参数
$ kubectl config set-credentials kube-proxy \
        --client-certificate=/etc/kubernetes/ca/kube-proxy/kube-proxy.pem \
        --client-key=/etc/kubernetes/ca/kube-proxy/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
#移动到合适位置
$ mv kube-proxy.kubeconfig /etc/kubernetes/kube-proxy.kubeconfig

3.改造kube-proxy服务

查看diff

$ cd ~/kubernetes-starter
$ vimdiff kubernetes-simple/worker-node/kube-proxy.service kubernetes-with-ca/worker-node/kube-proxy.service

经过diff你应该发现kube-proxy.service没有变化

启动服务

#如果之前的配置没有了,可以重新复制一份过去
$ cp ~/kubernetes-starter/target/worker-node/kube-proxy.service /lib/systemd/system/
$ systemctl daemon-reload

#安装依赖软件
$ apt install conntrack

#启动服务
$ service kube-proxy start
#查看日志
$ journalctl -f -u kube-proxy

改造kube-dns

kube-dns有些特别,因为它本身是运行在kubernetes集群中,以kubernetes应用的形式运行。所以它的认证授权方式跟之前的组件都不一样。它需要用到service account认证和RBAC授权。 service account认证: 每个service account都会自动生成自己的secret,用于包含一个ca,token和secret,用于跟api-server认证 RBAC授权: 权限、角色和角色绑定都是kubernetes自动创建好的。我们只需要创建一个叫做kube-dns的 ServiceAccount即可,官方现有的配置已经把它包含进去了。

1.准备配置文件

我们在官方的基础上添加的变量,生成适合我们集群的配置。直接copy就可以啦

$ cd ~/kubernetes-starter
$ vimdiff kubernetes-simple/services/kube-dns.yaml kubernetes-with-ca/services/kube-dns.yaml

大家可以看到diff只有一处,新的配置没有设定api-server。不访问api-server,它是怎么知道每个服务的cluster ip和pod的endpoints的呢?这就是因为kubernetes在启动每个服务service的时候会以环境变量的方式把所有服务的ip,端口等信息注入进来。

2.创建kube-dns

$ kubectl create -f ~/kubernetes-starter/target/services/kube-dns.yaml
#看看启动是否成功
$ kubectl -n kube-system get pods

kubernetes集群部署微服务

1. 微服务部署方案 - 思路整理

我们有如下微服务:
  • 消息服务:message-service
  • 课程dubbo服务:course-dubbo-service
  • 课程web服务:course-edge-service
  • 用户thrift服务:user-thrift-service
  • 用户web服务:user-edge-service
  • API网关:api-gateway
把它们放到kubernetes集群运行我们要考虑什么问题?
  • 哪些服务适合单独成为一个pod?哪些服务适合在一个pod中?
  • 在一个pod里面的服务如何彼此访问?他们的服务如何对外提供服务?
  • 单独的pod如何对外提供服务?
  • 哪个服务作为整个服务的入口,入口服务如何对外提供服务?

2. 搞定配置

配置的模板已经为大家准备好了,但是还需要大家做一下处理才能使用哦,参考下面脚本:

$ cd ~/kubernetes-starter/service-config/
$ ls
api-gateway.yaml     message-service.yaml
course-service.yaml  user-service.yaml
#替换变量 - (hub.mooc.com:8080是我的环境的镜像仓库地址,大家修改为各自的仓库)
$ sed -i 's/{{HUB}}/hub.mooc.com:8080/g' *

3. 部署服务

部署前准备:
  • 要过一遍我们现有的代码配置,看看是否有需要修改的,修改后需要新生成镜像
  • 要启动好微服务依赖的服务,像zookeeper,mysql,registry等