Kubernetes是谷歌以Borg为前身,基于谷歌15年生产环境经验的基础上开源的一个项目,Kubernetes致力于提供跨主机集群的自动部署、扩展、高可用以及运行应用程序容器的平台。html
k8s节点通常分为master节点和node节点,master节点通常三个足以,三个master节点承载成百上千node节点彻底没有问题,node节点能够横向扩容java
node节点用于部署应用程序,master节点不容许部署应用程序,它只负责控制,调度工做node
集群的控制中枢,各个模块之间信息交互都须要通过Kube-APIServer,同时它也是集群管理、资源配置、整个集群安全机制的入口。linux
集群的状态管理器,保证Pod或其余资源达到指望值,也是须要和APIServer进行通讯,在须要的时候建立、更新或删除它所管理的资源。nginx
集群的调度中心,它会根据指定的一系列条件,选择一个或一批最佳的节点,而后部署咱们的Pod。web
键值数据库,报错一些集群的信息,通常生产环境中建议部署三个以上节点(奇数个)。docker
master节点在安装完成以后,可能在很长一段时间都不会有任何的变化,因此在进行架设计的时候,要给足master节点资源,由于每次修改master节点是一件特别复杂的事情数据库
咱们在master节点绑定证书,每一个证书绑定在master节点的ip地址或者主机名,若是咱们在以前生成证书的时候没有预留的话,那咱们可能就须要从新生成一份证书,再把以前的证书都替换掉,并且还要替换node节点上面的证书,过程很是麻烦,因此一开始要给足资源,好比一次性给三台16核64Gvim
Etcd也特别重要,一次性给足资源,将来五到十年,node节点的个数在500到1000之间的话,咱们的master节点是彻底不须要作任何变化的后端
node节点和master节点的区别:node节点比较具备动态性,添加、删除
Kubelet:负责监听节点上Pod的状态,同时负责上报节点和节点上面Pod的状态,负责与Master节点通讯,并管理节点上面的Pod。
Kube-proxy:负责Pod之间的通讯和负载均衡,将指定的流量分发到后端正确的机器上。
[root@k8s-master01 dockerfiles]# netstat -lntp |grep kube-proxy tcp 0 0 0.0.0.0:30372 0.0.0.0:* LISTEN 1064/kube-proxy tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 1064/kube-proxy tcp6 0 0 :::10256 :::* LISTEN 1064/kube-proxy [root@k8s-master01 dockerfiles]# curl 127.0.0.1:10249/proxyMode ipvs[root@k8s-master01 dockerfiles]#
监听Master节点增长和删除service以及endpoint的消息,调用Netlink接口建立相应的IPVS规则。经过IPVS规则,将流量转发至相应的Pod上。
Ipvs映射规则
# 查看配置规则,主机访问30372端口就能够访问到172.25.244.214 [root@k8s-master01 ~]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.17.0.1:30372 rr -> 172.25.244.214:8443 Masq 1 0 0 # kubernetes-dashboard经过端口30372(kube-proxy)映射出去 [root@k8s-master01 dockerfiles]# kubectl get svc -n kubernetes-dashboard NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dashboard-metrics-scraper ClusterIP 10.109.161.186 <none> 8000/TCP 6d22h kubernetes-dashboard NodePort 10.96.188.229 <none> 443:30372/TCP 6d22h # 172.25.244.214正好时pod的ip地址 [root@k8s-master01 ~]# kubectl get po -n kubernetes-dashboard -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES dashboard-metrics-scraper-856586f554-ssjhm 1/1 Running 0 7d20h 172.18.195.8 k8s-master03 <none> <none> kubernetes-dashboard-67484c44f6-brz2z 1/1 Running 2 (3m56s ago) 7d20h 172.25.244.214 k8s-master01 <none> <none>
主机访问node节点30372端口,经过ipvs规则,反向代理到kubernetes-dashboard上面的ip地址172.25.244.214的8443端口,因此就能访问到dashboard
监听Master节点增长和删除service以及endpoint的消息,对于每个Service,他都会建立一个iptables规则,将service的clusterIP代理到后端对应的Pod。
不推荐使用Iptables的缘由是:当咱们的规则特别多的时候,它的性能就会急剧降低
Calico:符合CNI标准的网络插件,给每一个Pod生成一个惟一的IP地址,而且把每一个节点当作一个路由器。Cilium,eBPF
CoreDNS:用于Kubernetes集群内部Service的解析,可让Pod把Service名称解析成IP地址,而后经过Service的IP地址进行链接到对应的应用上。
Docker:容器引擎,负责对容器的管理。
Pod是Kubernetes中最小的单元,它由一组、一个或多个容器组成,每一个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,经过Pause容器可使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。
查看系统pod
[root@k8s-master01 ~]# kubectl get po -n kube-system NAME READY STATUS RESTARTS AGE metrics-server-64c6c494dc-lhkl2 1/1 Running 1 (82m ago) 87m
Pause容器
[root@k8s-master01 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b30c03e6e0ff 9759a41ccdf0 "/metrics-server --c…" About an hour ago Up About an hour k8s_metrics-server_metrics-server-64c6c494dc-lhkl2_kube-system_517b9ab1-a323-4530-8be4-ebd3a7d41de4_1 f45e50c4009e registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.2 "/pause" About an hour ago Up About an hour k8s_POD_metrics-server-64c6c494dc-lhkl2_kube-system_517b9ab1-a323-4530-8be4-ebd3a7d41de4_1
由于一个应用不可能单个容器就能支撑的,须要不少微服务支撑,可能出现一种状况就是两个服务,A服务和B服务之间须要网络互通,延迟很是小,并且两个服务有数据的依赖性,服务B须要用到服务A产生的文件,若是直接用k8s裸机的话,服务A和服务B不必定会在同一台宿主机上,当副本数很是大的时候,很难保证两个文件能够共享一个目录
每一个pod有一个惟一的ip地址,便于管理
从k8s的角度看,它做为一个很是流行的编排工具,须要兼容不少的容器技术,因此经过pod管理不一样的符合该标准的容器,而没有直接操做容器
其余容器技术:https://kubernetes.io/docs/setup/production-environment/container-runtimes/
[root@k8s-master01 ~]# vim pod.yaml :set paste # 添加如下内容 apiVersion: v1 # 必选,API的版本号 kind: Pod # 必选,类型Pod metadata: # 必选,元数据 name: nginx # 必选,符合RFC 1035规范的Pod名称 # namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可使用-n 指定namespace labels: # 可选,标签选择器,通常用于过滤和区分Pod app: nginx role: frontend # 能够写多个 annotations: # 可选,注释列表,能够写多个 app: nginx spec: # 必选,用于定义容器的详细信息 # initContainers: # 初始化容器,在容器启动以前执行的一些初始化操做 # - command: # - sh # - -c # - echo "I am InitContainer for init some configuration" # image: busybox # imagePullPolicy: IfNotPresent # name: init-container containers: # 必选,容器列表 - name: nginx # 必选,符合RFC 1035规范的容器名称 image: nginx:latest # 必选,容器所用的镜像的地址 imagePullPolicy: IfNotPresent # 可选,镜像拉取策略,IfNotPresent:若是宿主机又这个镜像,那就不须要拉取,Always:老是拉取,Never:不论是否存储都不拉取 command: # 可选,容器启动执行的命令 ENTRYPOINT,arg --> cmd - nginx - -g - "daemon off;" workingDir: /usr/share/nginx/html # 可选,容器的工做目录 # volumeMounts: # 可选,存储卷配置,能够配置多个 # - name: webroot # 存储卷名称 # mountPath: /usr/share/nginx/html # 挂载目录 # readOnly: true # 只读 ports: # 可选,容器须要暴露的端口号列表 - name: http # 端口名称 containerPort: 80 # 端口号 protocol: TCP # 端口协议,默认TCP env: # 可选,环境变量配置列表 - name: TZ # 变量名 value: Asia/Shanghai # 变量的值 - name: LANG value: en_US.utf8 # resources: # 可选,资源限制和资源请求限制 # limits: # 最大限制设置 # cpu: 1000m # memory: 1024Mi # requests: # 启动所需的资源 # cpu: 100m # memory: 512Mi # startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。 # httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 # path: /api/successStart # 检查路径 # port: 80 # readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。 # httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 # path: / # 检查路径 # port: 80 # 监控端口 # livenessProbe: # 可选,健康检查 #exec: # 执行容器命令检测方式 #command: #- cat #- /health #httpGet: # httpGet检测方式 # path: /_health # 检查路径 # port: 8080 # httpHeaders: # 检查的请求头 # - name: end-user # value: Jason # tcpSocket: # 端口检测方式 # port: 80 # initialDelaySeconds: 60 # 初始化时间 # timeoutSeconds: 2 # 超时时间 # periodSeconds: 5 # 检测间隔 # successThreshold: 1 # 检查成功为2次表示就绪 # failureThreshold: 2 # 检测失败1次表示未就绪 # lifecycle: # postStart: # 容器建立完成后执行的指令, 能够是exec httpGet TCPSocket # exec: # command: # - sh # - -c # - 'mkdir /data/ ' # preStop: # httpGet: # path: / # port: 80 # exec: # command: # - sh # - -c # - sleep 9 restartPolicy: Always # 可选,默认为Always,容器故障或者没有启动成功,那就自动重启该容器,Onfailure:容器以不为0的状态终止,Never:不管何种状态,都不会重启 #nodeSelector: # 可选,指定Node节点 # region: subnet7 # imagePullSecrets: # 可选,拉取镜像使用的secret,能够配置多个 # - name: default-dockercfg-86258 # hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口 # volumes: # 共享存储卷列表 # - name: webroot # 名称,与上述对应 # emptyDir: {} # 挂载目录 #hostPath: # 挂载本机目录 # path: /etc/hosts
建立pod
[root@k8s-master01 ~]# kubectl create -f pod.yaml pod/nginx created
查看pod
[root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 3m51s
查看labels
[root@k8s-master01 ~]# kubectl get po --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 3m57s app=nginx,role=frontend
label与yaml文件中的配置一致
labels: # 可选,标签选择器,通常用于过滤和区分Pod app: nginx role: frontend # 能够写多个
删除pod
[root@k8s-master01 ~]# kubectl delete po nginx pod "nginx" deleted
查看pod
[root@k8s-master01 ~]# kubectl get po No resources found in default namespace.
删除以后就找不到pod了,因此生产环境中通常不会直接使用,很难保证业务正常运行,通常使用高级资源deployment,daemonset,StatefulSets
StartupProbe:k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动。若是配置了startupProbe,就会先禁止其余的探测,直到它成功为止,成功后将不在进行探测。
# startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。 # httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 # path: /api/successStart # 检查路径 # port: 80
LivenessProbe:用于探测容器是否运行,若是探测失败,kubelet会根据配置的重启策略进行相应的处理。若没有配置该探针,默认就是success。
# livenessProbe: # 可选,健康检查 #exec: # 执行容器命令检测方式 #command: #- cat #- /health
ReadinessProbe:通常用于探测容器内的程序是否健康,它的返回值若是为success,那么久表明这个容器已经完成启动,而且程序已是能够接受流量的状态。
# readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。 # httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 # path: / # 检查路径 # port: 80 # 监控端口
ExecAction:在容器内执行一个命令,若是返回值为0,则认为容器健康。
# livenessProbe: # 可选,健康检查 #exec: # 执行容器命令检测方式 #command: #- cat #- /health
TCPSocketAction:经过TCP链接检查容器内的端口是不是通的,若是是通的就认为容器健康。
HTTPGetAction:经过应用程序暴露的API地址来检查程序是不是正常的,若是状态码为200~400之间,则认为容器健康。
生产环境推荐使用HTTPGetAction
查看coredns的deployment文件
[root@k8s-master01 ~]# kubectl edit deployment coredns -n kube-system
查找livenessProbe
livenessProbe: failureThreshold: 5 httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5
它请求了8080端口的/health,若是检测成功,则容器不会被重启
查找readinessProbe
readinessProbe: failureThreshold: 3 httpGet: path: /ready port: 8181 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1
它请求了8181端口的/ready,若是检测成功,则能够加上endpoint,开始接受流量,开始工做
探针检查参数配置
# initialDelaySeconds: 60 # 初始化时间 # timeoutSeconds: 2 # 超时时间 # periodSeconds: 5 # 检测间隔 # successThreshold: 1 # 检查成功为1次表示就绪 # failureThreshold: 2 # 检测失败2次表示未就绪
为何要引入StartupProbe?
若是容器启动特别慢,单独配置一个StartupProbe,它会先禁用另外两个探针,直到程序启动完成,再检测它的状态
编辑pod.yaml,取消注释
[root@k8s-master01 ~]# vim pod.yaml startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。 httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 path: /api/successStart # 检查路径 port: 80
启动容器
修改pod.yaml
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 # path: /api/successStart # 检查路径 # port: 80 tcpSocket: port: 80
构建容器
[root@k8s-master01 ~]# kubectl create -f pod.yaml pod/nginx created
获取IP
[root@k8s-master01 ~]# kubectl get po -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx 1/1 Running 0 2m31s 172.25.244.217 k8s-master01 <none> <none>
访问nginx
[root@k8s-master01 ~]# curl 172.25.244.217 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
编辑pod.yaml
[root@k8s-master01 ~]# vim pod.yaml # 修改内容以下 env: # 可选,环境变量配置列表 - name: TZ # 变量名 value: Asia/Shanghai # 变量的值 - name: LANG value: en_US.utf8 readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。 httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 path: / # 检查路径 port: 80 # 监控端口 livenessProbe: # 可选,健康检查 exec: # 执行容器命令检测方式 command: - pgrep nginx initialDelaySeconds: 3 # 初始化时间 timeoutSeconds: 2 # 超时时间 periodSeconds: 2 # 检测间隔 successThreshold: 1 # 检查成功为2次表示就绪 failureThreshold: 1 # 检测失败1次表示未就绪
建立pod
[root@k8s-master01 ~]# kubectl delete po nginx pod "nginx" deleted [root@k8s-master01 ~]# kubectl create -f pod.yaml pod/nginx created
查看pod
[root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 4s [root@k8s-master01 ~]# kubectl describe po nginx Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 10s default-scheduler Successfully assigned default/nginx to k8s-master01 Warning Unhealthy 2s (x2 over 6s) kubelet Liveness probe failed: OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "pgrep nginx": executable file not found in $PATH: unknown Normal Pulled 1s (x3 over 9s) kubelet Container image "nginx:latest" already present on machine Normal Created 1s (x3 over 9s) kubelet Created container nginx Normal Started 1s (x3 over 9s) kubelet Started container nginx Normal Killing 1s (x2 over 5s) kubelet Container nginx failed liveness probe, will be restarted
能够看到若是exec的命令不存在会报错Liveness probe failed
修改exec命令为ls
exec: # 执行容器命令检测方式 command: - ls
从新建立
[root@k8s-master01 ~]# kubectl delete po nginx pod "nginx" deleted [root@k8s-master01 ~]# kubectl create -f pod.yaml pod/nginx created [root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 4s [root@k8s-master01 ~]# kubectl describe po nginx Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 8s default-scheduler Successfully assigned default/nginx to k8s-master01 Normal Pulled 7s kubelet Container image "nginx:latest" already present on machine Normal Created 7s kubelet Created container nginx Normal Started 7s kubelet Started container nginx
能够看到健康检查经过
Liveness和Readiness推荐使用接口级健康检查,参考 coredns
[root@k8s-master01 ~]# kubectl edit deploy coredns -n kube-system /live 回车 livenessProbe: failureThreshold: 5 httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 /read 回车 readinessProbe: failureThreshold: 3 httpGet: path: /ready port: 8181 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1
能够看到 coredns 的 livenessProbe 请求了一个 /health 的接口,readinessProbe 请求了一个 /ready 的接口
用户执行删除操做:kubectl delete po nginx
Pod变成Terminating以后有一个宽限期,让咱们作一些清理的动做,或者后置的动做
[root@k8s-master01 ~]# kubectl edit deploy coredns -n kube-system /terminationGracePeriodSeconds 回车 terminationGracePeriodSeconds: 30
Prestop:先去请求eureka接口,把本身的IP地址和端口号,进行下线,eureka从注册表中删除该应用的IP地址。而后容器进行sleep 90;kill pgrep java
若是sleep时间过长,须要修改terminationGracePeriodSeconds
[root@k8s-master01 ~]# vim pod.yaml # 修改如下内容 # readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。 # httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。 # path: / # 检查路径 # port: 80 # 监控端口 # livenessProbe: # 可选,健康检查 # exec: # 执行容器命令检测方式 # command: # - ls # initialDelaySeconds: 3 # 初始化时间 # timeoutSeconds: 2 # 超时时间 # periodSeconds: 2 # 检测间隔 # successThreshold: 1 # 检查成功为2次表示就绪 # failureThreshold: 1 # 检测失败1次表示未就绪 lifecycle: # postStart: # 容器建立完成后执行的指令, 能够是exec httpGet TCPSocket # exec: # command: # - sh # - -c # - 'mkdir /data/ ' preStop: # httpGet: # path: / # port: 80 exec: command: - sh - -c - sleep 90
建立pod
[root@k8s-master01 ~]# kubectl delete po nginx pod "nginx" deleted [root@k8s-master01 ~]# kubectl create -f pod.yaml pod/nginx created [root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 28s
查看pod退出时间
[root@k8s-master01 ~]# time kubectl delete po nginx pod "nginx" deleted real 0m40.249s user 0m0.038s sys 0m0.019s
能够看到只执行了40s,并无sleep 90s,因此咱们须要配置terminationGracePeriodSeconds
设置 terminationGracePeriodSeconds
[root@k8s-master01 ~]# vim pod.yaml # 修改如下内容 terminationGracePeriodSeconds: 50 containers: # 必选,容器列表
建立pod
[root@k8s-master01 ~]# kubectl create -f pod.yaml pod/nginx created [root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 28s
查看pod退出时间
[root@k8s-master01 ~]# time kubectl delete po nginx pod "nginx" deleted real 0m51.427s user 0m0.031s sys 0m0.017s
能够看到退出时间延长了,可是也没有真正的执行sleep 90s,因此配置的时候须要注意一下,由于k8s并不知道你执行了什么操做,没法判断PreStop的执行时间,因此会强制性的删除
本做品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、从新发布,但务必保留文章署名 郑子铭 (包含连接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的做品务必以相同的许可发布。