1 k8s 简介
Kubernetes 是一个开源的容器编排引擎,用来对容器化应用进行自动化部署、 扩缩和管理平台。
官网:https://kubernetes.io/zh-cn/
临时 kubenets 环境: https://kubesphere.cloud/
1.1 能做什么
- 服务发现和负载均衡
- 存储编排
- 自动部署和回滚
- 自动完成装箱计算
- 自我修复
- 密钥与配置管理
1.2 kubenetes 架构
1.3 组件
1.3.1 控制面板:
- kube-apiserver: 资源操作的唯一入口, 接收用户输入的命令,提供认证,授权, APU注册和发现等机制。
- etcd: 是一个键值存储仓库,存储中各种资源 用于配置共享和服务发现。
- kube-scheduler: 负载资源调度, 按照预定的调度策略将Pod调度到相应的工作节点上。
- kube-controller-manager: 负责维护集群状态,比如服务的部署安排, 故障检测,自动扩展,滚动更新等。
1.3.2 Node
- kubelet: 负责维护Pod的生命周期,即通过控制docker来创建,更新,销毁容器等
- kube-proxy: 负责提供集群内部的服务发现和负载均衡
- Container Runtime:负责运行容器的软件
- supervisord: 是一个轻量级的进程监控系统,可以用来保证 kubelet 和 docker 运行
1.4 kubernetes API
Kubernetes 控制面板的核心是 API 服务器。 API 服务器负责提供 HTTP API,以供用户、集群中的不同部分和集群外部组件相互通信。Kubernetes API 使你可以查询和操纵 Kubernetes API 中对象(例如:Pod、Namespace、ConfigMap 和 Event)的状态。可以有三种方式访问 kubenetes API:
- Restful API
- 命令行接口 CLI(kubectl)
- 客户端
1.5 kubernetes 对象管理
主要是通过 Kubenetes API 对 kuberntes 对象进行管理
1.5.1 kubernetes 对象
被 kubernetes 持久化的实体, 比如 Pod, Deployment, Service 等
1.5.2 kubernetes 对象描述
通常使用 .yaml 文件来描述有一个 kubernetes 对象, 但是必须包含以下字段
- apiVersion
- metadata 的 name
- spec
1.5.3 管理对象的方式
- 指令式命令
kubectl run nginx --image=nginx --namespace=test [--env="key=value"] [--port=port] [--replicas=replicas] [--dry-run=bool]
- 指令式对象配置
apiVersion: v1
metadata:
name: nginx
namespace: test
labels:
app: nginx
version: 1.7.6
spec:
containers:
image: nginx
kubectl create -f -
- 声明式对象配置
1.5.4 常用的对象属性
- metadata 的 name: 同类资源对象的名称唯一,名称只能包含小写字母、数字,以及 '-' 和 '.'
- 命名空间: 资源隔离的一种机制, 同一名字空间内的资源名称要唯一
- label"release" : "stable", "release" : "canary""environment" : "dev", "environment" : "qa", "environment" : "production""tier" : "frontend", "tier" : "backend", "tier" : "cache""partition" : "customerA", "partition" : "customerB""track" : "daily", "track" : "weekly"
(1) cm 进程通过字段对象 RC 上定义的 Label Selector 来筛选要监控的 pod 副本数量, 从而实现 pod 的数量始终符合预期.
(2) kube-proxy进程通过 Service 的 Label Selector 来选择对应的 Pod, 自动建立每个 Service 到对应的 Pod 的转发路由信息, 从而实现 Service 智能负载均衡
- annotation: 主要存放非标识的元数据
2 kubenetes 资源对象
2.1 Pod
是 K8s 里最基本的概念, 也是最小的操作单位.
资源文件定义, 以 nginx 为例:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: demo
labels:
app: nginx
environment: dev
version: 1.16.0-alpine
annottations:
creator: hhh
spec:
containers:
image: nginx:1.16.0-alpine
name: nginx-1.16
ports:
需要注意的是:
在设置资源的时候,通常是以千分之一的 CPU 配额为最小单位, 用 m 表示. 比如 一个容器的 CPU 的配额定义是100m~200m, 相当于占用 0.1~0.2个CPU. 数值是绝对值,不是相对值. 单核 和 多核 CPU 100m 一样的.
创建 pod, 使用 create 或者 apply
kubectl create -f nginx-pod.yaml
2.2 Replication Controller(已经被废弃)
定义一个期望的场景, 声明期望的 Pod 的数量,并在任意时刻都符合这个期望值
资源文件定义, 以 nginx 为例, 副本数量为 2:
apiVersion: v1
Kind: ReplicationController
metadata:
name: nginx-rc
namespace: demo
labels:
controller: rc
spec:
replicas: 2
selector:
app: nginx
version: 1.16.0-alpine
template:
metadata:
labels:
app: nginx
version: 1.16.0-alpine
spec:
containers:
- image: nginx:1.16.0-alpine
name: nginx-1.16
ports:
- containerPort: 80
2.2 Replication Set
和 Replication Controller 功能几乎相同, 在Label Selector前者只支持等式, 在 Replication Set 中可以支持表达式.同时功能上支持Pod的 数量变更和版本变更
.....
spec:
selector:
matchLabels:
app: nginx
matchExpressions:
{key: version, operator: In, values: [1.16.0-alpine, 1.17.0-alpine]}
......
数量变更
kubectl scale --replicas=3 rs/nginx-rs -n demo
版本变更
kubectl set image nginx=nginx:1.17.0-alpine rs/nginx-rs -n demo
2.3 Deployment
Deployment 为了更好的解决服务编排问题, 而且它非直接管理 Pod, 而是通过管理 ReplicaSet
除了支持 ReplicaSet 所有功能, 还支持以下主要功能:
- 支持Pod的发布的暂停和继续
- 支持版本的升级和回退
资源清单
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: demo
labels:
controller: deploy
spec:
replicas: 2
revisionHistoryLimit: 3, # default 10
pause: false, # default false
progressDeadlineSeconds: 50, # default 600
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 30%, # 最大额外存在的副本数
maxUnavailable: 30% # 最大不可用的副本数量
selector:
matchLabels:
app: nginx
version: 1.16.0-alpine
template:
metadata:
labels:
app: nginx
version: 1.16.0-alpine
spec:
containers:
- image: nginx:1.16.0-alpine
name: nginx
ports:
- containerPort: 80
deploy的扩缩容:
通过 scale 来实现扩缩容
kubectl scale deploy/nginx-deploy --replias=5 -n demo:
镜像的更新,一般支持两种策略
- 重建更新(recreate)
- 滚动更新(rollongUpdate)
kubectl set image nginx=nginx:1.16.0-alpine deploy/nginx-deploy -n demo
版本回退: kubectl rollout
常见的选项有:
- status
- history
- pause
- resume
- restart
- undo
在创建deployment 时, 启用recode 标记
kubectl create -f nginx-deploy.yaml -n demo --record
##查看部署版本历史
kubectl rollout history depploy/nginx-deploy -n demo
#版本回退
kubectl rollout undo deploy/nginx-deploy --to-reversion=1 -n demo
金丝雀发布
2.4 Service
service 类似于 所谓的 "微服务", service 定义了服务的同意访问入口, 而 RS 保证了服务能力和服务质量始终保持预期. 客户端通过 Service 访问 Pod, 具体则是由 kube-proxy来实现, 通过它来把具体的请求发送给 Pod.
服务清单
apiVersion: apps/v1
kind: Service
metadata:
name: nginx-service
namespace: demo
spec:
selector:
app: nginx
version: nginx:1.16.0-alpine
type: ClusterIP
ports:
nodePort: 31080
port: 80
targetPort: 80
service type 分为 四种:
- ClusterIP
- NodePort
- LoadBalance
- ExternalName(将集群的外部服务引入到集群内部)
2.5 Volume
Volume 是 Pod 中能够被多个容器访问的目录, 目前主要有以下几种类型:
- emptyDir
- hostPath
- nfs
- pv/pvc
...
spec:
volumes:
name: tmp-volume
emptydir: {}
containers:
image: nginx
name: nginx
ports:
...
spec:
volumes:
name: tmp-volume
hostPath:
path: /data
type: DirectoryOrCreate
containers:
image: nginx
name: nginx
ports:
type: DirectoryOrCreate, Directory, FileOrCreate, File, Socket, CharDevice, BlockDevice
2.6 Secret
对敏感数据的存储, 值是Base64加密的字符串, 它只会存储在节点的内存里, 不会落盘, 以下场景可以使用:
- 作为挂载到一个或多个容器上的卷 中的文件。
- 作为容器的环境变量。
- 由 kubelet 在为 Pod 拉取镜像时使用。
apiVersion: v1
apiVersion: v1
data:
mysql_password: YWRtaW4= #admin
mysql_url: YWRtaW4=
db_name: MWYyZDFlMmU2N2Rm #1f2d1e2e67df
kind: Secret
metadata:
name: mysql-secret
namespace: demo
type: Opaque
键值方式使用
apiVersion: v1
kind: Pod
metadata:
name: user-service-pod
namespace: demo
labels:
app: user-service
version: 1.0.0
envirionment: dev
spec:
containers:
name: user-serivce
image: user-service:1.0.0
env:
或 将所有环境变量都加载进来
apiVersion: v1
kind: Pod
metadata:
name: user-service-pod
namespace: demo
labels:
app: user-service
version: 1.0.0
envirionment: dev
spec:
containers:
name: user-serivce
image: user-service:1.0.0
envFrom:
也可以创建透明的数据的 secret
apiVersion: v1
kind: Secret
metadata:
name: public-data-secret
namespace: demo
stringData:
baidu_url: www.baidu.com
type: Opaque
2.7 ConfigMap
configMap 的数据是透明的, 不被加密的. 在以下场景中可以用 configmap 来存储信息,
- 在容器命令和参数内
- 容器的环境变量
- 在只读卷里面添加一个文件,让应用来读取
- 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
最简单的键值对方式:
apVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
baidu_url: www.baidu.com
使用:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: demo
spec:
selector:
app: nginx
version: 1.16.0-alpine
templates:
metadata:
labels:
app: nginx
version: 1.16.0-alpine
sepc:
containers:
- name: nginx-pod
image: nginx:1.16.0-alpine
env:
- name: BAIDU_URL
valueFrom:
configMapKeyRef:
name: cm-appvars
key: baidu_url
ports:
- containerPort: 80
以配置文件方式:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-user-upsteam-cm
namespace: demo
data:
user-upstram.conf: |
upstream user-service {
server 192.168.1.10 weight=1;
server 192.168.1.11 weight=2;
}
使用:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: demo
labels:
app: nginx
verison: 1.16.0-alpine
spec:
containers:
name: nginx
image: nginx:1.16.0-alpine
ports:
name: user-upstream-cm
configMap:
name: nginx-user-upsteam-cm
items:
当使用卷方式来存储数据时, 使用的 ConfigMap 被更新时,所投射的键最终也会被更新
使用 kubectl 来创建 configMap
#创建键值对configMap
kubectl create cm demo-cm -n demo --from-literal=baidu_url=www.baidu.com --form-literal=....
#创建文件
kubecttl create cm demo-cm -n demo --from-file=user-upstram.conf
#从文件目录中创建
#目录 config , 将会将这个目录的所有文件都会生成在 configMap 中
kubecttl create cm demo-cm -n demo --from-file=conf
//user-service-upstream.conf
kubectl create cm user-service-upstream-cm --file-from=user-service-upstream.conf -o yaml --dry-run=client > user-service-upstream-cm.yaml
实用技巧:
如果 pod 出现问题,可以用 describle 来查看信息,
它会记录 Pod 创建的时候各种事件信息,基本 80% 能看到原因
kubectl describle pod/{pod_name} -n {namespace}
查看 Pod 容器日志, 也是标准的日志输出
kubectl logs -f --tail 100 pod/{pod_name} {container_name} -n {namespace}
进入 Pod 容器内部
kubectl exec -it pod/{pod_name} -n {namespace} -- sh
做端口映射来做本地联调
kubectl port-forward pod/{pod_name} -n {namespace} {local_port}:{container_port}