目的
随着部署组件的增多和数据中心的增长, 配置以及管理并保持系统的正常运行变得复杂与困难.
在想要获得足够高的资源利用率并降低硬件成本情况下, 把组件部署在什么地方变得越来越难以决策.
自动化调度, 配置, 监管以及故障处理, 正式 k8s 解决的痛点
带来的便捷
为应用程序提供一致的环境, 便于今早发现问题
提供更加便捷的持续交付能力
组件介绍
控制面板用于控制集群工作, 其中包含的组件可以部署在多个节点上以保证高可用性
kubernetes API 服务器 |
控制面板中各个组件之间通信的桥梁 |
schedule |
应用调度器 |
controller manager |
执行集群级别功能, eg: 复制组件, 持续跟踪工作节点, 处理失败节点等 |
etcd |
分布式数据存储, 持久化存储集群配置 |
工作节点是运行容器化应用的机器
容器运行时 |
docker 等其他的容器类型 |
kubelet |
与 api 服务器通信, 并管理它所在节点的容器 |
kube-proxy |
负责组件之间的负载均衡网络流量 |
容器生命周期示例
docker build -t kubia . |
docker images | grep kubia |
docker run --name kubia-container -p 8080:8080 -d kubia |
curl localhost:8080 |
docker inspect kubia-container |
docker exec -ti kubia-container bash |
docker stop kubia-container |
docker rm kubia-container |
docker tag kubia mingch94/kubia |
docker push mingch94/kubia |
环境准备
yum install bash-completion |
安装 bash-completion |
source <(kubectl completion bash) |
生效 kubectl 的自动补全 |
alias k=kubectl |
设置 kubectl 的别称 |
source <(kubectl completion bash | sed s/kubectl/k/g) |
调整别称 k 的自动补全 |
alias kcd='k config set-context $(k config current-context) --namespace' |
设置切换名称空间别称 |
集群操作
kubectl cluster-info |
查看集群状态 |
kubectl get nodes |
列出集群节点 |
kubectl describe node docker-desktop |
查看集群节点更多信息 |
k run kubia --image=mingch94/kubia --port=8080 |
部署应用 |
k get po |
列出 pod |
k describe po kubia |
查看 pod 更多详细信息 |
k apply -f https://k8s.io/examples/controllers/replication.yaml |
创建 rc |
k get rc |
查看 rc 资源 |
k expose po kubia --type=LoadBalancer --name kubia-http |
创建服务, 对外暴露 pod |
k get svc |
查看服务对象 |
curl localhost:8080 |
访问服务 |
k scale rc kubia —replicas=3 |
水平扩展 pod 到 3 个 |
get pods -o wide |
展示更多列 |
k get po kubia -o yaml |
检查现有 pod 的 yaml 描述 |
k explain po |
解析 pod 定义 |
k explain pod.spec |
查看 spec 属性 |
k create -f kubia-manual.yaml |
从 yml 创建 pod |
kubectl logs kubia-manual -c kubia |
查看 pod 中容器 kubia 的日志 |
k port-forward kubia-manual 8888:8080 |
将本地 8888 流量转发到 pod 的 8080 端口 |
k get po --show-labels |
查看 pod 以及所有的 label |
k get po -L creation_method,env |
标签单独展示到对应列 |
k label po kubia-manual creation_method=manual |
创建标签 |
k label po kubia-manual-v2 env=debug --overwrite |
修改标签 |
k get po -l creation_method=manual |
指定标签值查询 pod |
k get po -l env |
指定标签名查询 pod |
k get po -l '!env' |
指定不包含 env 标签名查询 pod, 支持 !, in, notin |
k label node docker-desktop gpu=true |
给 node 添加指定的标签 |
k annotate pod kubia-manual mycompany.com/someannotation="foo bar" |
创建注解 |
k get ns |
查看集群中所有的命名空间 |
k get po -n kube-system |
查看指定命名空间的 pod |
k create ns custom-namespace |
创建命名空间 |
k config get-contexts |
查看当前上下文以及对应使用的名称空间 |
k delete pod kubia-gpu |
根据名称删除 pod |
k delete po -l creation_method=manual |
根据标签删除 pod |
k delete ns custom-namespace |
删除名称空间以及其下边所有的 pod |
k delete po --all |
删除所有的 pod |
k delete all --all |
删除当前名称空间下所有资源 |
k logs kubia-liveness --previous |
获取前一个容器日志 |
k edit rc kubia |
编辑 rc |
k delete rc kubia --cascade=false |
仅删除 rc, 保留 pod 正常运行 |
k get rs |
查看 rc |
k get ds |
查看 ds |
k get jobs |
查看 jobs |
k exec kubia-p5mz5 -- curl -s http://10.96.72.201 |
pod 中执行命令, - - 代表 kubectl 命令的结束, 如待执行命令无 - 参数可去掉 |
k exec -it kubia-72v4k -- bash |
交互式进入 pod 中执行命令 |
k get endpoints |
查看 endpoints 资源 |
k get nodes -o json |
json 方式展示 node 信息 |
k get po --all-namespaces |
显示所有 ns 下的的 pod |
k get ingresses |
查看 ingress 服务 |
k run dnsutils --image=tutum/dnsutils |
使用带 dns 的 pod |
k proxy |
通过 kube-proxy 与 api 服务器进行交互, 访问根路径可以查看当前支持的 api |
k create -f kubia-deployment-v1.yaml --record |
创建 deployment 资源, --record 表示记录版本号 |
k patch deployment kubia -p '{"spec": {"minReadySeconds": 10}}' |
设置 pod 创建完成后至少 10s 后才可用 |
k set image deployment kubia nodejs=luksa/kubia:v2 |
修改镜像为 luksa/kubia:v2 , 镜像名称为 nodejs |
k rollout status deployment kubia |
查看升级过程 |
k rollout undo deployment kubia |
回滚到上一个版本 |
k rollout undo deployment kubia --to-revision=1 |
回滚到指定版本 |
k rollout pause deployment kubia |
暂停滚动升级 |
k rollout resume deployment kubia |
取消滚动升级, 回滚到上一个版本 |
k apply -f kubia-deployment-v3-with-readinesscheck.yaml |
通过一个完整的 yml 定义来修改对象 |
当一个 pod 包含多个容器时候, 这些容器总是会运行在同一个节点. 也就是一个 pod 绝不会跨越多个工作节点
由于不能讲多个进程聚集在一个单独的容器中, 因此需要一种更高级的结构将容器绑定在一起, 也就是 pod. 可以把 pod 理解为现实世界中的主机
同一个 pod 中的容器共享相同的 ip 和端口, 因此可以通过 localhost 与同一个 pod 中的其他容器通信
pod 定义的几个主要部分
API 版本以及 YAML 描述的资源类型 |
apiVersion, kind |
metadata 包括 名称, 命名空间, 标签以及其他容器信息 |
name, namespace, labels |
spec 包括 pod 内容的实际说明(容器, 卷和其他数据) |
containers, volumes |
status 包含当前运行的 pod 的信息(所处条件, 容器描述和状态, 内部 IP 等) |
conditions, containerStatuses, phase, hostIP |
# Kubernets API 版本为 v1
apiVersion: v1
# 资源类型为 pod
kind: Pod
metadata:
# 资源名称为 kubia-maual
name: kubia-manual
spec:
containers:
# 指定镜像
- image: luksa/kubia
# 容器名称
name: kubia
ports:
# 容器监听的端口为 8080
- containerPort: 8080
protocol: TCP
名称空间不对正在运行的对象做任何隔离, 同时名称空间之间的网络是否隔离取决于 k8s 采取的网络解决方案
如果需要部署的应用自动保持运行且保持健康, 无任何手动干预, 则不能直接创建 pod, 而是创建 rc 或 deployment 这样的资源来管理 pod.
直接创建的 pod 只会被 k8s 监控失败重启(节点上的 Kubelet 操作的), 但是整个节点失败, 无法被新节点替换
探测容器机制
HTTP GET 探针 |
对容器的 IP 地址执行 HTTP GET 请求. 响应状态码为 2xx 或 3xx 时候则认为探测成功 |
TCP 套接字探针 |
尝试与容器指定端口建立 TCP 连接. 连接成功建立则探测成功. 否则容器重启 |
Exec 探针 |
在容器内执行任意命令, 并检车命令的退出状态码. 状态码为 0 则探测成功 |
ReplicationController 三要素
label selector |
标签选择器, 用于确定 rc 作用域中有哪些 pod |
replica count |
副本个数, 指定应运行的 pod 数量, 会影响现有的 pod |
pod template |
pod 模板, 用于创建新的 pod 副本 |
rc 版本
apiVersion: v1
# rc 类型
kind: ReplicationController
metadata:
# rc 名称
name: kubia
spec:
# 副本数量
replicas: 3
# 标签选择器
selector:
app: kubia
# 创建新 pod 时候的模板
template:
metadata:
labels:
# 模板中的标签必须与标签选择器中的一致, 避免无休止的创建 pod
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia
ports:
- containerPort: 8080
rs 版本
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: kubia
spec:
replicas: 3
selector:
matchExpressions:
- key: app
operator: In
values:
- kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia
ds 版本
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ssd-monitor
spec:
selector:
matchLabels:
app: ssd-monitor
template:
metadata:
labels:
app: ssd-monitor
spec:
nodeSelector:
disk: ssd
containers:
- name: main
image: luksa/ssd-monitor
batch-job 版本
apiVersion: batch/v1
kind: Job
metadata:
name: batch-job
spec:
template:
metadata:
labels:
app: batch-job
spec:
restartPolicy: OnFailure
containers:
- name: main
image: luksa/batch-job
service 版本
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
# 会话亲和性, 同一个clientIP 的流量会被发送到同一个 pod
sessionAffinity: ClientIP
ports:
# 服务可用端口
- port: 80
# 服务将连接转发到的容器端口
targetPort: 8080
selector:
# 具有 app=kubia 标签的 pod 都属于该服务
app: kubia
内部集群测试服务
创建 pod |
请求发送到服务的集群 ip 并记录响应, 可通过 pod 的日志查看响应 |
ssh 到任意节点 |
在远程 node 上执行 curl |
kubectl exec |
在一个已经存在的 pod 中执行 cul 命令 |
将服务暴露给外部客户端
NodePort |
集群节点在节点上打开一个端口, 并将该端口上的流量重定向到基础服务 |
LoadBalance |
NodePort 类型的一种扩展, 使得服务可以通过专用的负载均衡器访问 |
Ingress |
通过一个 IP 地址公开多个服务, 运行在 7 层网络 |
几种常见的卷类型
更多详细见 https://kubernetes.io/docs/concepts/storage/volumes/
emptyDir |
存储临时数据的简单空目录 |
hostPath |
将目录从工作节点的文件系统挂载到 pod 中, 指向节点文件系统上特定的文件或目录. 持久性的卷, 但是 pod 一旦调度到其它节点就会有问题 |
gitRepo |
检出 git 仓库的内容来初始化券 |
nfs |
挂载到 pod 的 nfs 共享卷 |
gcePersistentDIsk |
google 的高效能存储磁盘卷 |
awsElasticBlockStore |
aws 的服务弹性块存储卷 |
azureDisk |
Microsoft Zaure 磁盘卷 |
configMap, secret, downwardAPI |
将 k8s 部分资源和集群信息公开给 pod 的特殊卷 |
persistentVolumeClaim |
预置或动态配置的持久性存储类型 |
emptyDir 卷使用
apiVersion: v1
kind: Pod
metadata:
name: fortune
spec:
containers:
- image: luksa/fortune
name: html-generator
volumeMounts:
# 名为 html 的卷挂载在容器 /var/htdocs, 可读可写
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
# 名为 html 的卷挂载在容器 /usr/share/nginx/html, 只读
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
# 名为 html 的卷, 挂载在上面两个容器中
- name: html
emptyDir: {}
gitRepo 卷使用
apiVersion: v1
kind: Pod
metadata:
name: gitrepo-volume-pod
spec:
containers:
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
gitRepo:
repository: https://github.com/chaimcode/kubia-website-example.git
revision: master
directory: .
api 服务使用
k proxy
curl http://localhost:8001
{
"paths": [
"/api",
"/api/v1",
"/apis",
"/apis/",
"/apis/admissionregistration.k8s.io",
"/apis/admissionregistration.k8s.io/v1",
"/apis/admissionregistration.k8s.io/v1beta1",
"/apis/apiextensions.k8s.io",
"/apis/apiextensions.k8s.io/v1",
"/apis/apiextensions.k8s.io/v1beta1",
"/apis/apiregistration.k8s.io",
"/apis/apiregistration.k8s.io/v1",
"/apis/apiregistration.k8s.io/v1beta1",
"/apis/apps",
"/apis/apps/v1",
"/apis/authentication.k8s.io",
"/apis/authentication.k8s.io/v1",
"/apis/authentication.k8s.io/v1beta1",
"/apis/authorization.k8s.io",
"/apis/authorization.k8s.io/v1",
"/apis/authorization.k8s.io/v1beta1",
"/apis/autoscaling",
"/apis/autoscaling/v1",
"/apis/autoscaling/v2beta1",
"/apis/autoscaling/v2beta2",
"/apis/batch",
"/apis/batch/v1",
"/apis/batch/v1beta1",
"/apis/certificates.k8s.io",
"/apis/certificates.k8s.io/v1beta1",
"/apis/compose.docker.com",
"/apis/compose.docker.com/v1alpha3",
"/apis/compose.docker.com/v1beta1",
"/apis/compose.docker.com/v1beta2",
"/apis/coordination.k8s.io",
"/apis/coordination.k8s.io/v1",
"/apis/coordination.k8s.io/v1beta1",
"/apis/events.k8s.io",
"/apis/events.k8s.io/v1beta1",
"/apis/extensions",
"/apis/extensions/v1beta1",
"/apis/networking.k8s.io",
"/apis/networking.k8s.io/v1",
"/apis/networking.k8s.io/v1beta1",
"/apis/node.k8s.io",
"/apis/node.k8s.io/v1beta1",
"/apis/policy",
"/apis/policy/v1beta1",
"/apis/rbac.authorization.k8s.io",
"/apis/rbac.authorization.k8s.io/v1",
"/apis/rbac.authorization.k8s.io/v1beta1",
"/apis/scheduling.k8s.io",
"/apis/scheduling.k8s.io/v1",
"/apis/scheduling.k8s.io/v1beta1",
"/apis/storage.k8s.io",
"/apis/storage.k8s.io/v1",
"/apis/storage.k8s.io/v1beta1",
"/healthz",
"/healthz/autoregister-completion",
"/healthz/etcd",
"/healthz/log",
"/healthz/ping",
"/healthz/poststarthook/apiservice-openapi-controller",
"/healthz/poststarthook/apiservice-registration-controller",
"/healthz/poststarthook/apiservice-status-available-controller",
"/healthz/poststarthook/bootstrap-controller",
"/healthz/poststarthook/ca-registration",
"/healthz/poststarthook/crd-informer-synced",
"/healthz/poststarthook/generic-apiserver-start-informers",
"/healthz/poststarthook/kube-apiserver-autoregistration",
"/healthz/poststarthook/rbac/bootstrap-roles",
"/healthz/poststarthook/scheduling/bootstrap-system-priority-classes",
"/healthz/poststarthook/start-apiextensions-controllers",
"/healthz/poststarthook/start-apiextensions-informers",
"/healthz/poststarthook/start-kube-aggregator-informers",
"/healthz/poststarthook/start-kube-apiserver-admission-initializer",
"/livez",
"/livez/autoregister-completion",
"/livez/etcd",
"/livez/log",
"/livez/ping",
"/livez/poststarthook/apiservice-openapi-controller",
"/livez/poststarthook/apiservice-registration-controller",
"/livez/poststarthook/apiservice-status-available-controller",
"/livez/poststarthook/bootstrap-controller",
"/livez/poststarthook/ca-registration",
"/livez/poststarthook/crd-informer-synced",
"/livez/poststarthook/generic-apiserver-start-informers",
"/livez/poststarthook/kube-apiserver-autoregistration",
"/livez/poststarthook/rbac/bootstrap-roles",
"/livez/poststarthook/scheduling/bootstrap-system-priority-classes",
"/livez/poststarthook/start-apiextensions-controllers",
"/livez/poststarthook/start-apiextensions-informers",
"/livez/poststarthook/start-kube-aggregator-informers",
"/livez/poststarthook/start-kube-apiserver-admission-initializer",
"/logs",
"/metrics",
"/openapi/v2",
"/readyz",
"/readyz/autoregister-completion",
"/readyz/etcd",
"/readyz/log",
"/readyz/ping",
"/readyz/poststarthook/apiservice-openapi-controller",
"/readyz/poststarthook/apiservice-registration-controller",
"/readyz/poststarthook/apiservice-status-available-controller",
"/readyz/poststarthook/bootstrap-controller",
"/readyz/poststarthook/ca-registration",
"/readyz/poststarthook/crd-informer-synced",
"/readyz/poststarthook/generic-apiserver-start-informers",
"/readyz/poststarthook/kube-apiserver-autoregistration",
"/readyz/poststarthook/rbac/bootstrap-roles",
"/readyz/poststarthook/scheduling/bootstrap-system-priority-classes",
"/readyz/poststarthook/start-apiextensions-controllers",
"/readyz/poststarthook/start-apiextensions-informers",
"/readyz/poststarthook/start-kube-aggregator-informers",
"/readyz/poststarthook/start-kube-apiserver-admission-initializer",
"/readyz/shutdown",
"/version"
]
}
deployment 版本
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
selector:
matchExpressions:
- key: app
operator: In
values:
- kubia
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v1
name: nodejs
deployment 需注意的属性
minReadySeconds |
pod 最少可用等待时间, 即使就绪探针返回成功, 也需要等改时间 |
revisionHistoryLimit |
限制历史版本数量 |
maxSurge |
滚动升级时候, 期望的副本数, 默认 25%, 则如果副本数为 4, 则滚动期间不会超过 5 个 pod 实例 |
maxUnavailable |
滚动升级时候, 允许最多多少 pod 不可用状态. |