k8s二进制方式安装
- 基础知识
- 基本概念
- 组成
- 集群中的网络设计
- 部署准备工作
- 部署须知
- 部署流程
- 使用cfssl签发ssl证书
- harbor搭建私有镜像服务器
- 开始部署
- 部署etcd服务(版本3.1)
- api-server启动
- controller-manager启动
- scheduler启动
- kuberlet部署
- kube-proxy部署
- 资源控制清单
- FLANNEL(CNI网络插件)
- 服务发现Coredns
- 服务暴露Ingress
- dashboard资源管理插件-仪表盘
- rbac(k8s中的鉴权机制)
- 平滑升级集群
- 共享存储
- 其他tips
基础知识
基本概念
名词 | 含义 | 解释 |
pod | 一个宿主机中可以有多个pod(豌豆荚)是k8s中最小的运行单元,都会被分配一个ip;类似为一个docker中的一个容器 | |
pod控制器 | 监控pod的运行,其下可以运行多个 pod;如果其下的pod被删除,pod控制器会重新启动一个新的;两种kind,daemon set、deployments、 | |
name | 资源名称 | k8s中所有的所有功能被称为资源:资源的配置信息有:api版本(apiVersion)类别(kind),元数据(metadata),定义清单(spec),状态(status)等;而资源名称就在metadata中存储;同一名称空间下的资源名称唯一;k8s中一切皆资源 |
namespace | 名称空间 | 为了隔离k8s中的各种资源;将k8s内部的资源划分为虚拟集群组;默认的名称有default、kube-system、kube-public;查询k8s中特定的资源需要带上相应的名称空间 |
Label | 标签 | 资源和标签多对多关系;定义标签:key=value |
标签过滤器 | 过滤选择带有特定标签的资源 | 过滤方式有:等于、不等于、属于、不属于、存在 |
Service | 一组提供相同服务的pod对外提供的接口;仅提供流量调度 | 用于解决pod销毁,ip消失的问题;Request----->Ingress---->Service---->pod |
Ingress | OSI第七层的应用,对外暴露接口 | 调度不同业务域,不同URL访问路径的流量 |
secret资源 | 秘钥资源 | 分为3种,generate(通用,token)、docker_register(自定义json格式)、TLS |
组成
名词 | 含义 | 解释 |
配置存储中心 | etcd服务 | 存储集群中各个节点的元数据信息;类似一个非关系型数据库 |
master | 主控节点(一个宿主机) | 1. kebu-apiserver 2. kebu-controller-manager 3.kube-scheduler |
kebu-apiserver | k8s大脑 | 1. 提供了集群管理的REST-API接口(包括鉴权、数据校验和集群状态变更)2. 负责其他模块数据的交互,提供数据枢纽的功能; 3. 资源配额控制的入口 4.提供完备的资源安全机制 |
kebu-controller-manager | 控制及管理器 | 由一系列的控制器组成;通过apiserver来控制整个集群的状态并确保集群出于预期的状态下 |
kube-scheduler | 资源调度器 | 接受指令并调度pod到合适的节点上;预选策略和优选策略 |
node | 运算节点(一个宿主机) | 主要包括kube-let、kube-proxy |
kube-let | 节点大脑 | 1. 定时从某个地方获取pod的运行状态(那个容器、副本数、网络、存储配置等等)调用对应的容器平台接口到达这个状态;2. 定时汇报当前pod的状态给apiserver,以方便后续的调度 3. 定时清理容器和镜像资源,保证推出的容器不会占用太多资源 |
kebu-proxy | 每个节点上的网络代理;维护了一套虚拟集群网络 | 1. 建立了集群网络和pod网络的关系;三种流量调度模式,推荐使用ipvs(基于LVS) 2. 依据kebu-apiserver建立更新删除调度规则,并通知kebu-apiserver自己的变更 |
LVS | 内网映射到外网的一种方式 | 网络拓扑 客户端请求 -->vip服务–负载均衡–>真实服务器–>响应数据–直接–>客户端;优点:请求经过vip服务,响应直接返回给客户端,避免vip服务成为网络瓶颈 |
集群中的网络设计
网络 | 含义 | 解释 |
10.4.7.21 | 节点网络 | 其中4为哪个机房,7为哪个项目的测试项或正式线 |
172.7.21.0/24 | pod网络 | 172打头,7.21继承宿主机的ip。方便排查问题 |
192.168.0.0 | Service网络 | 通过kebu-proxy;利用k8s中特色的标签选择器,将cluster-ip对应多个相同服务的pod |
部署准备工作
- 基础设施
- CentOS7.6系统(内核在3.8以上)
- 关闭SELinux, 关闭firewalld服务
- 时间同步(chronyd)
- 调整Base源和Epel源
- 内核优化
部署须知
- mini-kebu,单节点微型k8s,仅用于实验和练手
- 第一次部署推荐使用,二进制部署,因为都需要签ssl证书,证书有效期为1年,一年后过期时候需要知道哪个证书是哪个服务的
- 使用kebuadmin部署,k8s部署工具,跑在k8s容器里,部署简单
部署流程
- 准备2核2G虚拟机5台,节点网络ip为10.4.7.xx;
- 部署bind9域名服务
- 签CA证书,需要注意证书的过期时间(使用k8admin部署,ca证书默认为一年)
使用cfssl签发ssl证书
下载安装 cfssl、cfssl-json、cfssl-certinfo;并为其附加可执行的权限
cfssl :证书签发的主要工具
cfssl-json :将cfssl生成的证书( json格式)变为文件承载式证书
cfssl-certinfo :验证证书的信息创建ca证书签名的请求(csr)json文件
CN: Common Name ,浏览器使用该字段验证网站是否合法, 一般写的是域名。非常重要。浏览器使用该字段验证网站是否合法
C: Country,国家ST:State,州,省L: Locality ,地区,城市O: Organization Name ,组织名称,公司名称OU: Organization Unit Name ,组织单位名称,公司部门
# 位于ca-csr.json
cd /opt/certs/
cat > ca-csr.json <<EOF
{
"CN": "zoneyet",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "henan",
"O": "zhengzhou",
"OU": "zoneyet"
}
],
"ca": {
"expiry": "175200h"
}
}
EOF
指定ca请求文件,生成json格式的证书证书
cfssl gencert -initca ca-csr.json
生成josn格式的证书之后转为文件承载形式的ca证书cfssl gencert -initca ca-csr.json | cfssl-json -bare ca
生成 ca.pem(根证书), ca-key.pem(根证书的私钥)cfssl-certinfo -cert 证书名称
查询证书的信息
harbor搭建私有镜像服务器
将本地的镜像使用tag命令打包之后,push到私有镜像服务器中,push之前需要使用docker log 命令登录到harbor服务中,用户名和密码和登录后台的用户名密码一致;成功之后可以在后台中看到harbor拥有的镜像;
开始部署
部署etcd服务(版本3.1)
etcd之间需要通信需要ssl,需要签发的证书
创建基于根证书的配置文件ca-config.json文件
{
"signing": {
"default": {
"expiry": "175200h"
},
"profiles": {
"server": {
"usages": [
"signing",
"key encipherment",
"server auth"
],
"expiry": "175200h"
}
"client": {
"usages": [
"signing",
"key encipherment",
"client auth"
],
"expiry": "175200h"
}
"peer": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "175200h"
}
}
}
创建etcd的ssl证书请求文件 其中hosts需要配上etcd需要通信的所有主机
{ "CN": "etcd.zoneyet", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "henan", "O": "zhengzhou", "OU": "zoneyet" } ], "ca": { "expiry": "175200h" } }
使用cfssl gencert -config=co-config.json 命令生成证书文件
./etcd.sh一堆参数 进行启动,命令含义解释
./etcdctl cluster-health
来查询etcd配置集群中其他服务的状态./etcdctl member list
查询集群服务中的信息,ip是否是leader等
api-server启动
签发3套ssl证书,拷贝到下载的/opt/apiserver/certs/
- 作为etcd的客户端来与etcd通信
- 作为apiserver服务端,让别的客户端来建立链接
- ca.pem及ca-key.pem作用?
k8s资源配置清单,用户k8s日志审计,audit.yaml文件
运行起来之后,监听127.0.0.1:8080和:::6443
如果启用多个api-server服务可以使用nginx的stream命令的4层反向代理;如果nginx为集群可以使用keepalive来实现vip,漂移服务器的ip地址,实现服务的高可用;
controller-manager启动
指定master参数为本机的api-server;且使用的协议为http,不需要安装证书
可以指定管理的容器的ip地址范围
scheduler启动
指定master参数为本机的api-server;且使用的协议为http,不需要安装证书
集群命令含义解释
kubectl get cs
来查询配置集群中其他服务的状态kubectl get node
来查询配置集群中计算节点的状态kubectl get pods
来查询配置集群中计算节点的状态kubectl create -f nginx-ds.yaml
通过yaml文件 创建nginx服务kubectl label node ip或主机名 指定角色
指定节点的标签
kuberlet部署
给kuberlet签发cfssl证书
- 配置文件kubelet.kubeconfig集成ca证书
kubectl config set-cluster myk8s --certificate=ca.pem绝对路径 --embed-cert=true --server=apiserver地址 --kubeconfig=kubelet.kubeconfig
- 配置文件kubelet.kubeconfig集成client证书
kubectl config set-credentials k8s-node --certificate=ca.pem绝对路径 --embed-cert=true --kubeconfig=kubelet.kubeconfig
- 配置文件kubelet.kubeconfig添加集群名称和用户名
kubectl config set-context myk8s-context --cluster=myk8s --user=k8s-node -- kubeconfig=kubelet.kubeconfig
切换k8s上下文
kubectl config use-context myk8s-context --kubeconfig=kubelet.kubeconfig
???
kubectl create -f k8s-node.yaml
创建k8s资源;会记录在etcd数据库中
配置k8s-node.yaml文件?定义一个k8s-node用户让其具有system:node的集群权限(目标让k8s用户在集群中具有运算节节点的权限)kubectl get clusterrolebinding k8s-node -o yaml
查询名称为k8s-node资源的权限绑定信息
docker pull kuber/pause
该镜像用于初始化docker容器的网络空间、ups空间
kube-proxy部署
签发ssl证书,创建kube-proxy.kubeconfig文件
kips:
- 如果证书的CN使用"system:kube-proxy"(在k8s中为默认的proxy角色),签证书的时候直接指定user=kube-proxy,那么不需要绑定该服务或节点的角色,会自动绑定;
- 使用 kubectl config 创建kube-proxy.kubeconfig文件
启动ip_vs模块
- 启动proxy服务时候分发网络使用,ip_vs的nq调度方法,调度算法只能使用rr(轮询调度)
启动kube-proxy
指定hostname;proxy_mode,ipvs-scheduler;及创建的配置文件ipvsadm -Ln
查询本机的ipvs规则
资源控制清单
- 资源类型有 pod控制器(pods、deployment)、pod(deploy)、service网络(svc)、历史修改记录(describe);如果不指定资源名称那么获取该空间下的所有该类型资源
- 陈述式,直接指定资源名称及空间名称;声明式,指定yaml文件
集群命令 | 含义 | 解释 |
| 查询指定名称空间下所有资源,默认default空间下 | |
| 查询某个资源的信息 |
|
| 查询某个资源属性的解释说明 | |
| 通过yaml资源配置清单来声明式创建资源 | |
| 通过yaml资源配置清单来声明式修改资源配置清单 | 在线修改,没有修改记录 |
| 离线修改,有修改记录 | |
| 查询指定资源的历史修改记录 |
FLANNEL(CNI网络插件)
能使容器在不同宿主机之间的通信
安装下载flannel,建立软连接,拷贝client.pem及client-key.pem证书到flannel/certs目录下(因为其要与etcd通信)
vi subnet.envFLANNEL_NETWORK=172.7.0.0/16 FLANNEL_SUBNET=172.7.21.1/24 FLANNEL_MTU=1500 FLANNEL_IPMASQ=false
启动./flanneld,指定启动ip及port,etcd的ip,及与之通信的cert证书,subnetfile
flannel依赖与etcd进行配置的存储,需要在etcd中建立一个键值对./etcdctl set /coreos.com/netword/config '{"Netword": "172.7.0.0/16", "Backend": {"Type": "host-gw"}}'
创建supervisord配置文件,启动flannel;
如果网络类型为host-gw类型,那么flannel就是在本地添加了几条静态路由记录,先从本宿主机以另外一个宿主机为网关访问的另外一个宿主机中的容器;可以通过route -n 查询本地的路由
命令查询宿主机中的所有静态路由;前提是两个宿主机可以直接通信,效率是最高的。
VxLAN 如果 /coreos.com/netword/config 网络配置为 ‘{“Netword”: “172.7.0.0/16”, “Backend”: {“Type”: “VxLAN”, “Directrouting”: true}}’;VxLAN模型为在两个宿主机之间建立一个网络隧道(创建两个可以互通的网卡),来实现两个宿主机的通信,进而实现两边容器的相互通信;该配置下,如果两个宿主机可以直接通信,那么会以host-gw模式运行,如果不同,以VxLAN模式运行
作用: 就是在宿主机中添加了一条route,在对面宿主机中删除iptables中的filter表中的reject动作;添加指定ip的filter表的accept动作对网络的优化
发现另外一台宿主机中的获取的本宿主机的容器的请求地址,不是本容器的ip而是本宿主机的ip,这里是因为ip-tables的snet规则对源地址做了修改,为了能区分是哪个容器来的请求可以修改该条ip-tables的规则iptables -t nat -I postrouting -s 172.7.21.0/24 ! -d 172.7.0.0/16 ! -o docker0 -j MASQUERADE
修改后的规则含义为:10.4.7.21主机上,来源是172.7.21.0/24段的网络(本宿主机容器),目标不是172.7.0.0/16(该机房所有宿主机容器),出网不是从docker0出来的做SNAT转换。避免容器之间来回进行地址转换优化过程
- 安装iptables-services
- 删除iptables中两个reject规则;
- 修改snet规则,为上面的规则,避免容器之间通信的snat转发
服务发现Coredns
负责将Service资源的名字和service资源的Cluster-ip对应上(服务内部)
使用k8s官方的yaml文件来创建Coredns服务;一般创建在kube-system名称空间下资源名称.命名空间名称.svc.cluster.local
在k8s集群内部,来访问对应的资源;集群外部并不能访问;
如果想使用短域名,需要配上search 域名结尾????cat /etc/resolv.conf
查询dns配置文件
服务暴露Ingress
只能暴露7层应用,类似nginx的http功能;
常用的ingress控制器:traefik:1.7.2-alpinef
- 准备traefik镜像
- rbac.yaml traefik的鉴权模块
- traefik_ds.yaml的配置清单
采用kind: Daemonset的方式部署,该方式下符合匹配条件的节点都会部署一个pod;如果有新节点加入集群时,也会为他们新增一个pod,当节点从集群中移除时,这些pod也会被移除- svc.yaml traefik的Service资源
- traefik-web-ui.yaml Ingress资源
Ingress资源配置清单,rules中配置了path及对应的服务,类似nginxspec: rules: - host: traefik.od.com # 此处为traefik服务的域名 http: paths: - path: / backend: serviceName: hostname servicePort: 8080
- 在对外服务的nginx配置中,模糊匹配url,*.od.com统一分发到ingress服务,然后经ingress代理到各个Service对应的服务;其外网对外的nginx还可以配置详细的url,用于卸载ssl,避免ingress使用https协议过于复杂;
/etc/ngixn/conf.d/*.od.com.conf
upstream default_backend_traefik {
server 10.4.7.21:81 max_fails=3 fail_timeout=10s;
server 10.4.7.22:81 max_fails=3 fail_timeout=10s;
}
server {
server_name *.od.com;
location / {
proxy_pass http://defult_backend_traefik;
proxy_set_header Host $http_host;
proxy_set_header x-forwarded-for $proxy_addx_forwarded_for;
}
}
/etc/nginx/conf.d/dashboard.od.com.conf
server {
listen 80;
server_name dashboard.od.com; # 详细域名
rewrite ^(.*)$ https://${server_name}$1 permannet; # 重定向
}
server {
listen 443 ssl;
server_name dashboard.od.com;
ssl_certificate ".crt文件路径";
ssl_certificate_key ".key文件路径";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MDS;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://default_backend_traefik;
proxy_set_header Host $http_host;
proxy_set_header x-forwarded-for $proxy_addx_forwarded_for;
}
}
dashboard资源管理插件-仪表盘
- 准备dashboard:1.8.3的镜像
- 去k8s的github上找kubernetes/cluster/addons/dashboard 找rbac.yaml、dp.yaml、svc.yaml、ingress.yaml
在bind9中创建一条dashboard.od.com ip的记录;- 签发证书
rbac(k8s中的鉴权机制)
- 权限
- get write update list watch- 角色
- Role 普通角色
ClusterRole 对这个集群有效- 用户 通过绑定角色来获取权限
- 用户账户 user;kubeconfig文件就是k8s中用户的一个配置文件
服务账户 service account
所有的pod都必须有一个用户
过程
- 创建用户,声明类型,服务账户还是用户账户;声明用户名
- 创建角色
声明角色名称
声明角色具有的权限;rules: apiGroups(组),resources(资源),verbs(权限)- 绑定用户和角色,roleRef 绑定的角色;subjects:绑定的用户
平滑升级集群
- 将nginx4层及7层的流量切断到该节点的流量
- 删除资源偏少的节点
kubectl delete node node_name
;会自动迁移到其他节点查询k8s上的节点kubectl get nodes
- 安装需要的安装包后,将配置文件和需要的文件移动到新的安装包里,重新启动服务;
- 切换nginx4层及7层的流量,重新流入新集群
共享存储
不使用persistent Volumes;而是使用 nfs
- 配置nfs共享服务
yum install nfs-utils -y
nfs配置文件~]# cat /etc/exports /data/nfs-volume 10.4.7.0/24(rw,no_root_squash) mkdir -p /data/nfs-volume systemctl start nfs systemctl enable nfs
k8s配置清单中支持,nfs卷的加载
spec: volumes: - name: data nfs: # nfs类型的卷 server: hdss7-200 path: /data/nfs-volume/jenkins_home - name: docker hostPath: # 宿主机中的卷 path: /run/docker.sock type: '' container: ... volumeMounts: - name: data # 在容器中使用卷 mountPath: /var/jenkins_home # 映射到容器中的位置
其他tips
- 实现容器中与宿主机的docker-service通信,只需要容器中安装docker-start,将宿主机中的/run/docker.socket映射到宿主机相同位置就可以和宿主机通信了;
- docker镜像拉取策略
IfNotPresent 如果本地仓库没有就去远程仓库拉- 如果想拉取habor中的私有仓库,需要在资源配置清单中配置上,
ImagePullSecrects: -name: harbor
(该名字为同一名称空间下的 secret名字)