1.Kubernetes是什么
2.Kubernetes特性
3.Kubernetes集群架构与组件
4.Kubernetes核心概念
• Kubernetes是Google在2014年开源的一个容器集群管理系统,Kubernetes简称K8S。
• K8S用于容器化应用程序的部署,扩展和管理。
• K8S提供了容器编排,资源调度,弹性伸缩,部署管理,服务发现等一系列功能。
• Kubernetes目标是让部署容器化应用简单高效。官方网站:http://www.kubernetes.io
在节点故障时重新启动失败的容器,替换和重新部署,保证预期的副本数量;杀死健康检查失败的容器,并且在未准备好之前不会处理客户端请求,确保线上服务不中断。
使用命令、UI或者基于CPU使用情况自动快速扩容和缩容应用程序实例,保证应用业务高峰并发时的高可用性;业务低峰时回收资源,以最小成本运行服务。
K8S采用滚动更新策略更新应用,一次更新一个Pod,而不是同时删除所有Pod,如果更新过程中出现问题,将回滚更改,确保升级不受影响业务。
K8S为多个容器提供一个统一访问入口(内部IP地址和一个DNS名称),并且负载均衡关联的所有容器,使得用户无需考虑容器IP问题。
管理机密数据和应用程序配置,而不需要把敏感数据暴露在镜像里,提高敏感数据安全性。并可以将一些常用的配置存储在K8S中,方便应用程序使用。
挂载外部存储系统,无论是来自本地存储,公有云(如AWS),还是网络存储(如NFS、GlusterFS、Ceph)都作为集群资源的一部分使用,极大提高存储使用灵活性。
提供一次性任务,定时任务;满足批量数据处理和分析的场景。
Master
Kubernetes API,集群的统一入口,各组件协调者,以RESTful API提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后再提交给Etcd存储。
处理集群中常规后台任务,一个资源对应一个控制器,而ControllerManager 就是负责管理这些控制器的。
根据调度算法为新创建的Pod选择一个Node节点,可以任意部署,可以部署在同一个节点上,也可以部署在不同的节点上。
分布式键值存储系统。用于保存集群状态数据,比如Pod、Service等对象信息。
Node
kubelet是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创 建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等工作。kubelet将每个Pod转换成一组容器。
在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作。
容器引擎,运行容器。
更高级层次对象,部署和管理Pod
1.官方提供的三种部署方式
2.Kubernetes平台环境规划
3.自签SSL证书
4.Etcd数据库集群部署
5.Node安装Docker
6.Flannel容器集群网络部署
7.部署Master组件
8.部署Node组件
9.部署一个测试示例
10.部署Web UI(Dashboard)
11.部署集群内部DNS解析服务(CoreDNS)
Minikube是一个工具,可以在本地快速运行一个单点的Kubernetes,仅用于尝试Kubernete或日常开发的用户使用。 部署地址:https://kubernetes.io/docs/setup/minikube/
Kubeadm也是一个工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。部署地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
推荐,从官方下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。下载地址:https://github.com/kubernetes/kubernetes/releases
软件 | 版本 |
Linux | Centos7.5 |
Kubernetes | 1.12 |
Docker | 18.09 |
Etcd | 3.3.10 |
Flannel | 0.10 |
角色 | IP | 组件 | 主机名 |
Master01 Load Balancer(Master) |
192.168.100.10 192.168.100.50(vip) |
kube-apiserver kube-controller-manager kube-scheduler etcd Nginx L4 |
K8s1 |
Master02 Load Balancer(Backup) |
192.168.100.20 |
kube-apiserver kube-controller-manager kube-scheduler etcd Nginx L4 |
K8s2 |
Node01 | 192.168.100.30 |
kubelet kube-proxy docker flannel etcd |
K8s3 |
Node02 | 192.168.100.40 |
kubelet kube-proxy docker flannel |
K8s4 |
组件 | 证书 |
etcd |
ca.pem,server.pem,server-key.pem |
flannel |
ca.pem,server.pem,server-key.pem |
kube-apiserver | ca.pem,server.pem,server-key.pem |
kubelet | ca.pem,ca-key.pem |
kube-proxy | ca.pem,kube-proxy.pem,kube-proxy-key.pem |
kubectl | ca.pem,admin.pem,admin-key.pem |
颜色不同,代表有两份证书,意思就是2个不同的ca。
1.使用cfssl工具.
首先在master01安装工具,生成证书。
curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson /usr/local/bin/cfssl-certinfo (参见脚本cfssl.sh)
2.生成etcd证书
创建/opt/etcd-cert目录存储etcd证书。
首先创建ca-config.json和ca-csr.json,首先创建ca证书,才能为其它签发证书
ca-config.json cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "www": { "expiry": "87600h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } } } EOF
ca-csr.json cat > ca-csr.json <<EOF { "CN": "etcd CA", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Beijing", "ST": "Beijing" } ] } EOF
执行后结果
现在开始初始ca证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
现在为etcd签发证书
server-csr.json一定要正确的填写etcd的ip
执行以下命令为etcd签发证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
(参见脚本etcd-cert.sh)
https://github.com/etcd-io/etcd/releases
/opt/etcd/bin/etcdctl \ --ca-file=ca.pem --cert-file=server.pem --key-file=server-key.pem \ --endpoints="https://192.168.0.x:2379,https://192.168.0.x:2379,https://192.168.0.x:2379" cluster-health
etcd工作目录/opt/etcd mkdir -p /opt/etcd/{bin,cfg,ssl}
1.首先下载etcd包,然后将里面的二进制拷贝至工作目录bin。
2.将etcd证书拷贝至ssl
3.这一步使用脚本来初始etcd配置文件以及服务控制文件(参见脚本etcd.sh)
执行此脚本的时候会停住,因为etcd节点在需找其它其它节点。
4.现在验证一下上一步脚本生成的配置文件以及服务控制文件
/opt/etcd/cfg/etcd
/usr/lib/systemd/system/etcd.service
5.将etcd拷贝至其它两台etcd服务器后,修改配置
拷贝至etcd02
修改etcd02配置
将服务加入系统管理
拷贝至etcd03
修改etcd03配置
将服务加入系统管理
6.启动三台机器etcd服务,并检查集群状态。
Overlay Network:覆盖网络,在基础网络上叠加的一种虚拟网络技术模式,该网络中的主机通过虚拟链路连接起来。
VXLAN:将源数据包封装到UDP中,并使用基础网络的IP/MAC作为外层报文头进行封装,然后在以太网上传输,到达目的地后由隧道端点解封装并将数据发送给目标地址。
Flannel:是Overlay网络的一种,也是将源数据包封装在另一种网络包里面进行路由转发和通信,目前已经支持UDP、VXLAN、AWS VPC和GCE路由等数据转发方式。
1.写入分配的子网段到etcd,供flanneld使用
/opt/etcd/bin/etcdctl \ --ca-file=ca.pem --cert-file=server.pem --key-file=server-key.pem \ --endpoints="https://192.168.0.x:2379,https://192.168.0.x:2379,https://192.168.0.x:2379" \ set /coreos.com/network/config '{ "Network": "172.20.0.0/16", "Backend": {"Type": "vxlan"}}'
2.下载二进制包
https://github.com/coreos/flannel/releases
3.部署与配置Flannel
4.systemd管理Flannel
5.配置Docker使用Flannel生成的子网
6.启动Flannel
注意:因为flannel使用的证书是etcd的,所以这里可以不用创建证书。
1.写入分配的子网到etcd,供flanneld使用。(etcd节点执行)
/opt/etcd/bin/etcdctl --ca-file=ca.pem --cert-file=server.pem --key-file=server-key.pem --endpoints="https://192.168.100.10:2379,https://192.168.100.20:2379,https://192.168.100.30:2379" set /coreos.com/network/config '{ "Network": "172.20.0.0/16", "Backend": {"Type": "vxlan"}}'
然后使用get查看
2.将二进制包拷贝至node节点,因为只有node节点才需要flannel网络
首先在node节点创建flannel的文件夹。
mkdir -p /opt/kubernetes/{bin,cfg,ssl}
解压flannel包,然后将二进制文件拷贝至bin目录下
生成flannel配置文件
cat <<EOF >/opt/kubernetes/cfg/flanneld FLANNEL_OPTIONS="--etcd-endpoints=${ETCD_ENDPOINTS} \ -etcd-cafile=/opt/etcd/ssl/ca.pem \ -etcd-certfile=/opt/etcd/ssl/server.pem \ -etcd-keyfile=/opt/etcd/ssl/server-key.pem" EOF
但是还不够,需要把etcd的信息补充完毕(连接etcd的端点信息)
Flannel证书,由于etcd与node混合部署,所以第一台flannel是不需要去复制证书的
生成flannel 服务控制文件
cat <<EOF >/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=/opt/kubernetes/cfg/flanneld ExecStart=/opt/kubernetes/bin/flanneld --ip-masq \$FLANNEL_OPTIONS ExecStartPost=/opt/kubernetes/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env Restart=on-failure [Install] WantedBy=multi-user.target EOF
3.启动flannel 验证
启动服务后日志会输出开始操作iptables
然后查看flannel分配的子网
4.更改docker配置文件,使之使用flannel网络
然后重启docker验证
网卡验证
5.现在部署node02(从这里开始,也是部署每一个新node节点需要做的事情)
由于node02没有etcd的证书,所以这里需要将etcd的证书拷贝过去。
然后将flannel 服务及配置拷贝过去。
然后启动node02的flannel
重启docker
6.验证
现在在node01 和node02各创建一个测试镜像进行测试
Node01
Node02
现在node01 ping node02
本章也不是单纯自签apiserver证书,比如kubelet ,kube-proxy都会使用脚本一并签发,不同的是在以下证书,有多的字段,比如
o代表用户,OU代表组,后面都会用到
参考脚本 k8s-cert.sh
所有证书都放在master01节点上
整个脚本有一个地方需要注意,在签发api证书时,这里的ip一定要包括master所有节点以及vip,这里10.0.0.1一定要,这是集群ip的地址。
1.kube-apiserver
2.kube-controller-manager
3.kube-scheduler
配置文件 -> systemd管理组件 -> 启动
Kube-apiserver 方式和上述方式一样,只不过证书以及配置文件需要有几点注意。
1.在master01创建/opt/kubernetes/文件夹
2.将需要用到的二进制包拷贝至对应目录
3.拷贝证书至对应目录
因为etcd的证书本来就在master上,所以这里就不拷贝了,现在拷贝api证书
4.生成token.csv文件
此文件是node集群需要的用户名和一些参数
首先生成一串token字符串
参数一: 字符串token值
参数二: node用户名
参数三: node 用户组id
参数四: node用户组
此参数在后续node端会详细讲解
5.使用脚本生成kube-apiserver配置及服务控制脚本。 (apiserver.sh)
脚本需要指定etcd集群信息和本地master信息,配置里面需要的证书和token已经在前面准备好了
查看配置文件
查看服务控制脚本
6.验证kube-apiserver是否正常
kube-controller-manager服务和api服务一样,改的东西也比较少,所以执行脚本后将不在贴出配置信息。
执行脚本
查看服务状态
kube-scheduler和 kube-controller-manager一样,只需要注意配置里面的 集群选举打开即可。
这里没有api模块的信息,但是当能正常返回集群组件信息的时候,代表api已经正常了。
1) 将kubelet-bootstrap用户绑定到系统集群角色
kubectl create clusterrolebinding kubelet-bootstrap \ --clusterrole=system:node-bootstrapper \ --user=kubelet-bootstrap
2) 创建kubeconfig文件
3) 部署kubelet,kube-proxy组件
1.首先准备将kubelet-bootstrap用户绑定到系统集群角色。
此步骤如果不绑定创建用户,node启动时会报用户没有绑定的错误,也就无法给node颁发证书。
此操作在master节点上操作
首先将kubelet加入系统变量,这样方便操作
创建绑定用户,将kubelet-bootstarp 绑定到role角色上
2.这里准备node节点需要的文件
需要在master节点操作,因为 生成bootstrap.kubeconfig 的文件需要ca.pem文件,而node配置文件需要指定bootstrap.kubeconfig和kube-proxy kubeconfig。
这里使用kubeconfig.sh 脚本来生成配置文件,脚本里面的变量名BOOTSTRAP_TOKEN 一定要是之前token里面相同的。
以上会多出2个配置文件,这里一定要注意不要生成脚本时填写错误
然后将生成的2个配置文件拷贝至node节点的/opt/kubernetes/cfg里面
3.将node需要的二进制 文件拷贝至node节点。
将node节点生成配置的脚本也拷贝至node节点
4.Kubelet 服务部署
使用kubelet.sh 来生成 配置文件以及服务控制文件,服务控制文件里面需要指定之前生成的bootstrap.kubeconfig,3个文件是调用的一个关系。
这里需要注意,kubelet里面设置了pod去下载的镜像源,这里稍微注意一下
执行脚本指定node节点地址以及dns服务器地址
启动成功后可以在/opt/kubernetes/ssl里面看到颁发的证书
5.Kube-proxy服务部署
Proxy 脚本没什么需要注意的,不过,proxy-mode参数1.11版本之前是iptables的模式,1.12之后ip_vs已经稳定了
6.在master通过node节点的请求
回到master节点查看待审批的请求
现在予许通过
7.重复第2步-第6步的操作,将第二台node加入集群
拷贝bootstrap.kubeconfig kube-proxy.kubeconfig 至第二台node节点
拷贝生成配置文件和服务文件脚本至第二台node节点
拷贝二进制安装文件至 第二台node节点
执行脚本生成配置文件并启动服务
在master节点,通过审批
查看pods状态
映射端口以nodeport的模式
首先在node01上访问
然后在node02上访问
然后用本机浏览器直接访问node端口
查看分布情况
由于创建pod后,使用kubectl直接去exec进入交互和logs是权限拒绝的,这里使用以下方案,开始匿名访问权限,并将匿名用户加入管理员角色权限。
1.首先开始node节点的匿名访问权限。
针对所有node
然后重启kubelet服务
2.将匿名用户加入系统权限里面
kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
3.验证
现在可以进入容器,也可以查看容器日志
创建web ui的方式是使用kubectl yml的方式,这里总共有6个文件需要创建。(一个授权token文件是自己编写的)。
这里也只有2个文件需要更改一下。
1.更改dashboard-controller.yml文件。
更改里面的镜像地址,因为默认是谷歌地址,国内无法访问。
文件路径
2019年6月10日星期一 v1.10.0阿里云只有1.10.1版本了
2.更改dashboard-service 的NodePort,否则客户端无法使用浏览器访问
3.创建5个yml文件,然后验证
查看namespace是否创建dashboard
查看nodeport
4.添加权限token文件
到这一步,dashboard可以访问了,但是没有token文件,无法正常登陆,所以这里使用一个自建的权限文件来生成token。
5.查看token密钥,然后访问测试
6.使用令牌的方式访问,推荐火狐浏览器,其它浏览器因为证书问题会直接拒绝。
本章使用nginx 做4层负载,keepalived做高可用,所以本章要注意以下几点。
配置master02 可以直接将 master01的配置拷贝过去,稍作更改即可。
1.master01配置,服务控制脚本以及证书。
配置文件只需要更改api 配置的两处的 绑定IP就可以启动三个服务了。
验证搭建完成
Nginx 使用14.02版本,yum源上官网查找
只需要在http相同层级加以下配置即可。
stream { log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent'; access_log /var/log/nginx/k8s-access.log main; upstream k8s-apiserver { server 192.168.100.10:6443; server 192.168.100.20:6443; } server { listen 0.0.0.0:6444; proxy_pass k8s-apiserver; } }
以上有2点需要注意:
使用以上方式,配置另一台nginx 服务。
如果出现vip切换问题,请更改主备配置文件里面的virtual_router_id为其它相同的数本工具也使用yum安装,只需要注意一下检测nginx的脚本即可。
主配置文件
global_defs { # 接收邮件地址 notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } # 邮件发送地址 notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_MASTER } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 # VRRP 路由 ID实例,每个实例是唯一的 priority 100 # 优先级,备服务器设置 90 advert_int 1 # 指定VRRP 心跳包通告间隔时间,默认1秒 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.100.50/24 } track_script { check_nginx } }
备配置文件
global_defs { # 接收邮件地址 notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } # 邮件发送地址 notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_MASTER } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 # VRRP 路由 ID实例,每个实例是唯一的 priority 90 # 优先级,备服务器设置 90 advert_int 1 # 指定VRRP 心跳包通告间隔时间,默认1秒 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.100.50/24 } track_script { check_nginx } }
Check_nginx
count=$(ps -ef |grep nginx |egrep -cv "grep|$$") if [ "$count" -eq 0 ];then systemctl stop keepalived fi
请验证完成主备切换
首先查看哪些连接api server。
Node01
更改前
更改后
Node02
更改前
更改后
然后两台node重启kubelet和kube-proxy服务
然后监听主master的日志
早期版本是用kube-dns,但是部署方式复杂。
包路径在/tools/Soft/kubernetes/cluster/addons/dns/coredns,该目录下有文件
1.修改 coredns.yaml.sed.
以下3处内容
2.创建dns容器
3.创建一个容器测试解析。
同一个命令空间解析测试
不同命名空间解析测试
不同命令空间需要加上命令空间后缀才能解析
首先这里介绍,在使用kubectl工具的时候一般是在master节点上,kubectl请求的是本机的127.0.0.1:8080未加密的远程api server端口,现在部署至node节点,查看解决方案。
以下是学习截图
具体命令
./kubectl config set-cluster kubernetes --server=https://192.168.100.50:6444 --certificate-authority=ca.pem ./kubectl config set-credentials cluster-admin --certificate-authority=ca.pem --client-key=admin-key.pem --client-certificate=admin.pem ./kubectl config set-context default --cluster=kubernetes --user=cluster-admin ./kubectl config use-context default
需要使用ca.pem以及admin的证书。
上图中每一步执行就是为了写一个配置文件。
1.拷贝需要的二进制文件及密钥至客户端
2.按照上图中执行每一条命令来生成配置文件
查看root文件夹生成的配置文件
验证结果
• Infrastructure Container:基础容器
• InitContainers:初始化容器
• Containers:业务容器
基础容器在node节点的配置文件是已经指定的,每次创建一个pod都会创建一个这样的容器。
初始化容器 初始化一些操作,比如之前无状态的,给一个pod里面的容器做一些初始顺序的控制。
业务容器就没必要解释了。
本章讲解主要点是 docker login 里面拉去镜像和k8s拉取镜像是不同的认证,这里一定要注意。
K8s如果需要去拉取认证的仓库镜像,是需要创建一个k8s token的。
1.首先docker登录。
这里会在~/.docker/config.json中有一个认证信息
2.将token信息写入一个k8s文件中
3.最后在拉取镜像的时候指定密钥即可
Request 是比如一个node已经没有这些资源了,就不会调度到这个node上
Limits 是一个容器最大的资源限制。
250m代表一核cpu的百分之25,也就是0.25。
查看节点资源的利用率
NodeName会跳过调度器,直接分配。
NodeSelector要先给node打标签。
比如一个server的定义,通过selector与pod相关联
可以给一个pod指定多个server,且同一个pod标签可以给不同的pod容器关联(意思就是同一个server下面的容器服务可以不相同)。
ClusterIP
集群级别,集群内部可以访问
NodePort (用户浏览器可以访问)
LoadBalancer(云平台服务)
Iptables是用户态的工具,而ipvs是内核态的工具,1.10版本以上使用的是ipvs。
Iptables流程图
Ipvs流程图
1.四层、七层负载均衡转发
2.支持自定义Service访问策略
3.只支持基于域名的网站访问
4.支持TLS
简单来说,就是在node节点监听80和443,然后在一个命名空间里面创建一个镜像,镜像内部是一个nginx,然后通过访问域名来解析到具体的server里面去。
(官方有很多实现方式,只不过这里是使用nginx)
具体流程看下图:
部署文档:
https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md
注意事项:
• 镜像地址修改成国内的:lizhenliang/nginx-ingress-controller:0.20.0
• 使用宿主机网络:hostNetwork: true
其他控制器:
https://kubernetes.io/docs/concepts/services-networking/ingress/
1.首先下载该地址yaml 部署文件。
2.修改配置
将国外谷歌的源改成可下载的源,以及将此容器网络改为host模式。
3.特别注意的一点
所有node节点的kube-proxy都需要加上一行配置,否则pod无法正常启动。
主要原因在于健康检查失败.
4.创建该pod
注意创建到哪台node上。
现在通过ingress暴露自己的项目。
原理就是下面创建了一个nginx的容器,来实现负载均衡的调度。
测试访问
原理验证
就是给nginx-ingress里的nginx加了记录,让nginx自动去负载调度后端pod
https就不多做解释,官网有使用文档:
https://kubernetes.io/docs/concepts/services-networking/ingress/
简要步骤就是把证书做成一个引用文件,在创建的时候引用即可。
以上ingress的问题很明显,只能访问单台node,那么解决方案就是在创建ingress的时候使用标签等方式部署在每一台node上。(创建kind类型为daemonset,这个以后在补充)
这里部署java项目,首先要确定一个思路。ci/cd流程首先略过,首先 java项目包已经构建完成,然后build至镜像仓库了,那么现在。
1.创建一个namespace。
2.部署tomcat应用
3.发布到用户可以访问