参考:
Kubernetes权威指南 从Docker到Kubernetes实践全接触.pdf
1.概述
service-服务
分布式集群架构核心
特征: 唯一名称\虚拟IP端口\提供远程服务\映射到一组容器之上
基于socket通信
k8s给pod贴标签(如mysql),然后给service定义标签选择器,从而将service与pod关联
pod
pod运行于node中,node可以是物理机或者虚拟机,通常一个node几百个pod
pod中运行pause容器,其他业务容器共享pause的网络和volume
pod是最小单元
master节点运行kube-apiserver\kube-controller-manager\kube-scheduler,实现资源管理\pod调度\安全监控等,全自动完成
node上运行kublet\kube-proxy,负责pod的创建\启动\监控\重启\销毁以及负载均衡
通过创建rc(replication controller),实现服务扩容,rc文件包括pod定义\副本数量\标签
环境准备
# centos 7虚拟机
# 修改网络配置
vi /etc/sysconfig/network-scripts/ifcfg-ens33
service network restart
# 设置主机名
hostnamectl set-hostname k8s-01
# 重启
# 配置阿里云镜像
yum install -y wget
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum clean all && yum makecache
# 关闭防火墙
systemctl disable firewalld
systemctl stop firewalld
# k8s单机环境搭建
# 安装
yum install etcd kubernetes -y
# 按顺序启动所有服务
systemctl start etcd && \
systemctl start docker && \
systemctl start kube-apiserver && \
systemctl start kube-controller-manager && \
systemctl start kube-scheduler && \
systemctl start kubelet
启动MySQL服务
# 创建rc文件: mysql-rc.yaml
--------------
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql # RC的名称,全局唯一
spec:
replicas: 1 # Pod副本期待数量
selector:
app: mysql # 符合目标的Pod拥有此标签
template: # 根据此模板创建Pod的副本(实例)
metadata:
labels:
app: mysql # Pod副本拥有的标签,对应RC的Selector
spec:
containers: # Pod内容器的定义部分
- name: mysql # 容器的名称
image: mysql # 容器对应的DockerImage
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_ASSWORD
value: "123456"
-----------------
# 发布到集群
kubectl create -f mysql-rc.yaml
# 删除
# kubectl delete -f mysql-rc.yaml
# 查看创建的rc
kubectl get rc
# 查看pod
kubectl get pods
# 查看创建情况
kubectl describe pods mysql-z1jr4
# 异常: No resources found.
# 异常解决
vi /etc/kubernetes/apiserver
# 找到这一行 "KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota",去掉ServiceAccount
# 重启apiserver
systemctl restart kube-apiserver
# 查看运行的容器
docker ps I grep mysql
# 创建与之关联的service定义文件
mysql-svc.yaml
-------------
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
-------------
# 创建service
kubectl create -f mysql-svc.yaml
# 查看service
kubectl get svc
# 查看结果中cluster ip是虚地址,其他pod可以通过cluster ip+端口访问它
# cluster ip无法预先知道,k8s使用linux环境变量实现根据服务名找到cluster ip
启动tomcat应用
# myweb-rc.yaml
---------------
apiVersion: v1
kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 2
selector:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
containers:
- name: myweb
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
---------------
# 创建rc
kubectl create -f myweb-rc.yaml
kubectl get pods
# 创建service
# myweb-svc.yaml
--------------
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: myweb
---------------
kubectl create - f myweb-svc.yaml
# 查看service
kubectl get services
# 访问:
192.168.68.151:30001/demo
2.概念
master
集群控制节点
api server 所有资源的crud
controller manager 所有资源的自动化控制
scheduler 资源调度
etcd 资源数据保存
node
node可以运行时动态增加到集群
kubelet向master定时汇报自身情况
# 查看某个node信息
kubectl describe node 127.0.0.1
# 显示:
# 1.node基本信息
# 2.node当前运行状态,磁盘不足\内存不足等
# 3.node资源总量
# 4.node可分配资源量
# 5.主机系统信息
pod
pause 所有pod根容器,以其状态代表整个容器总体状态,并解决通信和文件共享问题
任意两个pod可以通信,采用flannel等虚拟二层网络
静态pod不存在etcd中,而是放在某个node的文件中,普通node存在etcd中
k8s所有资源都可用yaml或者json格式文件定义
event记录事件信息,用于排查故障
kubectl describe pod ***
pod可对服务器资源进行限额,cpu与内存,cpu是一个绝对值
cpu配额通常以千分之一为最小单位,用m表示,100-300m表示0.1-0.3个cpu
k8s中配额设定两个参数 requests(最小申请量)\limits(最大允许量,超额可能被kill重启)
# 配置mysql配额为0.5个cpu和128m内存
spec:
containers:
- name: db
image: mysql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Label标签
kv键值对,可以负载在pod\node\service\rc等各种资源上
一个资源对象可以定义任意数量的label,一个label也可以被添加到任意数量的资源对象上
label可以在对象创建后动态添加
通过label可以实现多维度的资源分组管理,版本\环境\架构\分区等
通过类似sql的label selector选择资源对象
label selector 2种,基于等式和基于集合
# 匹配不具有标签的对象
env ! = production
# 集合中的
name in (redis-master, redis-slave)
# 可以通过多个表达式组合实现复杂的条件选择
# 示例myweb pod
metadata:
name: myweb
labels:
app: myweb
# rc和service在spec中定义selector
spec:
replicas: 1
selector:
app: myweb
...
# 基于集合筛选
selector:
matchLabels:
app: myweb
matchExpressions:
- {key: tier, operator:In, values: [frontend]}
- {key: environment, operator: NotIn, values: [dev]}
Label Selector使用场景:
kube-controller控制pod副本数量
kube-proxy实现负载均衡
kube-scheduler定向pod调度
rc
定义pod副本数,label selector,pod模板
通过rc实现集群高可用,减少运维工作
pod意外终止,pod数目小于定义的副本数自动创建新pod
运行时可修改rc副本数量动态缩放
kubectl scale rc redis-slave --replicas=3
删除rc不会删除pod,需要先设置replicas为0,然后跟新rc,可通过stop和delete命令一次性删除rc和rc控制的所有pod
系统升级时,如10个旧版本pod,每次停止一个旧pod并创建一个新版本pod,这称为滚动升级
k8s1.2后rc升级为replica set,支持基于集合的label selector,功能更强
deployment
rc的升级,可以随时知道pod部署进度
场景:
创建pod副本
查看部署是否完成
创建新pod(如镜像升级)
...
# deployment定义,
apiVersion: extensions/v1beta
kind:Deployment
metadata:
name: nginx-deployment
# replica set定义
apiVersion: v1
kind: ReplicaSet
metadata:
name: nginx-repset
# 创建deployment
# tomcat-deployment.yaml
----------------
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: app-demo
tier: frontend
spec:
containers:
- name: tomcat-demo
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
----------------
kubectl create -f tomcat-deployment.yaml
# 查看deployment
kubectl get deployments
# 查看replica set
kubectl get rs
# 可以看到rs命名与deployment有关
# 查看pod
kubectl get pods
# 可以看到pod命名以rs为前缀
Horizontal Pod Autoscaler
横向自动扩容
通过scale扩容不符合k8s自动化定位,需要根据负载水平扩展或缩容,这一过程频繁发生,手工控制不现实
两种度量指标,CPUUtilizationPercentage()cpu使用率)和自定义指标(TPS或QPS)
通常使用1min内的平均CPU使用量,需要安装Heapster插件
# HPA例子
# 目标对象为php-apache,pod副本的CPUUtilizationPercentage超过90%时自动扩容
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
kind: Deploynent
name: php-apache
targetCPUUtilizationPercentage: 90
# 还可以通过命令创建HPA对象
kubectl autoscale deployment php-apache --cpu-percent=90 - - min=1 --max=10
StatefulSet
Deployment/RC的一个特殊变种
特性:
假设StatefulSet的名字叫kafka,,那么第l个Pod叫kafka-0,第2个叫kafk-1,以此类推
Pod副本的启停顺序是受控的
pod使用稳定的持久化存储卷,通过pv/pvc实现,删除pod不会删除存储卷
要与HeadlessService配合使用,HeadlessService没有cluster ip
如一个3节点的Kafka的StatefulSet集群,对应的HeadlessService的名字为kafka,StatefulSet的名字为kafka,则StatefulSet里面的3个Pod的DNS名称分别为kafka-0.kafka、kafka-1.kafka、kafka-3.kafka,这些DNS名称可以直接在集群的配置文件中固定下来
service
就是微服务
k8s为service定义入口地址,通过该地址访问背后的pod副本,service和pod通过label selector对接,rc保证service质量
客户端pod转发到哪个pod由负载算法决定
kube proxy机负载均衡器,k8s为每一个服务分配全局唯一的虚拟ip
# 创建service
# tomcat-service.yaml
------------
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
ports:
- port: 8080
selector:
tier: frontend
------------
kubectl create -f tomcat-service.yaml
# 查看endpoint列表
kubectl get endpoints
# 查看service的cluster ip
kubectl get svc tomcat-service -o yaml
# targetPort确定容器暴露的端口号,默认与port相同
# 很多服务存在多端口问题, service支持多endpoint
-------
spec:
ports:
- port:8080
name: service-port
- port: 8080
name: shutdown-port
-------
服务发现机制
大多数分布式系统通过api接口实现服务发现导致侵入性比较强
k8s中服务有唯一的cluster ip和name,k8s最早采用环境变量的方式通过服务名找到cluster ip,后来引入dns系统
外部系统访问Service
区别3种ip:
node ip即每个节点的物理网卡ip
pod id是docker0网桥分配,真实流量通过node ip网卡流出
cluster ip,仅作用与service对象,无法被ping,结合service port组成具体通信端口,无法在集群外使用,集群外访问通过定义NodePort实现
# 修改上述tomcat-service.yaml,增加type和nodePort
------------
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
ports:
type: NodePort
- port: 8080
nodePort: 31002
selector:
tier: frontend
-------------------
# 浏览器访问: NodeIp:31002
volume
volume定义在pod,被pod多个容器挂载到具体的目录
容器停止,volume数据不丢失
k8s支持多种类型的volume,如gluster fs和ceph
template:
metadata:
labels:
app: app-demo
tier:frontend
spec:
volumes:
- name: datavol
emptyDir: {}
containers:
- name: tomcat-demo
image: tomcat
volumeMounts:
- mountPath: /mydata-data
name: datavol
imagePullPolicy: IfNotPresent
volume扩展出配置管理,通过ConfigMap实现
Namespace
多租户资源隔离
# 默认pod\rc\service都被创建到default中
kubectl get namespaces
# 定义namespace
-----------
apiVersion: v1
kind: Namespace
metadata:
name: development
------------
# 定义pod指定namespace
-----------
kind: Pod
metadata:
name: busybox
namespace: development
----------
# get命令查看无法显示
kubectl get pods
# 需指定namespace参数
kubectl get pods --namespace=development
多租户namespace资源隔离可以配合资源配额管理
Annotation
与label类似,kv形式
定义附加信息,如构建信息\团队信息等
网友评论