k8s 核心概念描述
k8s 管理
– 前言
- 主要是k8s核心概念的描述随笔…
1 命令行管理
- kubectl 命令行管理工具
- 管理应用程序生命周期
- 远程连接k8s 集群
1.1 基础命令概要
类型 | 命令 | 描述 |
---|---|---|
基础命令 | explain | 文档参考资料 |
- | get | -o wide 显示一个或多个资源 |
部署命令 | rollout | 管理资源的发布 |
- | scale | 扩容或缩容Pod 数量 |
集群管理命令 | cluster-info | 显示集群信息 |
- | certificate | 修改证书 |
- | cordon | 标记节点不可调度 |
- | uncordon | 标记节点可调度 |
- | drain | 驱逐节点上的应用,准备维护下线 |
- | taint | 修改节点taint 标记 |
故障诊断调试 | describe | 显示特定资源或资源组的详细信息 |
- | logs | 在一个pod种打印一个容器日志。如果pod 只有一个容器,容器名可选 |
- | exec | 执行命令到容器 |
高级命令 | apply | 通过文件名或标准输入对资源应用配置 |
- | patch | 使用补丁修改,更新资源的字段 |
其他命令 | help | 所有命令帮助 |
1.2 基础命令举例
# 创建
kubectl run nginx --replacs=3 --image=nginx:1.14 --port=80
kubectl get pods,deploy
# 发布
kubectl expose deployment nginx --port=80 --type=NodePort --target-port=80 --name=nginx-service
kubectl get service
# 更新
kubectl set image deployment/nginx nginx:1.15
# 回滚
kubectl rollout history deployment/nginx
kubectl rollout undo deployment/nginx
# 删除
kubectl delete deployment/nginx
kubectl delete svc/nginx-service
1.3 kubectl 远程管理配置
1.3.1 生成访问的证书
[root@master01 k8s]# cat k8s_config.sh
#!/bin/bash
cat > admin-csr.json <<EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
# 设置集群参数
kubectl config set-cluster kubernetes \
--server=https://10.199.204.181:6443 \
--certificate-authority=ca.pem \
--embed-certs=true \
--kubeconfig=config
# 设置客户端认证参数
kubectl config set-credentials cluster-admin \
--certificate-authority=ca.pem \
--embed-certs=true \
--client-key=admin-key.pem \
--client-certificate=admin.pem \
--kubeconfig=config
# 设置上下文参数
kubectl config set-context default \
--cluster=kubernetes \
--user=cluster-admin \
--kubeconfig=config
# 设置默认上下文
kubectl config use-context default --kubeconfig=config
1.3.2 远程访问实现
# 认证文件+ kubectl 命令实现访问
kubectl --kubeconfig=./config get node
# home 目录创建 .kube 目录
kubectl get node (直接访问)
2 yaml 配置文件使用
- 通过文件来描述资源对象(留存复用)
- 缩进表示层级关系
- “#” 表示注释
- “—” 表示一个yaml 开始
#run 命令生成 kubectl run --image=nginx my-deploy -o yaml --dry-run > my-deploy.yaml # get 命令导出 kubectl get my-deploy/nginx -o=yaml --export > my-deploy.yaml # Pod 字段帮助 kubectl explain pods.spec.containers
3 Pod 进一步理解
3.1 Pod包含容器
- Infrastructure Container: 基础容器
- 维护整个Pod 网络空间
- InitContainers: 初始化容器
- 先于业务容器开始执行的容器
- Containers: 业务容器
- 并行启动
docker ps 可以查看 pause 基础容器 启动容器的基础模板
- 并行启动
- Pod 优势(共享网络,存储)
- 两个应用之间发生文件交互
- 通过127.0.0.1 或socket 实现通讯
- 两个应用频繁调用
3.2 Pod 中容器拉去策略于状态
- IfNotPresent:默认值,宿主机存在就不拉去镜像
- Always: 每次创建Pod 都会重新拉取镜像
- Never: Pod 永远不会主动拉去镜像
- Pending, Running, Failed, Succeeded, Unknown
- 自建harbor 镜像拉取(docker daemon.json 添加可信任)
# 部署yaml 中添加凭据 imagePullSecrets: - name: myregistrykey # 主机查看认证信息 cat .docker/config.json # 认证信息编码 cat .docker/config.json | base64 -w 0 # 创建凭据yaml 文件 [root@node01 opt]# cat /root/.docker/registry-pull-secret.yml apiVersion: v1 kind: Secret metadata: name: registry-pull-secret data: .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxMC4xOTkuMjA0LjE3NSI6IHsKCQkJImF1dGgiOiAiWVdSdGFXNDZkMkZ1WkdGMmJUSXdNVGs9IgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOC4wOS42IChsaW51eCkiCgl9Cn0= type: kubernetes.io/dockerconfigjson # 查看信息 kubectl get secret registry-pull-secret --namespace=default -o yaml # 不同 Namespace , secrets 可以同名 # 在secrets创建后可以修改一些内容 # 但不能修改Namespace。 所以,必须在创建时准确指定。
3.3 Pod 资源限制
- Pod 与 Container 的资源请求和限制
request: memory: "64Mi" cpu: "250m" # 一核cpu25% limits: memory: "128Mi" cpu: "500m" # 查看信息 kubectl describe pod my-pod kubectl describe nodes 10.199.204.176
3.4 Pod 重启策略
- restartPolicy (字段定义)
- Always: 默认策略,容器退出,总是重启
- OnFailure: 异常退出(状态码非0),重启(计划任务)
- Never: 从不重启
3.5 Pod 健康检查
- Probe 两种类型
- livenessProbe(检查失败,根据规则操作)
- readinessProbe (检查失败,k8s把Pod 从service endpoints 剔除)
- Probe 三种检查方式
- httpGet(发送http ,请求200-400表示成功)
- exec(执行shell 状态码0 为成功)
- tcpSocket(发去TCP Socket 建立成功)
# kubectl get ep (service 通过 endpoint 管理后端IP) livenessProbe: exec: command: - cat - /tmp/healthy initialDeplaySeconds: 5 periodSeconds: 5 --- tcpSocket: port: 8080 --- httpGet: path: /status port: 80 httpHeaders: - name: X-Custom-Header value: Awesome
3.5 Pod 调度约束
- 同一个k8s 集群放在不同的位置满住部门或一些特殊场景要求
- 创建流程
- 创建完成 ,Pod 信息会记录在etcd 中,运行在那台主机,状态,便于查看
- nodeName (指定Node 名称,跳过打分,指定部署)
- nodeSelector (指定匹配Label 的Node 上)
# 给几点打标签 kubectl label nodes 10.199.204.176 env_role=dev # 查看标签 kubectl get nodes --show-labels # 查看调度 kubectl describe pod my-pod nodeName: 10.199.204.176 --- nodeSelector: env_role: dev
3.6 故障排查
状态值 | 描述 |
---|---|
Pending | Pod 创建已经提交到kubernetes。但是,因为某种原因而不能顺利创建。例如:下载镜像失败,调度不成功 |
Running | Pod 已经绑定到一个节点,并且已经创建了所有容器。至少有一个容器正在运行,或正在启动正在运行 |
Succeeded | Pod 中所有容器都已经成功终止,不会重启 |
Failed | Pod 说有容器均已经终止,且至少有一个容器已经在故障中终止。要么容器非零退出,要么被系统终止 |
Unknown | 由于某种原因apiserver 无法获取Pod 的状态,通常是由于Master 与Pod 所在主机kubelet 通讯出现问题 |
# 常用命令
# 查看事件
kubectl describe TYPE/NAME
# 查看日志
kubectl logs TYPE/NAME [-c CONTINER]
# 进入容器中进行详细查看
kubectl exec -it POD [-c CONTINER] --COMMAND [args...]
4 k8s 控制器
- Deployment (解决 “无状态” 应用落地而产生的)
- StatefulSet (解决 “有状态” 应用落地而产生的)
- DaemonSet (每个node里部署)
- Job
- CronJob
4.1 Deployment 使用
-
标签与标签选择器的使用
-
部署无状态应用
-
管理Pod 和 ReplicaSet
-
管理顺序
-
-
部署,副本,升级,回滚
-
声明式更新
-
web 服务,微服务使用
-
yaml 文件组成
- 控制器定义
- 控制器对象
# yaml 模板生成 kubectl create deployment nginx --image=nginx --dry-run -o yaml # 手动暴露服务(service 使用) kubectl expose --name=web deployment nginx --port=80 --target-port=8080 --type=NodePort # 查看 kubectl get deployment,svc,pod # 模板实例 [root@master01 opt]# cat nginx-pod.yaml apiVersion: v1 kind: Deployment metadata: name: nginx namespace: default spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: imagePullSecrets: - name: registry-pull-secret containers: - name: nginx image: nginx ports: - conrainerPort: 80
4.2 Deployment 升级回滚,弹性伸缩
-
默认滚动更新
# 手动升级 kubectl set image deployment/web nginx:1.15 #滚动更新 (创建新的rs 实现扩容,新老版本共存) - apply声明式更新,修改yaml 文件 # 回滚指定版本 kubectl rollout undo deployment/web --revision=2 # 扩容 kubectl scale deployment web --replicas=5
5 应用发布,实现外界连通
5.1 Service
5.1.1 存在的意义
- 提供对外访问入口(实现负载均衡)
- 动态感知后端pod (防止pod 失联)
- CLusterIP (集群内部使用)
- NodePort (集群外访问,通过nodeIP + 端口,同时也会有ClusterIP,四层负载均衡)
- LoadBalancer (公有云,四层负载均衡)
- 网络模式
- iptables
- IPVS
5.1.2 模板实例
- 在api-server 的配置文件中指定service-cluster-IP + service-port 定义
# 查看状态 kubectl get svc,ep kubectl get pod -l app=nginx -o wide kubectl describe svc my-service --- apiVersion: v1 kind: Service metadata: name: my-service namespace: default spec: clusterIP: 10.0.0.1 ports: - name: http port: 80 protocol: TCP targetPort: 80 nodePort: 30008 selector: app: nginx
5.1.3 代理模式
- kube-proxy 实现网络代理(kube-proxy 配置文件中配置)
-
iptables (用户态)
-
ipvs
# 模块加载(centos7 默认加载) [rroot@node01 ~]# vim ipvs.sh #!/bin/bash ipvs_mods_dir="/usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs" for i in $(ls $ipvs_mods_dir|grep -o "^[^.]*") do /sbin/modinfo -F filename $i &>/dev/null if [ $? -eq 0 ];then /sbin/modprobe $i fi done # 查看是否加载 lsmod | grep ip_vs # iptables # 查看所有规则 (至上而下的访问,非增量方式,匹配延时) iptables-save | grep 10.0.0.8 #ipvs (内核态,四层转发LVS) ipvsadm -ln 调度算法: rr, wrr, lc, wlc, ip hash 配置文件中添加:(kube-proxy 配置文件中添加) --ipvs-scheduler=wrr
-
5.1.4 coreDNS 的意义
-
clusterIP 也是变化的, 通过解析固定访问方式。github 网址
-
DNS 服务监视Kubernetes API,为每一个Service 创建DNS 记录用于域名解析
ClusterIP A my-svc.my-namespace.svc.cluster.local
-
coredns 配置的ip 与kubelet配置文件 配置相同
-
coredns 配置的domain 与kubelet配置文件 配置相同
# 测试是否成功 # 启动一个容器 kubectl run -it --image=busybox:1.28.4 --rm --restart=Never sh # 容器内部测试 / # nslookup kubernetes Server: 10.0.0.2 Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local # 跨命名空间 nslookup my-service.default
5.2 Ingress
- 全局负载均衡器(七层,四层 负载均衡)
- Ingress Controller (控制器通过service想关联)
- ingress-nginx
- traefik
- 修改使用主机网络:hostNetwork: true
- ingress-nginx github 地址
- ingress-nginx 所在节点配置解析
5.2.1 模板实例
# http
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
reules:
- host: example.foo.com
http:
paths: /
- backend:
serviceName: service1
servicePort: 80
# 查看实现方式
进入容器中
cat /etc/nginx/nginx.conf
# https
# 证书生成与secert创建
[root@master01 ssl]# cat self_certs.sh
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
cat > ca-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
cat > sslexample.foo.com-csr.json <<EOF
{
"CN": "sslexample.foo.com",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes sslexample.foo.com-csr.json | cfssljson -bare sslexample.foo.com
#kubectl create secret tls sslexample-foo-com --cert=sslexample.foo.com.pem --key=sslexample.foo.com-key.pem
---
# 部署https
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- sslexample.foo.com
secreName: testsecret-tls
reules:
- host: example.foo.com
http:
paths: /
- backend:
serviceName: service1
servicePort: 80
6 存储卷
- vilume 的存在使得pod 漂移到任何节点数据的访问
- 卷来源 (spec.volume)
- 挂载点 (spec.containers.volumeMounts)
6.1 emptyDir
- Pod 删除该卷也会被删除
- Pod 中容器之间数据共享
apiversion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: write
image: centos
command: ["bash","-c","for i in {1..10};do echo $i >> /data/hello;sleep 1;done"]
volumeMounts:
- name: data
mountPath: /data
- name: read
image: centos
command: ["bash", "-c", "tail -f /data/hello"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}
6.2 hostPath
- 挂载Node 文件系统上文件或者目录到Pod 中的容器
- Pod 访问容器需要访问宿主机文件
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
contrainers:
- name: busybox
image: busybox
args:
- /bin/sh
- -c
- sleep 36000
volumeMounts:
- name: data
mountPath: /data
vilumes:
- name: data
hostPath:
path: /tmp
type: Directory
6.3 NFS 网络挂载
apiVersion: apps/v1neta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMount:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: wwwroot
nfs:
srver: 10.199.204.177
path: /data/nfs
7 RBAC 简单实例
#授权apiserver 可以查看日志
[root@master01 opt]# more apiserver-to-kubelet-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
- pods/log
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:kube-apiserver
namespace: ""
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-apiserver-to-kubelet
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kubernetes
8 上线准备
- 了解业务架构
- 需要的服务分类,有状态,无状态
- 服务之间调用关系,通讯方式
- 资源预估,下线上线
- namespace 进行租户的隔离
- 发布方式,如何外部访问
- 项目基础镜像构建
- yaml 文件编写部署
8.1 Tips
# 拉去私有仓库需要创建认证信息:
kubectl create secret docker-registry registry-pull-secret --docker-username=joker --docker-password=joker --docker-email=joker@joker.com --docker-server=registry.docker.com -n joker
# yaml 中的配置
imagePullSecrets:
- name: registry-pull-secret
# 数据库部署 StatefulSet
clusterIP: None (直接访问减少网络转发)
# 不同namespace 访问
db-0.mysql.default (pod + service + namespace 可以访问)
8.2 资源监控
- 集群监控
- 节点资源利用率
- 节点数
- 运行Pods
- Pod 监控
- Kubernetes 指标
- 容器指标
- 应用程序
- 日志监控
- k8s 系统的组件日志
- k8s cluster 里面部署的应用程序日志
- 标准输出
- 日志文件
8.2.1 docker 对日志接管
- 标准输出stdout (通过docker logs 可以查看)
- 通过守护进程读取 /var/log/containers/ID.json
- 存储的docker 中(随着容器的消亡,而消亡)
8.2.2 k8s 管理日志方案
- ELK 方案使用
- graylog 日志系统
8.2.2.1 方案一Node 部署日志收集程序
- 应用无入侵,不支持多行,容器内日志需要挂载
- DaemonSet 方式部署日志收集程序
- /var/lib/kubelet/pods/ID*/volumes/kubernetes.io~empty-dir/ (emptyDir挂载空卷)
- /var/lib/docker/containers/*/ *json.log
- Pod 中容器日志目录挂载到宿主机统一目录 (hostPath)
- 日志覆盖问题(开发根据容器名称命名日志文件)
8.2.2.2 方案二Pod 附加专用日志收集程序
- 增加资源消耗,手动打标签日志源
- 使用emptyDir 共享日志目录
- 日志收集程序进行收集
8.2.2.3 方案二应用直接推送日志
- 应用入侵,需要开发配合
- 脱离k8s
8.2.3 filebeat 配置方案(直接连接ES)
- 处理器使用自动添加k8s 属性
- 日志路径 (* 递归匹配log 文件)
- 标准输出(/var/lib/docker/containers hostPath 实现)
- 格式化日志(正则匹配,logstash 优先)
- 日志源(标记那个应用,动态获取)
- 容器
- 命名空间
- service
- 项目
8.2.4 kibana 配置
- 索引模式创建(时间搓筛选)
- discover 查看日志
- 日志量过大,加logstash过滤, 进行有用的日志进行入库