Kubernetes权威指南一
一、Kubernetes入门
1.1了解kubernetes
在每个Pod中都运行着一个特殊的被称为Pause的容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和Volume挂载卷,因此他们之间的通信和数据交换更为高校,在设计时候我们可以充分利用这一特性将一组密切相关的服务进程放入同一个Pod中。
在集群管理方面,Kubernetes将集群分为一些Master节点,和一些Node节点,Master节点上部署了kube-apiservice,kube-conller-manager,kube-scheduler管理进程,这些进程实现了集群的资源管理,Pod调度,弹性伸缩,安全控制,系统监控和纠错等管理功能,并都是自动完成的。Node节点作为集群的工作节点,其上运行着真正的应用程序。在Node上,Kubernetes运行的最小单元是Pod。在Node节点上运行着kubelet、kube-proxy,这些服务进程负责Pod的创建,启动,监控,销毁,以及实现软件模式的负载均衡。
通过一个实例来理解Kuberentes
创建一个Deployment:
apiVersion: apps/v1 kind: Deployment metadata: labels: app: mysql name: mysql spec: replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - image: mysql:5.7 name: mysql ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: "123456"
创建一个Service
apiVersion: v1 kind: Service metadata: name: mysql spec: ports: - port: 3306 selector: app: mysql
创建一个Tomcate应用,最后的value为mysql Service的ClusterIP
apiVersion: apps/v1 kind: Deployment metadata: name: myweb labels: app: myweb spec: replicas: 2 selector: matchLabels: app: myweb template: metadata: labels: app: myweb spec: containers: - image: tomcat-app:v1 name: myweb ports: - containerPort: 8080 env: - name: MYSQL_SERVICE_HOST value: 10.103.76.207
创建web的service
apiVersion: v1 kind: Service metadata: name: myweb spec: type: NodePort ports: - port: 8080 nodePort: 30001 selector: app: myweb
1.4、Kubernetes基础概念
namespace的创建
apiVersion: v1
kind: Namespace
metadata:
name: develoyment
通过文件创建以后,namespace就永久存在了。
1.4.3 应用类
Kubernetes 里的 Service 具有一个全局唯 的虚拟 ClusterIP 地址 Service 一旦被创建, Kubernetes 就会 动为它分配一个可用的 lusterIP 地址,而且在 Service 整个生命周期中,它的 lusterIP 地址都不会改变。
- 为多进程之间的协作提供 个抽象模型,使用 Pod 作为基本的调度 复制等管理工作的最小单位,让多个应用进程能一起有效地调度和伸缩。
- Pod 里的 多个业务容器共享 Pause 容器的 IP, 共享 Pause 容器挂接的 Vo lume,样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。
Endpoints Controller就是负责生成和维护所有Endpoints对象的控制器,它负责监听Service和对应的Pod副本的变化。如果检测到Service被删除,则删除和该Service同名的Endpoints对象。如果检测到新的Service被创建或者修改则根据该Service信息获得相关的Pod列表,然后创建或者更新Service对应的Endpoints对象。
[root@master01 mysql]# kubectl get replicaset NAME DESIRED CURRENT READY AGE mysql-557fd4547d 1 1 1 88m myweb-c49f967d8 2 2 2 56m [root@master01 mysql]# kubectl get pod NAME READY STATUS RESTARTS AGE mysql-557fd4547d-m29k6 1/1 Running 0 93m myweb-c49f967d8-4h7d8 1/1 Running 0 61m myweb-c49f967d8-6vggh 1/1 Running 0 61m
Pod、Service、Deployment的逻辑关系:
Kubernets的Service定义了一组入口访问地址,前端的应用通过这个地址访问其背后的一组由Pod副本组成的集群实例,Service与后端的Pod的集群是有Label Selector无缝对接的,Deployment是保证Service的服务能力和服务质量,始终符合预期的标准。
apiVersion: v1 kind: Service metadata: name: testservice spec: clusterIP: 10.96.85.70 ports: - port: 8080 protocol: TCP targetPort: 8080 selector: tier: frontend type: ClusterIP status: loadBalancer: {}
各种port的理解
https://www.cnblogs.com/devilwind/p/8881201.html
nodePort: 集群外部地址访问集群Service的时候用的端口,比如外部用户要访问k8s集群中的一个Web应用,那么我们可以配置对应service的type=NodePort,nodePort=30001。其他用户就可以通过浏览器http://node:30001访问到该web服务。
port:是暴露在cluster ip上的端口,:port提供了集群内部客户端访问service的入口,即clusterIP:port。 mysql容器暴露了3306端口,集群内其他容器通过33306端口访问mysql服务,但是外部流量不能访问mysql服务,因为mysql服务没有配置NodePort。
targetPort:是pod上的端口,从port/nodePort上来的数据,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
containerPort:是在pod控制器中定义的、pod中的容器需要暴露的端口。
总的来说,port和nodePort都是service的端口,前者暴露给k8s集群内部服务访问,后者暴露给k8s集群外部流量访问。从这两个端口到来的数据都需要经过反向代理kube-proxy,流入后端pod的targetPort上,最后到达pod内容器的containerPort
ConfigMap典型用法:
生成容器内的环境变量;
设置容器启动命令的启动参数;
以Volume的形式挂载为容器内部的文件或者目录;
创建一个configMap testconfig.yaml
apiVersion: v1 kind: ConfigMap metadata: name: config-test data: apploglevel: info appdatadir: /var/data
执行kubectl create -f testconfig.yaml 命令创建
第二种方法:直接通过命令 kubectl create configmap testconfig.yaml --from-file=server.xml
通过 --from-file参数在目录下进行创建,该目录的每个配置文件名都被设置为key,文件的内容被设置为 value 语法如下:
kubectl create configmap NAME --from-file=config-files-dir
使用 --from-literal 会从文本中进创建, 直接将指定的 key#=value #创建为ConfigMap内容,如下
kubectl create configmap NAME --from-literal=keyl=valuel --from-literal=key2=value2
容器对ConfigMap的用法有以下两种方法:
(1)通过环境变量获取ConfigMap中的内容;
(2)通过Volume挂载的方法,将ConfigMap中的内容挂载为容器内部的文件或者目录。
创建一个ConfigMap
apiVersion: v1 kind: ConfigMap metadata: name: test-config data: apploglevel: info appdatadir: /var/data
[root@master01 configmap]# kubectl create -f conf.yaml
创建pod引用ConfigMap
apiVersion: v1 kind: Pod metadata: name: con-test spec: containers: - name: mappod image: busybox command: ["/bin/sh","-c","env|grep APP"] env: - name: APPLOGLEVEL valueFrom: configMapKeyRef: name: test-config key: apploglevel - name: APPDATADIR valueFrom: configMapKeyRef: name: test-config key: appdatadir restartPolicy: Never
[root@master01 configmap]# kubectl create -f pod.yaml
查看日志:
[root@master01 configmap]# kubectl logs con-test
Secret
保存敏感信息。
HPA
Horizontal Pod Autoscaler 自动实现pod的自动扩容缩容。
Volume
Volume是能够被多个容器访问的共享目录。
emptyDir
一个emptyDri是pod分配到Node上创建的,当Pod从Node上移除时候,目录就会自动删除;用途如下:
临时空间,无需长时间保留;
长时间任务执行过程中使用的临时目录;
一个容器需要从另外一个容器获取数据的目录;
hostPath
在应用容器上生成的日志文件需要长期保存时候,
需要访问Docker内部数据时候
动态存储管理:
Persistetn Volume(PV);
二、Pod
apiVersion: v1 kind: Pod metadata: name: volume-pod spec: containers: - name: tomcat image: tomcat ports: - containerPort: 8080 volumeMounts: - name: app-logs mountPath: /usr/local/tomcat/logs - name: buhbux image: busybox command: ["sh", "-c", "tail -f /logs/catalina*.log"] volumeMounts: - name: app-logs mountPath: /logs volumes: - name: app-logs emptyDir: {}
pod的生命周期和重启策略
Pod的重启策略包括Always,OnFailure、Never
Pod的健康检查
LivenessProbe用户判断容器是否存活(Running),如果LivenessProbe探针判断容器的状态不健康,则kubelet将杀掉该容器,并根据响应的重启策略重启改容器,如果一个容器的探针不包含LivenessProbe,则kubelet则认为该容器的LivenessProbe的返回值永远是Successful。
ReadinessProbe用户判断容器状态是否为(Ready)达到Ready的状态的Pod才能够接收请求,如果运行状态不是为Ready,自系统自动将其从EndPoint的列表中隔离出去,后续在把恢复到Ready状态的EndPoint加入到列表中,这样保证访问service的时候不会被转发到不可用的Pod上来。
StartupProbe:某些应用会遇到启动比较慢的情况,可以通过StartupProbe探针解决。
apiVersion: v1 kind: Pod metadata: name: liveness labels: test: liveness spec: containers: - name: livenessdock image: busybox args: - /bin/bash - -c - echo ok > /tmp/health; sleep 10; rm -rf /tmp/health; sleep 600; livenessProbe: exec: command: - cat - /tmp/health initialDelaySeconds: 15 timeoutSeconds: 1
通过检测端口来判断容器的状态
apiVersion: v1 kind: Pod metadata: name: tcp labels: test: tcp spec: containers: - name: liveness image: nginx ports: - containerPort: 80 livenessProbe: tcpSocket: port: 80 initialDelaySeconds:30 timeoutSeconds: 1
HTTPGetAction: 通过容器的 IP地址端口号及路径调用 HTTPGet法,如果响应的状态码大千等于 200 且小于 400, 则认为容器健康。
apiVersion: v1 kind: Pod metadata: name: httpget labels: test: httpget spec: containers: - name: httget image: nginx ports: - containerPort: 80 livenessProbe: httpGet: path: /_status/healthz port: 80 initialDelaySecond: 30 timeoutSeconds: 1
initialDelaySeconds: 启动容器后进行首次健康检查的 等待时间,单位为s
timeoutSeconds 健康检查发送请求后等待响应的超时时间,单位为 。当超时发生时, kubele会认为容器已经无法提供服务,将会重启该容器。
apiVersion: apps/v1 kind: Deployment metadata: name: deploy01 spec: selector: matchLabels: app: nginxtest replicas: 3 template: metadata: labels: app: nginxtest spec: containers: - name: nginxtest image: nginx ports: - containerPort: 80
NodeSelector定向调度
先给node打标签:
[root@master01 deploy]# kubectl label nodes work01 zone=north
在Deployment中加入节点的标签
NodeSelector:
zone: north
NodeAffinity节点亲和性调度:
IgnoredDuringExecution:表示如果Pod运行中,Labels发生变化,Pod可以继续运行。
apiVersion: apps/v1 kind: Deployment metadata: name: deploy spec: apiVersion: v1 kind: Pod metadata: name: affinity-test spec: containers: - name: aff-test image: pause affinity: nodeAffinity requiredDruingSchedulingIgnoredDruingExecution: nodeSelectorTerms: - matchExpressions - key: beta.kubernetes.io/arch operator: In values: -amd64 preferredDuringSchedulingIgnoreDruingExection: - weight: 1 preference: matchExpressions: - key: disk-type operator: In values: - ssd
如果 nodeAffinity 指定了多个 nodeSelectorTerms, 那么其中一个能匹配成功即可;
如果在 nodeSelectorTerms 中有多个 matchExpressioos, 则一个节点必须满足所有matchExpressions 才能运行该 Pod
kubectl taint nodes work1 key=value:NoSchedule
tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule"
Pod Priority Preemption :Pod 优先级调度
apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-cloud-logging namespace: kube-system labels: k8s-app: fluentd-cloud-logging spec: selector: matchLabels: k8s-app: fluentd-cloud-logging template: metadata: namespace: kube-system labels: k8s-app: fluentd-cloud-logging spec: containers: - name: fluentd-cloud-logging image: gcr.io/google_containers/fluentd-elasticsearch:1.17 resources: limits: cpu: 100m memory: 200Mi env: - name: FLUENTD_ARGS value: -q volumeMounts: - name: varlog mountPath: /var/log readOnly: false - name: containers mountPath: /var/lib/docker/containers readOnly: false volumes: - name: containers hostPath: path: /var/lib/docker/containers - name: varlog hostPath: path: /var/log
CronJob:
apiVersion: batch/v1 kind: CronJob metadata: name: hello spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: hello image: busybox args: - /bin/sh - -c - date; echo Hello from the Kubernetes cluster restartPolicy: OnFailure
Init Container初始化容器
apiVersion: v1 kind: Pod metadata: name: ngi namespace: default spec: initContainers: - name: install image: busybox command: - wget - "-O" - "/work-dir/index.html" - http://kubernetes.io volumeMounts: - name: workdir mountPath: "/work-dir" containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: - name: workdir mountPath: /usr/share/nginx/html dnsPolicy: Default volumes: - name: workdir emptyDir: {}
[root@master01 initCont]# kubectl get pod -owide
[root@master01 initCont]# curl https://10.244.75.124:80/index.html