1.K8S简单诉述
• Kubernetes是Google在2014年开源的一个容器集群管理系统,Kubernetes简称K8S。
• Kubernetes用于容器化应用程序的部署,扩展和管理,目标是让部署容器化应用简单高效。
官方网站:http://www.kubernetes.io 官方文档:https://kubernetes.io/zh/docs/home 重点看概念和任务
2.K8S架构和组件
Master组件
kube-apiserver:Kubernetes API,集群的统一入口,各组件协调者,以RESTful API提供接口服务,所有对象资源的增删改查和监听操作都交给 APIServer处理后再提交给Etcd存储。
kube-controller-manager:处理集群中常规后台任务,一个资源对应一个控制器,而 ControllerManager就是负责管理这些控制器的。例如 Deployment、Service
kube-scheduler :根据调度算法为新创建的Pod选择一个Node节点,可以任意部署, 可以部署在同一个节点上,也可以部署在不同的节点上。
etcd:分布式键值存储系统。用于保存集群状态数据,比如Pod、Service 等对象信息。
Node组件
kubelet :kubelet是Master在Node节点上的Agent,管理本机运行容器的生命周 期,比如创建容器、Pod挂载数据卷、下载secret、获取容器和节点状态 等工作。kubelet将每个Pod转换成一组容器。
kube-proxy :在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作。
第三方容器引擎,例如docker、containerd、podman 容器引擎,运行容器。
3.K8S部署
kubeadm :Kubeadm是一个工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。 部署地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
二进制:从官方下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。 下载地址:https://github.com/kubernetes/kubernetes/releases
第三方工具或者Web
安装链接:https://www.cnblogs.com/CGCong/p/15621946.html
4.K8S网络组件
部署网络组件的目的是打通Pod到Pod之间网络、Node与Pod之间网络,从而集群中数据包可以任意传输,形成了一 个扁平化网络。
主流网络组件有:Flannel、Calico等 而所谓的CNI( Container Network Interface,容器网络接口)就是k8s对接这些第三方网络组件的接口。
5.Kubeconfig配置文件
cat /root/.kube/config
其他节点使用这个配置文件也可以使用master的命令api,但它不是master.
拷贝这个config到其他节点,然后使用 kubectl --kubeconfig=/home/config get node
也可以在家目录的同样路径下创建目录文件,--kubeconfig= 默认是/root/.kube/config
6.Kubectl命令行管理工具
https://kubernetes.io/zh/docs/reference/kubectl/overview/
补全依赖包下载:yum install bash-completion 生效:source <(kubectl completion bash) 重启客户端
7.Kubectl快速部署应用
#使用Deployment控制器部署镜像: kubectl create deployment cgcnginx --image=nginx kubectl get deploy,pods #使用Service将Pod暴露出去: kubectl expose deployment cgcnginx --port=81 --type=NodePort --target-port=80 --name=cgcnginx kubectl get service #访问应用: http://NodeIP:Port # 端口随机生成,通过get svc获取 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cgcnginx NodePort 10.110.220.181 <none> 81:30190/TCP 7m36s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 26h --port=81 集群内部使用端口 --target-port=80 容器中应用端口 --type=NodePort 类型
8.Kubectl基本资源
# 查看pod详情信息,主要多了Pod IP、所属节点 [root@k8s1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES cgcnginx-865d746c47-2mz74 1/1 Running 0 2d3h 10.244.219.6 k8s3 <none> <none> # 查看service关联的pod [root@k8s1 ~]# kubectl get endpoints NAME ENDPOINTS AGE cgcnginx 10.244.219.6:80 2d2h kubernetes 192.168.137.3:6443 3d5h # 查看Pod标签 [root@k8s1 ~]# kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS cgcnginx-865d746c47-2mz74 1/1 Running 0 2d3h app=cgcnginx,pod-template-hash=865d746c47 # -o yaml将一个资源导出yaml格式(配置文件) [root@k8s1 ~]# kubectl get service cgcnginx -o yaml |grep -A 2 selector selector: app: cgcnginx sessionAffinity: None
kubectl get pods -o wide # 查看pod详情信息,主要多了Pod IP、所属节点
kubectl get endpoints # 查看service关联的pod
kubectl get pods --show-labels # 查看Pod标签
kubectl get service cgcnginx -o yaml |grep -A 2 selector # -o yaml将一个资源导出yaml格式(配置文件)
命名空间(Namespace):
Kubernetes将资源对象逻辑上隔离,从而形成多个虚拟集群。
应用场景:
• 根据不同团队划分命名空间
• 根据项目划分命名空间
kubectl get namespace
• default:默认命名空间
• kube-system:K8s系统方面的命名空间
• kube-public:公开的命名空间,谁都可以访问,
• kube-node-lease:K8s内部命名空间
两种方法指定资源命名空间:
• 命令行加 -n
• yaml资源元数据里指定namespace字段
• 命令行加 -A 指所有namespace
[root@k8s1 ~]# kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE calico-kube-controllers-56b8f699d9-5tmdl 1/1 Running 0 2d5h calico-node-5bnx8 1/1 Running 0 3d5h calico-node-8sx8p 1/1 Running 0 3d5h calico-node-jtms5 1/1 Running 0 3d5h coredns-545d6fc579-5ns65 1/1 Running 0 2d5h coredns-545d6fc579-72h4f 1/1 Running 0 2d5h etcd-k8s1 1/1 Running 0 3d5h kube-apiserver-k8s1 1/1 Running 0 3d5h kube-controller-manager-k8s1 1/1 Running 0 2d8h kube-proxy-46p76 1/1 Running 0 3d5h kube-proxy-88r8n 1/1 Running 0 3d5h kube-proxy-mr5zm 1/1 Running 0 3d5h kube-scheduler-k8s1 1/1 Running 0 2d8h
[root@k8s1 ~]# kubectl logs calico-node-jtms5 -n kube-system
kubectl create namespacke a kubectl create namespacke b kubectl get pods -n a kubectl get pods -n b kubectl create deployment cgcnginx1 --image=nginx -n a kubectl get pods -n a
kubectl get pods -A 所有命名空间下的pods
kubectl delete <资源类型> <资源名称> # 删除资源
kubectl api-resources #列出资源命令名称和缩写
kubectl api-resources |grep pod
9.查看资源集群状态
查看master组件状态: kubectl get cs 查看node状态: kubectl get node 查看Apiserver代理的URL: kubectl cluster-info 查看集群详细信息: kubectl cluster-info dump 查看资源的详细: kubectl describe <资源类型> <名称名称> 查看资源信息: kubectl get <资源> #-o wide,-o yame,
#执行时会提示错误:error: Metrics API not available
#这是因为这个命令需要由metric-server服务提供数据,而这个服务默认没 有安装,还需要手动部署下。
查看Node资源消耗:
kubectl top node
查看Pod资源消耗:
kubectl top pod
监控集群资源利用率获取流程
#kubectl top -> apiserver -> metrics-server(pod) -> 所有节点kubelet(cadvisor指标接口) -> 所有容器资源利用率
10.metric-server部署
# wget https://github.com/kubernetes-sigs/metricsserver/releases/download/v0.3.7/components.yaml # vi components.yaml ... containers: - args: - --cert-dir=/tmp - --secure-port=4443 - --kubelet-preferred-address-types=InternalIP - --kubelet-use-node-status-port - --kubelet-insecure-tls image: lizhenliang/metrics-server:v0.4.1 ... 增加一个kubelet-insecure-tls参数,这个参数作用是告诉metrics-server不验证kubelet提供的https证书 # kubectl apply -f components.yaml
检查是否部署成功: #kubectl get pods -n kube-system #kubectl get apiservices |grep metrics #kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes
使用:
#kubectl top nodes --use-protocol-buffers #去掉警告,不加也没关系
#kubectl top pods
11.K8s组件日志
Pod部署的组件: #kubectl get pods -n kube-system #kubectl logs metrics-server-84f9866fdf-9czxr -n kube-system -f #-f就是实时的
kubectl logs(获取容器标准输出的日志)-> apiserver -> kubelet -> docker(接管了容器标准输出并写到文件中持久化) -> 获取某个容器的日志 除了kubelet之外,其他的组件都是pod运行的,所以查看kubelet用 systemd守护进程管理的组件: journalctl -u kubelet journalctl -u kubelet -r #-r参数表示反序输出,(从新到旧) 查看系统日志: /var/log/messages
容器标准输出在宿主机的路径:
/var/lib/docker/containers/<container-id>/<container-id>-json.log
日志文件,进入到终端日志目录查看:
kubectl exec -it <pod名称> -- bash
12.k8s生命周期
1、使用Deployment控制器部署镜像 kubectl create deployment web --image=tomcat kubectl get deployment,pods 2、使用Service发布Pod kubectl expose deployment web --port=80 --type=NodePort --target-port=8080 --name=web kubectl get service
deployment一般用yaml文件部署
部署:kubectl apply -f xxx.yaml
卸载:kubectl delete -f xxx.yaml YAML语法格式: • 缩进表示层级关系 • 不支持制表符“tab”缩进,使用空格缩进 • 通常开头缩进 2 个空格 • 字符符号后缩进 1 个空格,如冒号、逗号等 •“---” 表示YAML格式,一个文件的开始 • “#”注释
• 用create命令生成 kubectl create deployment web2 --image=nginx --replicas=3 --dry-run=client -o yaml > deployment2.yaml kubectl expose deployment web2 --port=80 --target-port=80 --type=NodePort --dry-run=client -o yaml > service2.yaml • 用create命令生成 kubectl get deployment nginx -o yaml > my-deploy.yaml kubectl get deployment nginx -o json> my-deploy.yaml • Pod容器的字段拼写忘记了 kubectl explain pods.spec.containers kubectl explain deployment
13.deployment
Deployment是最常用的K8s工作负载控制器(Workload Controllers), 是K8s的一个抽象概念,用于更高级层次对象,部署和管理Pod。 其他控制器还有DaemonSet、StatefulSet等。
Deployment的主要功能:
• 管理Pod和ReplicaSet
• 具有上线部署、副本设定、滚动升级、回滚等功能
• 提供声明式更新,例如只更新一个新的Image
应用场景:网站、API、微服务
部署镜像: apiVersion: apps/v1 kind: Deployment metadata: name: web namespace: default spec: replicas: 3 # Pod副本预期数量 selector: matchLabels: app: web template: metadata: labels: app: web # Pod副本的标签 spec: containers: - name: web2 image: nginx:1.16 • kubectl apply -f xxx.yaml • kubectl create deployment web --image=nginx:1.16 --replicas=3
• kubectl get pods
java-demo-56d54df448-dmnn5
deployment名称-RS名称-随机名(因为会有多个副本)
应用升级(更新镜像三种方式,自动触发滚动升级) • kubectl apply -f xxx.yaml • kubectl set image deployment/web web2=nginx:1.17 • kubectl edit deployment/web #使用系统编辑器打开 滚动升级:K8s对Pod升级的默认策略,通过使用新版本.Pod逐步更新旧版本Pod,实现零停机发布,用户无感知。
ReplicaSet控制器用途:
• Pod副本数量管理,不断对比当前Pod数量与期望Pod数量
• Deployment每次发布都会创建一个RS作为记录,用于实现回滚
滚动升级 在K8s中的实现: • 1个Deployment • 2个ReplicaSet 第一次部署:3个副本 升级: 第一次扩容 将创建一个新的RS,副本数设置为1 第二次缩容 将旧的RS的副本数缩容为2 第三次扩容 将新的RS的副本数扩容为2 第四次缩容 将旧的RS的副本数缩容为1 第五次扩容 将新的RS的副本数扩容为3 第六次扩容 将旧的RS的副本数缩容为0 最后的结果,旧RS副本数为0,新RS副本数为3 一个RS维护了一个镜像版本。 水平扩缩容(启动多实例,提高并发) • 修改yaml里replicas值,再apply • kubectl scale deployment web --replicas=10 #replicas参数控制Pod副本数量 回滚(项目升级失败恢复到正常版本) #回滚是重新部署某一次部署时的状态,即当时版本所有配置 kubectl rollout history deployment/web # 查看历史发布版本 kubectl rollout undo deployment/web # 回滚上一个版本 kubectl rollout undo deployment/web --to-revision=2 # 回滚历史指定版本 $ kubectl get rs #查看RS记录 NAME DESIRED CURRENT READY AGE cgcnginx-865d746c47 1 1 1 5d22h web-6979f7f654 4 4 4 62m web-6d78cc8568 0 0 0 86m $ kubectl rollout history deploy web #版本对应RS记录 deployment.apps/web REVISION CHANGE-CAUSE 3 <none> 4 <none>$ kubectl describe rs web-6979f7f654 |grep revision deployment.kubernetes.io/revision: 4 deployment.kubernetes.io/revision-history: 2 项目下线: #不能直接删除pod 不然replicas会自动重新拉起到指定副本数 kubectl delete deploy/web kubectl delete svc/web
kubetcl delete -f xxx.yaml
14.pod
Pod是一个逻辑抽象概念,Kubernetes创建和管理的最小单元, 一个Pod由一个容器或多个容器组成。
Pod特点:• 一个Pod可以理解为是一个应用实例,提供服务 • Pod中容器始终部署在一个Node上 • Pod中容器共享网络、存储资源
Pod主要用法:
• 运行单个容器:最常见的用法,在这种情况下,可以将Pod看做是单 个容器的抽象封装
• 运行多个容器:边车模式(Sidecar) ,通过在Pod中定义专门容器, 来执行主业务容器需要的辅助工作,这样好处是将辅助功能同主业务 容器解耦,实现独立发布和能力重用。(日志收集、应用监控)
创建Pod.taml(共享网络): kubectl run bs --image=busybox --dry-run=client -o yaml > pod.yaml vi pod.yaml apiVersion: v1 kind: Pod metadata: name: my-pod labels: run: nginx spec: containers: # 主程序 - name: container1 image: nginx # 辅助程序(边车容器) - name: container2 image: busybox
command: ["/bin/sh","-c","sleep 12h"] 创建Pod: kubectl apply -f pod.yaml 或者使用命令:kubectl run nginx --image=nginx kubectl run busybox --image=busybox -- sleep 24h 查看Pod: kubectl get pods kubectl describe pod <Pod名称> 查看日志: kubectl logs <Pod名称> [-c CONTAINER] kubectl logs <Pod名称> [-c CONTAINER] -f 进入容器终端: kubectl exec <Pod名称> [-c CONTAINER] -- bash kubectl exec -it my-pod -c bs -- sh #进入bs,网络协议栈共享,打破net ns隔离,实际上除了nginx和bs外,还有pause镜像容器做网络共享 / # netstat -tlnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN - tcp 0 0 :::80 :::* LISTEN - 删除Pod: kubectl delete pod <Pod名称>
pause 负责Pod网络的容器镜像
创建Pod2.yaml(共享存储): vi pod2.yaml apiVersion: v1 kind: Pod metadata: labels: run: nginxpod name: pod-volume-web spec: containers: # 辅助程序(边车容器) - image: busybox name: bs command: ["/bin/sh","-c","sleep 12h"] volumeMounts: # 数据卷挂载 - name: log # 指定挂载的数据卷名称 mountPath: /data # 数据卷挂载到容器中的路径 映射到下面的log数据卷 # 主程序 - image: nginx name: webpod volumeMounts: - name: log mountPath: /usr/share/nginx/html #也是映射到下面的log数据卷 volumes: # 定义数据卷 - name: log # 数据卷名称,2个容器通过这个数据卷达到共享存储 emptyDir: {} # 数据卷类型
15.Pod对象:重启策略+健康检查(应用自修复)
重启策略(restartPolicy):
• Always:当容器终止退出后,总是重启容器,默认策略。 什么样的应用需要持续性运行?nginx、mysql、redis
• OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。 什么样的应用周期性运行?数据库备份、巡检
• Never:当容器终止退出,从不重启容器。 什么样的应用一次性运行(按需)?计算类的,数据离线处理
[root@k8s1 home]# kubectl get pods pod-web -o yaml | grep restart restartPolicy: Always restartCount: 1 restartCount: 0
健康检查有以下两种类型:
• livenessProbe(存活检查):如果检查失败,将杀死容器,根据Pod 的restartPolicy来操作。
• readinessProbe(就绪检查):如果检查失败,Kubernetes会把 Pod从service endpoints中剔除。
• startupProbe(启动检查):检查成功才由存活检查接手,用于保护 慢启动容器
支持以下三种检查方法:
• httpGet:发送HTTP请求,返回200-400范围状态码为成功。
• exec:执行Shell命令返回状态码是0为成功。
• tcpSocket:发起TCP Socket建立成功。
示例:端口探测 apiVersion: v1 kind: Pod metadata: name: probe-demo spec: containers: - name: web image: nginx ports: - containerPort: 80 livenessProbe: tcpSocket: port: 80 initialDelaySeconds: 30 #启动容器后多少秒健康检查 periodSeconds: 10 #以后每间隔多少秒检查一次 readinessProbe: tcpSocket: port: 80 initialDelaySeconds: 30 periodSeconds: 10 注:livenessProbe与readinessProbe的配置参数一样 示例:执行Shell命令 livenessProbe: exec: command: - cat - /tmp/healthy 示例:HTTP请求 #以下检查的链接 http://IP:8080/healthz livenessProbe: httpGet: path: /healthz port: 8080 httpHeaders: - name: Custom-Header value: Awesome
Pod环境变量
创建 Pod 时,可以为其下的容器设置环境变量。
应用场景:
• 容器内应用程序获取Pod信息
• 容器内应用程序通过用户定义的变量改变默认行为
变量值几种定义方式:
• 自定义变量值
• 变量值从Pod属性获取
• 变量值从Secret、ConfigMap获取
apiVersion: v1 kind: Pod metadata: name: pod-envars spec: containers: - name: test image: busybox command: [ "sh", "-c", "sleep 36000"] env: # 变量值从Pod属性获取 - name: MY_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: MY_POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: ABC # 自定义变量值 value: "123456"
Init Container:顾名思义,用于初始化工作,执行完就结束,可以理解为一次性任务。
• 支持大部分应用容器配置,但不支持健康检查
• 优先应用容器执行
应用场景:
• 环境检查:例如确保应用容器依赖的服务启动后再启动应用容器
• 初始化配置:例如给应用容器准备配置文件
边车容器与初始容器最大区别?
边车容器:持续运行
初始容器:工作完成后就退出,退出才启动应用容器
共同特点:都辅助应用容器工作。
示例:部署一个web网站,网站程序没有打到镜像中,而是希望从代码 仓库中动态拉取放到应用容器中。 apiVersion: v1 kind: Pod metadata: name: init-demo spec: initContainers: - name: download image: busybox command: - wget - "-O" - "/opt/index.html" - http://www.baidu.com volumeMounts: - name: wwwroot mountPath: "/opt" containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: - name: wwwroot mountPath: /usr/share/nginx/html volumes: - name: wwwroot emptyDir: {}
Pod中会有这几种类型的容器:
• Infrastructure Container:基础容器 , 维护整个Pod网络空间
• InitContainers:初始化容器, 先于业务容器开始执行
• Containers:业务容器 ,并行启动
静态Pod
静态Pod特点:
• Pod由特定节点上的kubelet管理
• 不能使用控制器
• Pod名称标识当前节点名称
在kubelet配置文件启用静态Pod的参数: vi /var/lib/kubelet/config.yaml ... staticPodPath: /etc/kubernetes/manifests ... 注:将部署的pod yaml放到该目录会由kubelet自动创建。
作者:陈耿聪 —— 夕狱
出处:https://www.cnblogs.com/CGCong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。